From a6ae35ba912465cc39b058e86446f244710bbc40 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sat, 8 May 2021 20:59:55 +0000 Subject: [PATCH 1/4] Issue #1751 -- Remove cocoa support code from /dom --- dom/gamepad/cocoa/CocoaGamepad.cpp | 590 ------------------ dom/gamepad/moz.build | 4 - dom/geolocation/moz.build | 4 - dom/media/standalone/moz.build | 3 - .../systemservices/OSXRunLoopSingleton.cpp | 44 -- .../systemservices/OSXRunLoopSingleton.h | 25 - dom/media/systemservices/moz.build | 4 - .../cocoa/OSXSpeechSynthesizerModule.cpp | 56 -- .../synth/cocoa/OSXSpeechSynthesizerService.h | 43 -- .../cocoa/OSXSpeechSynthesizerService.mm | 498 --------------- dom/media/webspeech/synth/cocoa/moz.build | 11 - dom/media/webspeech/synth/moz.build | 3 - dom/moz.build | 2 +- dom/plugins/base/moz.build | 6 - dom/plugins/base/nsPluginsDirDarwin.cpp | 572 ----------------- dom/system/mac/CoreLocationLocationProvider.h | 59 -- .../mac/CoreLocationLocationProvider.mm | 268 -------- dom/system/mac/moz.build | 14 - dom/system/moz.build | 2 - dom/xbl/builtin/mac/jar.mn | 6 - dom/xbl/builtin/mac/moz.build | 6 - dom/xbl/builtin/mac/platformHTMLBindings.xml | 72 --- dom/xbl/builtin/moz.build | 2 - 23 files changed, 1 insertion(+), 2293 deletions(-) delete mode 100644 dom/gamepad/cocoa/CocoaGamepad.cpp delete mode 100644 dom/media/systemservices/OSXRunLoopSingleton.cpp delete mode 100644 dom/media/systemservices/OSXRunLoopSingleton.h delete mode 100644 dom/media/webspeech/synth/cocoa/OSXSpeechSynthesizerModule.cpp delete mode 100644 dom/media/webspeech/synth/cocoa/OSXSpeechSynthesizerService.h delete mode 100644 dom/media/webspeech/synth/cocoa/OSXSpeechSynthesizerService.mm delete mode 100644 dom/media/webspeech/synth/cocoa/moz.build delete mode 100644 dom/plugins/base/nsPluginsDirDarwin.cpp delete mode 100644 dom/system/mac/CoreLocationLocationProvider.h delete mode 100644 dom/system/mac/CoreLocationLocationProvider.mm delete mode 100644 dom/system/mac/moz.build delete mode 100644 dom/xbl/builtin/mac/jar.mn delete mode 100644 dom/xbl/builtin/mac/moz.build delete mode 100644 dom/xbl/builtin/mac/platformHTMLBindings.xml diff --git a/dom/gamepad/cocoa/CocoaGamepad.cpp b/dom/gamepad/cocoa/CocoaGamepad.cpp deleted file mode 100644 index eb6eda9a17..0000000000 --- a/dom/gamepad/cocoa/CocoaGamepad.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -// mostly derived from the Allegro source code at: -// http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.9/src/macosx/hidjoy.m?revision=13760&view=markup - -#include "mozilla/dom/Gamepad.h" -#include "mozilla/dom/GamepadPlatformService.h" -#include "mozilla/ArrayUtils.h" -#include "mozilla/Unused.h" -#include "nsThreadUtils.h" -#include -#include -#include -#include - -#include -#include - -namespace { - -using namespace mozilla; -using namespace mozilla::dom; -using std::vector; - -struct Button { - int id; - bool analog; - IOHIDElementRef element; - CFIndex min; - CFIndex max; - - Button(int aId, IOHIDElementRef aElement, CFIndex aMin, CFIndex aMax) : - id(aId), - analog((aMax - aMin) > 1), - element(aElement), - min(aMin), - max(aMax) {} -}; - -struct Axis { - int id; - IOHIDElementRef element; - uint32_t usagePage; - uint32_t usage; - CFIndex min; - CFIndex max; -}; - -typedef bool dpad_buttons[4]; - -// These values can be found in the USB HID Usage Tables: -// http://www.usb.org/developers/hidpage -const unsigned kDesktopUsagePage = 0x01; -const unsigned kSimUsagePage = 0x02; -const unsigned kAcceleratorUsage = 0xC4; -const unsigned kBrakeUsage = 0xC5; -const unsigned kJoystickUsage = 0x04; -const unsigned kGamepadUsage = 0x05; -const unsigned kAxisUsageMin = 0x30; -const unsigned kAxisUsageMax = 0x35; -const unsigned kDpadUsage = 0x39; -const unsigned kButtonUsagePage = 0x09; -const unsigned kConsumerPage = 0x0C; -const unsigned kHomeUsage = 0x223; -const unsigned kBackUsage = 0x224; - - -class Gamepad { - private: - IOHIDDeviceRef mDevice; - nsTArray - - diff --git a/widget/cocoa/crashtests/403296-1.xhtml b/widget/cocoa/crashtests/403296-1.xhtml deleted file mode 100644 index 800eaa3558..0000000000 --- a/widget/cocoa/crashtests/403296-1.xhtml +++ /dev/null @@ -1,10 +0,0 @@ - - -xxx -yyy - -300 diff --git a/widget/cocoa/crashtests/419737-1.html b/widget/cocoa/crashtests/419737-1.html deleted file mode 100644 index fe6e4532b4..0000000000 --- a/widget/cocoa/crashtests/419737-1.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -
- - diff --git a/widget/cocoa/crashtests/435223-1.html b/widget/cocoa/crashtests/435223-1.html deleted file mode 100644 index 1bbc27ba01..0000000000 --- a/widget/cocoa/crashtests/435223-1.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - -
- - diff --git a/widget/cocoa/crashtests/444260-1.xul b/widget/cocoa/crashtests/444260-1.xul deleted file mode 100644 index f1a84023df..0000000000 --- a/widget/cocoa/crashtests/444260-1.xul +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/widget/cocoa/crashtests/444864-1.html b/widget/cocoa/crashtests/444864-1.html deleted file mode 100644 index f8bac76e6a..0000000000 --- a/widget/cocoa/crashtests/444864-1.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -
- - diff --git a/widget/cocoa/crashtests/449111-1.html b/widget/cocoa/crashtests/449111-1.html deleted file mode 100644 index 4494591803..0000000000 --- a/widget/cocoa/crashtests/449111-1.html +++ /dev/null @@ -1,4 +0,0 @@ - - -
- diff --git a/widget/cocoa/crashtests/460349-1.xhtml b/widget/cocoa/crashtests/460349-1.xhtml deleted file mode 100644 index cc9b9700c7..0000000000 --- a/widget/cocoa/crashtests/460349-1.xhtml +++ /dev/null @@ -1,4 +0,0 @@ - - -
- diff --git a/widget/cocoa/crashtests/460387-1.html b/widget/cocoa/crashtests/460387-1.html deleted file mode 100644 index cab7e7eb32..0000000000 --- a/widget/cocoa/crashtests/460387-1.html +++ /dev/null @@ -1,2 +0,0 @@ - -
diff --git a/widget/cocoa/crashtests/464589-1.html b/widget/cocoa/crashtests/464589-1.html deleted file mode 100644 index d25d92315d..0000000000 --- a/widget/cocoa/crashtests/464589-1.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/widget/cocoa/crashtests/crashtests.list b/widget/cocoa/crashtests/crashtests.list deleted file mode 100644 index b65fe01394..0000000000 --- a/widget/cocoa/crashtests/crashtests.list +++ /dev/null @@ -1,11 +0,0 @@ -skip-if(!cocoaWidget) load 373122-1.html # bug 1300017 -load 397209-1.html -load 403296-1.xhtml -load 419737-1.html -load 435223-1.html -load 444260-1.xul -load 444864-1.html -load 449111-1.html -load 460349-1.xhtml -load 460387-1.html -load 464589-1.html diff --git a/widget/cocoa/cursors/arrowN.png b/widget/cocoa/cursors/arrowN.png deleted file mode 100644 index 5ca8ec5ac6b815cc849c70098a05334e7aa9a4e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmV+b0ssDqP)_tHdJ^rDBl9{=$dooxd(k0lmCP$> zlu22PJ6Py7UV$j3(krtenCX??BMLnDR7OKE(i7h$Q|xds1jE*&{(_`}Lh0k7){Ne1 zL9TSX^Dmgl^78_|2L|@gk;zrRYhkwqDItnfT0000fLxb3y>s9RB8-x^BMRT0CG|3na5H>r{k9PabzI*DJIwfYsfO+m2Q*N zP3X1&5WC{MBG^T)8 zmaOSxV{YROLIntZDW4+%vGfh0JO;0)%^L=9t8<%?FNkXZ8U^13f)y0ts^CLHsJ4O+ z1);9Um;o3z4gL(o5CBw&3?#xL4Cun|7c523^*oO?K+EBpg{D*JWEE`tya!LU622+i zBBnASJ&>lPC(?}cN?JHfp9Qy_ao;JAHEClJ|K2cCNh(M=>A;`4!#KIKHs$(`$2!))cm*&J2#|_kE)|4M1waYc@d{uDv}Iri!Mg&; zJ~9J6SBPsffOCHjpRQ|QFZ#;05PS-mEEwfbzf^2}j%@%)2m^vD9mc5Z*Esm@SBVaw z1Ly#(yOYZ<)OfcE2~gPp&iMaQ^oarhA8sxWvc{$@6ae1IlRqL~|44c!%}Fn;IUjoj z-{U0~l0$!sT7T p>r=S%LeT@n_P>a33UvSh$~P3DweOCmeq8_n002ovPDHLkV1nAL9dZBw diff --git a/widget/cocoa/cursors/arrowS.png b/widget/cocoa/cursors/arrowS.png deleted file mode 100644 index 9b2d19e0fdaf93421fb50fe2b0af11ac6ccb347c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmV+b0ssDqP)CTF{>6h5ZE;H5(H+|f*#C*U}jb=7{DS3mYn?sO$6oqk6;r7 z8?z1=h2V4kDG>h$jlhD5O+=VYz-k2#uuBrwc79{EN8~{Sr*H=+Gp{`&!=2s1O38ck zm6_FCvLuP%AhB$&5tI@S0`Wz2g+P82EaB{n>j$6AraS=@vT)pN3FNK-0000b znTW(%+qq{XojY$)Kok%KTxiCapwPAl3?pH51$@6B7fc9A(mg_-F<|)XUV)e(1Q;Oi z2#**K41YZU5heryNZw&Ur{kKiA}k4Cj3xK2SwvS$gk}i25E)h&Kjg7VC>}^4?nmc# zFlZxK4@oE<=r-^`H>5RSU;&pkzmQF6YryY9WevB|ptey{(O#nU^fgc7rUGIz7X?HC zQGkBVU*(=^wL;R6yg#&hkO%c@9At8iJlxDJ1o(nw2%r55cKTw@0CJ<&1Q>Kb<@G6H z!+HKEVL|vHyq6hrV|eU>=Pub+D#FmT<^f8NAGH@F+iX3A{^Or+IKK1-qwEcb_-))Y z$*Uv4${K)f`~;y<-4Kjr8?rXAZEd3#kh@PJFsUO#ke{F}K&LGai~$FU$_4+88h7IB$~S;00s(y00000NkvXXu0mjfJqaGF diff --git a/widget/cocoa/cursors/cell.png b/widget/cocoa/cursors/cell.png deleted file mode 100644 index 5284eaec576e1181775c883adc50d544823578ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 268 zcmV+n0rUQeP)r zR#Xf*ayN;mWi;JXP_ zK?sq^0!8yFjrPQ*=!-4r^I4CYw2+7`kQB}HO>c;mVT0O2BKahNf7T{!i8hUGTLINj z+h%NHdMH((AyT$RCWb|$udbH@Luz}BZNwI6vA=i4*a=Xx%a~SdfhJp_F9u?21yn4}&-0cs|U$(W<-5<6VLCu}BmXykycapnZ5$r&?Xjw~Rtjetp5hY_&& z#P$LvVapKki5((f61J?%Cw72@iwE)O1gLpn%q?>)ne&1*j{Hp={xf>W#HZr7 zIA_62@s}pwF#e!=m-zha8< hlCOTvS_^!Xz!PFP&F$Pjh$jF5002ovPDHLkV1g|KBF_K- diff --git a/widget/cocoa/cursors/colResize.png b/widget/cocoa/cursors/colResize.png deleted file mode 100644 index 4e3e19e223f915e6c0246071b717a14d07647b66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 321 zcmV-H0lxl;P)`D!&n& zICcpl!3c?Pg@jlXETGVBT#YG4E?AHVmZB50z>*6S(2~L-D9G&;xceRpccF3!Dsr*j z55FK{QM%}NqXfkGow6o!3v}^pF38+7J7dh5k|5YD&SHi?rX^Zngp>!rVc9OD1eoms z0!uBoK T(3wME00000NkvXXu0mjf|00M@ diff --git a/widget/cocoa/cursors/colResize@2x.png b/widget/cocoa/cursors/colResize@2x.png deleted file mode 100644 index 6a92cf68063e51617c26edbe98147c3e85660bf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 836 zcmV-K1H1f*P)#w3oW7(9T}tBkjjcmr%7A)FpZZy}&(AD?6V1?Vdb^qCt1-^DQUNc!o&0xI;X?K^=3K@vB zyVnw5Rh{FnzXC(3Pc3y&UDyCPcK9Pc77XZy5a@vqVCrBRowDy>ufYNM z3@(MC@EzPK4BRETLK~Ot;<1WhVxeP|d-2k-3a}pH!4_zx z4z|Qda+uqa4z}DLEefGMT6BK6%PH{-XPYZBW7(17aM$heIv7ys37C)*mJJlg>uxVN zDDVx~12NfSSx0ff;r5CNY;r+rgO{Yuvdz3Jru8M?|9;K7+(q{~e#b8X0dlvc>f^lt O0000Q)MPdtXje&@u zb|JKgMH)@iAOW#z_4XckSq#rHbYc78;4t@|bA0#S_vRiEtrh>qV2$fe1BG#)p)xiY z7C=0!BBtDJpf9{pC=_1wdc6;m$>jTDv6uk7zTq8W$dQaB16kY@4u>E2`~8nBG~e6X zBcIPls;UwY2n6Wh;D8Y0oJ=ehbAltdl7S>13WXduH#fyxE=P8|9SKWev)KqaoLd4% zHjxdmReQJF&48#V3WDVEcG%=IOMBqY0Xh{YZ#`Y?MMx#Mkkw`>}Su7Ts&1Pe0KugzvN3OlBLS}@ddc9sU8jWN&n<*F!(*FKFAy%nW3U0UiEjZFu zp?BFa9ty%vB9YiVJ3IS)eSO{G5&q4i_=|7QpLmx{CU=p8TyR!jcCv{bTNZVF$#}zv z0OEN^#GWx8+=~D82S+sRi5S0aKs;|ECVg=J%O`W4>km{^mHw>2>}>!5002ovPDHLk FV1o1LMkD|L diff --git a/widget/cocoa/cursors/help@2x.png b/widget/cocoa/cursors/help@2x.png deleted file mode 100644 index 0ac53a973386bfe552f27201174ecce63bf1ab7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1693 zcmV;O24eY%P)@CV=xvz;_K2A(G##LK0->sX$Zf2_wH9L>=zdLH(4}{g%5m9i8v8k zIBel1po_Q5?T^dP&-YGGPv2xQn<9$3y1J;gwwAK8vM3=Tf$VlWfZzUOSFc{h82?xp zd}n56ZXy<9N^HB4L}&@<;vI}=hNrc)^=mGPeu#MW>J_!Lw2;r|Ll8^ASopvfhFG_6 z-_Ag6;c!?^LK3hlKEA!Z{UX=&EQm)(N9oL&GjI+I@I?$5Vj?y;v?TNd0?S6kH#awD zG0{8-J32aO-@bi{NF9iQvVtKtIE*Bea#9mOM~ITT^yKB`rL3*34T9+5!-uHtH^kU% zHph0~N7cXAW?CdNJ3=Gh%Tem1DC+Dq6Al8Ei4+zE_L*N3Za7RH)s0rAl ztvO|K9hjJyXad2|&=AGO#=ccZLqh{;cH_nkB>IMLOiYYFHVj*u*+Z1F7)TJuFkMP$XQs;YLJ6W{-~`Y!3who+{ceg!c) zN3eR1j*h0))m2(vUiOy+PfFreOM&+I@#7t1@Ejl*bKc{>y`sTo+yyOxz^lK%prGJO zZg;Eb-BwyMW5#b3NmiWlXNE#U#A+zxkBB&3z zVBm%Z(c(7BNJ}6}Zdn532-ou;2zKt=xv&zbtE(fkVUnIac`~R^c6K(wzzq$eB?j8G z1W;oRXHn$GID9g_A&ieLb12zrUZ{Za2LhkJ9Dx%T z$5g+-Nepf!0lkEtKY#uk5#eP-B{o02%(k?&WZBo;M!~I=kUojq+S=-r2U(cVA7tQG zCb8Z|xo3aFC9q~%O1w{i1CtkJw+?Qljp`3F##vs=V6l#cmSrKBv{=aDeW1L&+_E1y zVBiF|@*vZf5{whP{H@@tvdu=PPoK6VWPE&_414+Vr6r&A^mGCTxT>qGzXP|jl+YJ* zj8sNuUtixnh#4Fl#LI^&W^8PX44a#qQ^zAFV#A(1d2$b&;8qrM`f{3)%s7>pn3&IP z?N1QgzkgqSuoV{<`-LwqE>cBBh5Fz^Oc*#)Qd08432uEkt-sKCM+bs*nSo6jfVj(7C3x`j6sSkZyMJCf1jC2qkJb19U zr>CbK9m7Zj`#V>zT%pX&%r~|caSZ1$#t;r)#6T<&pDrASlx>ypHnxl;URlE@0`l7{=MpeB*e9ml nk9;5cGwbe$?%jVi_!sRTCBqPFa8!r000000NkvXXu0mjfn4=rJ diff --git a/widget/cocoa/cursors/move.png b/widget/cocoa/cursors/move.png deleted file mode 100644 index 1360f822777ee41f649fe9275ebb7b3d9f0cd8e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 284 zcmV+%0ptFOP)8|%*rPJ~u(%?g@wgV62EdJApl3ULCQhp=2ur>>v z;f+Rk^-d8ug|=DsTC3-_3pl(}@Eff=kbr>0K>~uk;Vh{I7+$J~7R3??@X2+(7eUnn zi3GTzD(InPDey)MGiQpVHGCzIxj#YB8_lY~hzCX#N#ON*!AKt)_|UcPmHT7_Wq90V zV>IR+pXqFjw8?9dX~T~;t%cWuS~5sN;lrLE4acQ$919Crk`^;h5Do&C1S5(7;ol!P iMlayN`NxrYWjz7e$SD;$@K)*o0000!yx?M3o=1~5 z<@2qos;ACNAPIpdZZ84)^;*kZ$e8p50Nt_VmIBGqmpxJ-enS}~fP0qr3eCMnU*X0? z{$D{L9=;3MLFF~qhxfXWXi0#>e^`dqmFC{V7)Z1sz~M(8u!}D-ijWWmba+8R7f|6v z30**f*CliT30{}b1tfS~LKoohyis7ZdI?>C!|MWELKmoCHkYrzEZ=nkZj2jy@i&!F z1UP&Mc8(A@$K34h6yWfPx`b}t*i0Z6zHxzg2`-RX3Y;8=WU}VMC5B)rz{Uk&+OrG@ z{G%lXVCvi=ki&SKkiZyBITN^CK7Gr?vP@tJEy2CK3R`?{!nj6`#3lSjW0{9YhuE4-HF~5vjW|p<(({dt5i6565fpA<1 zf5KdA%yhIl0^9vlwlv#rk z6VC7xWbBuiQmhjPMLtX4#V_(DUg+j!)@Q5KXD+Xw8j$t}uA@@(%qG-;00000NkvXX Hu0mjfhkg@w diff --git a/widget/cocoa/cursors/rowResize.png b/widget/cocoa/cursors/rowResize.png deleted file mode 100644 index 4c16bb8bd662a0878a309094dfed2ddd9b7cf407..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmV-R0kr;!P)rAEQPC#6a6!K6)QA%vfL z{`|20Pk@6*CLZov0Zv8Bp!T@dJ(m{H7hkIIldhL$hytb*H$tWbc$6v>Gn_8}NkE2G zP#Xrl+*={D1Nt{5M}Y;_*y9pegNyps8e1TThl>Sx%)@Bw1B@|q_*g)WN`pS4XDj5f zfCBXw0%{ba0SQxN1ZaxT;eZp)xZ)OBXyaKsGaH&gX9CvXe()7|t~RkHCzU2Z31^pgj<$0CNt72&aC21Y$`S#k?qqGL*Ph zyp@@%0B!C|J|N+$sD+g1Z?2U^;7UN|0&ep2q9PuP#n36yH9o6Q7m4W!xXD+=6Y(re zDA8xssX7vw3M3`p5N#*n2v?#_T}L82fi%gdlJF6jMDp24ATWXCGm=0cljQv+`~`y8 zP}wq)Pb1Na4Y7frfc@WJ5R0Kv+=Q*dJh9;11uubuvpgu>j`j5EE#Q{e98scAL_`XK zc+vsEDx$`-`doCxy4Vp1;!IqM@0LJRhq`C9-62+o*bVxs(0Aa-SOO$}H}R%;DZ1i~ z7>Ye{B)*8N6arVYIU>f8m|gm4-Vs5<5-2#2OFc|kk_0^B)SbtwUPx#YlV>r{XKK=r=JI*Gx<|;-~m! z2}E_Mdqdl6F(&3EeVo$g$oLZ5!>Cv%&?j+7@N+u4pwltQ{4fPnhq`0hUJ&b?*oX8r zqHkjuH6}6w^m!KFi`@w>=6300K%XndL}o7~SeLvI9fH0U!wD>>hs5rS4t+L_rG(#N z?q6+a(l6%xm($(b<+S&flI1ipQ!J-FHZ*k96Ys>H$EJRd7(HU9*wA=xDY?~aj1~uf z@ml48wrj*Pwv-dt)N|Vh;-ffD@nY+kHUnaKZ0bE4-G4XvajraYVzCm!;NI^286m#2g7)W@uOJ*hVj ex*vXO;FRB3(u>{v?2?uM00009+W-+ diff --git a/widget/cocoa/cursors/sizeNE.png b/widget/cocoa/cursors/sizeNE.png deleted file mode 100644 index f62c046575c830a21d7663d4db225accd275b913..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmV+y0qFjTP)1Cl20R)R)k-y#kzNKiVNiGm7dO~D@ROhJt_ zq(H%-lAuis6e1MEaG8LDad>liZrr`@CQz)uty2&`wyb- z-H*bLC}5BX&z~#>XnJRSm+%~sgpJ1Qh)|=!1&1Z!zL%WAifl=^?=#hiM0dvP3g+iu du$3Pucmw!wX%mWe*wz35002ovPDHLkV1jLRdW!%6 diff --git a/widget/cocoa/cursors/sizeNE@2x.png b/widget/cocoa/cursors/sizeNE@2x.png deleted file mode 100644 index 98d19e9efa143a3bbbe0e572ff24ff11138f8324..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 794 zcmV+#1LgdQP)Ks0lH~hnTDa2LTzLL8_nuTHrb8fENZj9Mb|#Py-c;P$D}4*?oqOEEMH^MM7jP;PPexXju>l zDNzAl9s(Y3R_C-BYJrYH9Y5sMsAj8XTvm4Y;(qjq2h36T@#g?kD&GzJYbj!)^+OwjX3%u*sd*(bmRy z@CkeXON9sREcDXWQ9?iO)Ik`rQiflHkKASE;F`?%dd6`hd8D=`AfL3U!lO9uD|pXy z&V(TcWCX@!2zsCmsJ(y_1z1HfmC*SL zLpvHS@nmor-o_#>X~*R$cndzqg#RKJtTDV$4~6l_vb>GT@4b{*DdAV(9hk?2FR9^8 z7|Q;Gj1p5$r+cyhuff<99;B|UjuKrkV5cYK3cLa#$M|~ZPcQq2xjJYwY>$MzR=3-E z`^RaIYr@y|@EWg`IYtYAegV^eqszp!hvzSl{x<=_>%}iLg+L*YNfkeI7XpPqA#i5? Y0W#W>Kis2_oB#j-07*qoM6N<$f^DmA>;M1& diff --git a/widget/cocoa/cursors/sizeNESW.png b/widget/cocoa/cursors/sizeNESW.png deleted file mode 100644 index 0a077fa67414f7e3d4271614b7e6db84833d4f5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 300 zcmV+{0n`48P)as@SL(?%$(a|I6cEE4eh9=KeA2SZ{MK?I>ha0bhUU<7TB zpyHiH78MF)c>}uda>f*BtLRD4%JKQ4!dj@(q&}@O@Hq2bV y$BIR)q7w5Quq1+UMO0SN6qLSHY(YVOFL(o3yc^cNOT_p90000+yT9eX72)a-KVhi*E#8$*R|Np&N%y~E?U5#uxb}~jq zxzZ;!sS}@XJf69&??q8`r&$ZE1=a%M#T}}(KvG%6CQc4)ViBVP^0Sr*T>@oLB_8lo z@OW&6pLK(8=%ARleF+CV*+|p=E{akBHD*d&}R5qT6j?_6^L!jB9v&hO2h?a&ih8z@RP~p zRygPar^^b+#>^LAT<22hks1h8cvNC|+qP9md1L>P68b8XS3pjSy58G}?ywuVDo6xSs}M^F_(ciGjjRujqa~~ODa2Mn z{%yMgi8_}`$FzXW6E(PF4%oZA1Y>rR-@y&}34VZY;4?eSSKt{4ISqHz`Y#2tRGxOa z4qB=oqQnKmy#?DrnYjeS+GGJ|Fe-wPIk7c)iv&7F&@sm-ASir9Z1UkX zWs}X<^yr~^u4&{Wn!b#R$@9>JW1t6%(u0M$3W#gifq{~J@xe3fG)WKcq*sdjKOAr& gh7YIAm+AlXACnbt4p~|!kN^Mx07*qoM6N<$f?n5nEdT%j diff --git a/widget/cocoa/cursors/sizeNS@2x.png b/widget/cocoa/cursors/sizeNS@2x.png deleted file mode 100644 index e48fd0cb3a461667e2280e008b62872d14e69f30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 660 zcmV;F0&D$=P)%@94baf*t%I=5u$? z&)R$*uY#nj2IoV*C?}&seq(nzbxEIh*UQ5Ec zfPV7&5-tUFlK+#08v%9lMiSNp^piK2uq6GapQaN3|>K@Ay6>(nR7F)b-r0E*}REcAm)ab;2I3U6L`}Qcw_94b1%78 z3|e+?;&r*)n@=7v|HIcRbMZtHEv18| z9^9}YnSw(1CT34C<=h+FO}&wXdGh80CK3k8+pUFE5{oU#FLovGx|mZ*Ou)xR@*iNb zD|vSU>OZGGoAnWxkP)x-W%53pkx7YFaW?=%GT=3Nz~Rp^t2|-?Dd>_^9x-`&PAm`k uKwKdY`FuX;Rvxqdx0CvyqW)Kd9RfenDKI|(n51F=0000^ c3a}=@8#Ht1B3FEfZ5Xo41a3OeA~BXoFA3p79#__{>e0+tqh02(_3Lz7?@(iL!l&l&6* z2)+d>oD?T*0h>QmV>t}9Kn_6$KV)guIVo-y0v>CA0H%y3N${`081$4t78!7W&$OR_ z8RLl?{97=mK$jWyvJwcmlbnJJ#uO*`CAeV*Ml8i@R*Tr-g6nYh7W)J&%X*Mluh)Ne z7!;T>i)~JdoBlRR0WQ1=xD*0=B{rMQiudPRz;T>MCAQnG%7iMRiYTGu3Sb-}p)xT5 zO>G;c#E}HlP}gkRj*{5$zCLJ3i7W(O>%r<{wOX-E81!KhP1#nYCLnepIrG2Of|U{y zj!22Lw$W2?9uoXda0h!8;$qi zBlxCjJ&A-^*oFkyN`sNsn9cb)BXe*GK7gf?h}m{@L0#{YOtsTho}hh}(wL0E2^oPY zxB&0Kmn0J6q&6Z@(jFyS+>v^mtqy3D4j6E|J=Y~zCULS*khx?a4YDFh0EgGTY9yAUV@3W1z+56MU! Uv&eqyPW_ diff --git a/widget/cocoa/cursors/sizeNWSE.png b/widget/cocoa/cursors/sizeNWSE.png deleted file mode 100644 index 0574a584c196e6698cf140c109eda79052a4ab65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 295 zcmV+?0oeYDP)i}!&;biP2rC?0emAv(4urH5%DP&C1p_A%@cjU6t-ynr5o}j50#_>tU@8gle1OYu z1yT~ZQgc|qW=qJcWeG zS6IKvj(Bdzl@hf8LZHNeo|2i{RT4}fNP!-+EkK<>j{_G@)J!m@QtHn@R+#mDt#G{P tEs`l!ID%<~<3Ya%G6#P~6f{hG!53Vd8`cnp8>|2T002ovPDHLkV1gxwYefJ6 diff --git a/widget/cocoa/cursors/sizeNWSE@2x.png b/widget/cocoa/cursors/sizeNWSE@2x.png deleted file mode 100644 index 9a0a276c34b502ff09066b53320fefefabd2c6e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 976 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 Q8=z4Pp00i_>zopr0P=e$EdT%j diff --git a/widget/cocoa/cursors/vtIBeam@2x.png b/widget/cocoa/cursors/vtIBeam@2x.png deleted file mode 100644 index 41c47af116acb9570776a457f238e2b12a2eeec2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezr3(Fp7J+IEGZ*dVAfF>rj9I%Z2$K z98D2b?9%HOEM?yysPn~PqsK$eOUulT2unI{*d!3UeTLJ94JUTF%xu-X`|#xTKP-Yj zUkW%dFtR`i2X{uTz*n8DvRZ&#h;GrQjXKa z8n{lMdSI?xbbA_I_}T<4EutFki5Xam|w~C YcVaG^jL6DhU`R1|y85}Sb4q9e0N#>(wEzGB diff --git a/widget/cocoa/cursors/zoomIn.png b/widget/cocoa/cursors/zoomIn.png deleted file mode 100644 index 275bf1c69deca4473b598927233865ac83616fac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 655 zcmV;A0&x9_P)IrpCX-RBh|`m6YFW@FeHZpKxH zSFkBQyKpXLNZ!cha(BAjZq6`_i`i`U9pH7n)9JiN3>-7TW8a|E^MS~BqKp;S)(MU_D(+^}^Hr4L0HJi;-?9}OWQlrrzF=)+%7-A*|+*Ygg z0lBJEKp8uO!QeCI9FNBdwyFUP9B_xj;TPmejg@I33M^rACKSJkLFB#lQ zrE-Q`)KFe>EEYTFOB+LikRm@OS~U0&^ZWe-ZZsM_;oLn)RVh=({X(JeR`t-Zfw@!R z_qJTJ?Y9q&vCVjt&*$H1nx0 diff --git a/widget/cocoa/cursors/zoomIn@2x.png b/widget/cocoa/cursors/zoomIn@2x.png deleted file mode 100644 index fdd3f8e71d4eda8cabb8789ffdca66ce8068b27e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmV;m21@yfP)q zgg4=h5ZWJL0%Ckf1@1&J+N{4B38x9X0-wMy2pI75nU`(d>q$l@?Lk6JE+~iy(ghiU zje<7;UT5%Ggl+xo>(OMO;k8U&Cmup#(P(tjty{N_kB^UEo12@vy|}pe&$DOG<^f#e z-o(VjHMBunk_l-dn#5Wp@1YceNFpaEC+pt5d*9E`&yT2=G_*w@^d*rXeR^IU3F@40 zEDTAswY8N$dGe%R(eB^BuP$G{tg5T4RbF16^85WN5{amyq9RpOQ?vYRcz9T8Ltpry zyu$R&`f%1eZ`wqbo^4HjRyq>cN8t$~4@=Gqlm|T`rfpa^;GGiO*U1 zCW)|9HKAvlAat6Wn;V~hVP zC!~`u$m#FzuhW``1auM&4Gk()Lm#W0bWIEl4E%stjA>s=?BwNKy(tg~Y?WDKIZAD9 z?Mm=-=gz4_W@oj-qm<@u>orxXk^5DPIG+iRDA+xqr9J3GHZfYH%W=w53clCVtx zeRWO1Cw#*Y%NPZ>-Dxw(=`Ah`Pb-|)*VmiUu}#2~5`4oD3o#ixsHass@`(tt1>2^k zrv8L;EJ!-w(9qDT3BZSL1K%)-^#@`yb_BWDA>iW>ZV~K|<$n^+W3kwBuy{OfCY%zi z24A=b-!Q~NOvX-UE-pLz&k)1}#d_hw_5i`Es;V3#0AIN0^Z8a5Hu-xOV`tc@12hhB zKF$~HmW5`)N}#N)%rOG+WhH=Eh>6(DAz+UH3s|t{>C>l=EE2-@z%c^wWt9+OA*L>5 zM+i(#PGSYdPV$fZfR-x7S2aTMjTnlxcB+b zLI&Tk=H}+_5L1xH97tdl(`Z^+TGivnkH-)I%RUpscEGu<1WmRQhb*(u20aVGEs^>{ zCMfOh?ruu7nZq_YRcmT$TInAOh2Yale!pO+AlEhlb1MN&O43K9!0sYQdwctH+i6H5 znV}80(;C{3UIUg$VwWKy5Aq^`)Hid2?Sj1*E?oF}VPRn|)eoA74)hU_B7C^+6+e zTTmi6B5(g^js*0JBIIZ!{isJ<^hx-f2LmRF&B(z@!p!u z6CJByRrPwk0IqQl&#+Zi7E6Uhwn@U)M?DvpB9b^Fd!tXJpnsj7p8i`UH@#gRH?&Uq zBqkwpopXYOK335rc2G_S1l6(;J8|jKr61+I=(n-4vA<-tnMR!exRxTm+tbtYdtF`K zFET1;q|X^mBFRXYBbFtIT1dE3J(bfWVyFog_Flmu!H0s61;+)S2~GmMJ|Xy2a18(Q z?=Sd<7tN6{VKuu)FXqwWMizDfr`X+;Ri)q{w~19_AqRw&3yHUjp^B!?ck z07opFB#KGm17%n^97e(KV-4l$^HZmf;!$ZyVT_tdVi#w#gT|ZR$5AR|+o(P}b((-} z5|l-p#l43MWhrH|lgZ~$dO_p2wRJI*M3mEGF4vcBEZ9QICY#BJjO5qX3=&}^Ng~-S z@+@jT>inB`o`larBnlY6Ew6j>$rnlMluYoRXN{A$KONise-{4&?<$PSMQ=Xy00000 LNkvXXu0mjfNNq9j diff --git a/widget/cocoa/cursors/zoomOut.png b/widget/cocoa/cursors/zoomOut.png deleted file mode 100644 index 19d2d89125e4d1812b5397bb285f34cfcef8d818..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 650 zcmV;50(Jd~P);(b=8jVI;I-Pzb?Xsy(f4kXizQ;+OPA4@Q4O(Q_0|(qztMvh~ zs#`!A>x04IEBYLd$4O=2fIA!xzads~EHudP{&YIMK#y@U82kPR7&vaXn>c2ISdsHW zgT{BRS^&zLOeQ*FkwaOa-|v6NwG)X1sSF%&Ii|(250FFIqH?+X5jwXzWN<5$${Avj zLpkJFEOy948$*JSB0nZF8+_RF`~3uNG#WkT*iA@PDO1L7p-?zgJv1EPw|U@qONMN_ z^r11<7?1P${98@a^h_p0p-_lC9uF{IvkxaXm}f3>SM}iR^6c-SNF)+@RVtM}^?JQF ztLrDL#o!O!k7BX-nQw3+NzFy>SS_-Kb}^nXUNVjZFBs1l&l$%HimWmm%FngTWL*@p z11ZXSQ-1duheTv9uz~pN{Nb#?Cq4Hw4oHmGPpuZP^!1gV?=d2h{Gp;nOBF%F4Z*5n k$V(M*AgRD1zJF)G01ekxEQLv)^8f$<07*qoM6N<$f)zI?TmS$7 diff --git a/widget/cocoa/cursors/zoomOut@2x.png b/widget/cocoa/cursors/zoomOut@2x.png deleted file mode 100644 index 0ed46ce75e1e1435a0d7d91a55e12633dde3a086..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1714 zcmV;j22J^iP)Rsa&O+ed2n=e^upBC)E~36v;V$$@nRZ4 z8`mB^dUOGO(3fPwnusQ`63P20g%FY`EG%3*I5_zI^z`(wTBM;bp24#u5~5Gv@{yp< z`NkrUM0a<0^|NQs`W5Z|{rl?d*|Vylp+OZF7pq_}sG`xRDl02fjg5`-_lAaslr}sI zACy;wzF8mcn#V{!3SIa1_8t~#Jl2UHJ$h96d_IWymGFAK=sW)m3_h-1yY@M2C2ElH zxGfu-=Eqbe#Ylt|^J`xu#v7cVLpeD(G9eF@(N z3ChVm%|{TRtE+3@+}zv*0-rl~4sUcJDafX+txY|6@IcvyYq*C#y1&QcQ5_u}3MM`$ z;hQ8PZqp#QBhH1a&q!E0$#dw2?;DDbNcjYH8C-vQW^T7uSo*FVDOC?oOVNc zc5*{HS%Sj;{{CjIc}PGf(c0Ro(ltC|%1PJ6ty{N#KrF^|E+szX=UknenVGp>W{vqM zO-)S;!B3nxp`6;ulP4Ga9654C!4Lzn5RF;w}1Ka<*yLn-o1O!z1DmR*`$_} zt_k>rZx~`(qu_NqZH73#C1m00g7cP^mK4%)E+zPeAr@jXc1TaFPUI66Oyvf zz}VOrR$%Njm%WJPyWzGg1WXCtxpSvyC8klX#yv}xkX^)`ot@vp`S9?tD+?L-KITF; z?;Cdh{Q2(?Q&7wtNMH%mXhudx-P5N}M-TwZKHnO)1MY1lXtI^qYs^Ax^elu@Bhp{U z1eI5>UTsgdnZq_YU2AV|UwA$o4#TH8A?y-t5fnKlU~eU$NlCh13hXX|^z`)D+i6H* zQL-_&(*XVGHDHb;wwe;syHXNJe={f8B-nB4)Tys$W@e_+{h)dH@S*)dvltTguGC8s z>2Ie6rJNadOF{pH#pYF?l%=Jms+Jkb_CW$tPuwAkIxzmEis3$B%y_2U$bO zj#aR#`u%5#~`NjUnb=i*XE67{k-`a}x)*YWZ3e^hGI+vQP9>y%G& z5+c{BrIX;Xia}yC<+NMSARDnmXU?4YQO=8g8yOk-TV|Va)CqvL6!G2b*RTKH+}!+& zjLI>2=9ngtVkGPlTPuheBs}S!%4rgD)C3EAhhVSZL&3*_gM!ZlhXJ+^2|g7Zz`y+a z3%=o5dn9a_=Je>rK3dFSVV81>-9}l}3id!=g8cy7dpTOW`0qXvKA^YIOwI=CC>e?D z^hSXs?89BYjY2MV8!4@F650;1UCza63)}Ass!8l4lLTk0#g2mC$v(+vAFp%8&gZ-x zXPqPfwu^bai0$IaTB0NZ&a`xZus(rd6u z*vV&QWmU8G3Ruh}u*^R(5kcc#m_!OV8t({dP!}q>VFS6JBep@XHq{6?CzBd_Y7C&!X$HO*L*9Syz}YU>Ho9%4<#_{YD*7bo&W#<07*qo IM6N<$f -class nsIWidget; - -namespace mozilla { -namespace widget{ -class TextInputHandler; -} // namespace widget -} // namespace mozilla - -// A protocol listing all the methods that an object which wants -// to live in gecko's widget hierarchy must implement. |nsChildView| -// makes assumptions that any NSView with which it comes in contact will -// implement this protocol. -@protocol mozView - - // aHandler is Gecko's default text input handler: It implements the - // NSTextInput protocol to handle key events. Don't make aHandler a - // strong reference -- that causes a memory leak. -- (void)installTextInputHandler:(mozilla::widget::TextInputHandler*)aHandler; -- (void)uninstallTextInputHandler; - - // access the nsIWidget associated with this view. DOES NOT ADDREF. -- (nsIWidget*)widget; - - // return a context menu for this view -- (NSMenu*)contextMenu; - - // called when our corresponding Gecko view goes away -- (void)widgetDestroyed; - -- (BOOL)isDragInProgress; - - // Checks whether the view is first responder or not -- (BOOL)isFirstResponder; - - // Call when you dispatch an event which may cause to open context menu. -- (void)maybeInitContextMenuTracking; - -@end - -// An informal protocol implemented by the NSWindow of the host application. -// -// It's used to prevent re-entrant calls to -makeKeyAndOrderFront: when gecko -// focus/activate events propagate out to the embedder's -// nsIEmbeddingSiteWindow::SetFocus implementation. -@interface NSObject(mozWindow) - -- (BOOL)suppressMakeKeyFront; -- (void)setSuppressMakeKeyFront:(BOOL)inSuppress; - -@end - -#endif // mozView_h_ diff --git a/widget/cocoa/nsAppShell.h b/widget/cocoa/nsAppShell.h deleted file mode 100644 index b7836b6391..0000000000 --- a/widget/cocoa/nsAppShell.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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/. */ - -/* - * Runs the main native Cocoa run loop, interrupting it as needed to process - * Gecko events. - */ - -#ifndef nsAppShell_h_ -#define nsAppShell_h_ - -#include "nsBaseAppShell.h" -#include "nsTArray.h" - -// GeckoNSApplication -// -// Subclass of NSApplication for filtering out certain events. -@interface GeckoNSApplication : NSApplication -{ -} -@end - -@class AppShellDelegate; - -class nsAppShell : public nsBaseAppShell -{ -public: - NS_IMETHOD ResumeNative(void); - - nsAppShell(); - - nsresult Init(); - - NS_IMETHOD Run(void); - NS_IMETHOD Exit(void); - NS_IMETHOD OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait); - NS_IMETHOD AfterProcessNextEvent(nsIThreadInternal *aThread, - bool aEventWasProcessed); - - // public only to be visible to Objective-C code that must call it - void WillTerminate(); - -protected: - virtual ~nsAppShell(); - - virtual void ScheduleNativeEventCallback(); - virtual bool ProcessNextNativeEvent(bool aMayWait); - - static void ProcessGeckoEvents(void* aInfo); - -protected: - CFMutableArrayRef mAutoreleasePools; - - AppShellDelegate* mDelegate; - CFRunLoopRef mCFRunLoop; - CFRunLoopSourceRef mCFRunLoopSource; - - bool mRunningEventLoop; - bool mStarted; - bool mTerminated; - bool mSkippedNativeCallback; - bool mRunningCocoaEmbedded; - - int32_t mNativeEventCallbackDepth; - // Can be set from different threads, so must be modified atomically - int32_t mNativeEventScheduledDepth; -}; - -#endif // nsAppShell_h_ diff --git a/widget/cocoa/nsAppShell.mm b/widget/cocoa/nsAppShell.mm deleted file mode 100644 index 33ce8e742a..0000000000 --- a/widget/cocoa/nsAppShell.mm +++ /dev/null @@ -1,907 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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/. */ - -/* - * Runs the main native Cocoa run loop, interrupting it as needed to process - * Gecko events. - */ - -#import - -#include "CustomCocoaEvents.h" -#include "mozilla/WidgetTraceEvent.h" -#include "nsAppShell.h" -#include "nsCOMPtr.h" -#include "nsIFile.h" -#include "nsDirectoryServiceDefs.h" -#include "nsString.h" -#include "nsIRollupListener.h" -#include "nsIWidget.h" -#include "nsThreadUtils.h" -#include "nsIWindowMediator.h" -#include "nsServiceManagerUtils.h" -#include "nsIInterfaceRequestor.h" -#include "nsIWebBrowserChrome.h" -#include "nsObjCExceptions.h" -#include "nsCocoaFeatures.h" -#include "nsCocoaUtils.h" -#include "nsChildView.h" -#include "nsToolkit.h" -#include "TextInputHandler.h" -#include "mozilla/HangMonitor.h" -#include "GeckoProfiler.h" -#include "pratom.h" -#if !defined(RELEASE_OR_BETA) || defined(DEBUG) -#include "nsSandboxViolationSink.h" -#endif - -#include -#include "nsIDOMWakeLockListener.h" -#include "nsIPowerManagerService.h" - -using namespace mozilla::widget; - -// A wake lock listener that disables screen saver when requested by -// Gecko. For example when we're playing video in a foreground tab we -// don't want the screen saver to turn on. - -class MacWakeLockListener final : public nsIDOMMozWakeLockListener { -public: - NS_DECL_ISUPPORTS; - -private: - ~MacWakeLockListener() {} - - IOPMAssertionID mAssertionID = kIOPMNullAssertionID; - - NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) override { - if (!aTopic.EqualsASCII("screen")) { - return NS_OK; - } - // Note the wake lock code ensures that we're not sent duplicate - // "locked-foreground" notifications when multiple wake locks are held. - if (aState.EqualsASCII("locked-foreground")) { - // Prevent screen saver. - CFStringRef cf_topic = - ::CFStringCreateWithCharacters(kCFAllocatorDefault, - reinterpret_cast - (aTopic.Data()), - aTopic.Length()); - IOReturn success = - ::IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, - kIOPMAssertionLevelOn, - cf_topic, - &mAssertionID); - CFRelease(cf_topic); - if (success != kIOReturnSuccess) { - NS_WARNING("failed to disable screensaver"); - } - } else { - // Re-enable screen saver. - NS_WARNING("Releasing screensaver"); - if (mAssertionID != kIOPMNullAssertionID) { - IOReturn result = ::IOPMAssertionRelease(mAssertionID); - if (result != kIOReturnSuccess) { - NS_WARNING("failed to release screensaver"); - } - } - } - return NS_OK; - } -}; // MacWakeLockListener - -// defined in nsCocoaWindow.mm -extern int32_t gXULModalLevel; - -static bool gAppShellMethodsSwizzled = false; - -@implementation GeckoNSApplication - -- (void)sendEvent:(NSEvent *)anEvent -{ - mozilla::HangMonitor::NotifyActivity(); - if ([anEvent type] == NSApplicationDefined && - [anEvent subtype] == kEventSubtypeTrace) { - mozilla::SignalTracerThread(); - return; - } - [super sendEvent:anEvent]; -} - -#if defined(MAC_OS_X_VERSION_10_12) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 && \ - __LP64__ -// 10.12 changed `mask` to NSEventMask (unsigned long long) for x86_64 builds. -- (NSEvent*)nextEventMatchingMask:(NSEventMask)mask -#else -- (NSEvent*)nextEventMatchingMask:(NSUInteger)mask -#endif - untilDate:(NSDate*)expiration - inMode:(NSString*)mode - dequeue:(BOOL)flag -{ - if (expiration) { - mozilla::HangMonitor::Suspend(); - } - NSEvent* nextEvent = [super nextEventMatchingMask:mask - untilDate:expiration inMode:mode dequeue:flag]; - if (expiration) { - mozilla::HangMonitor::NotifyActivity(); - } - return nextEvent; -} - -@end - -// AppShellDelegate -// -// Cocoa bridge class. An object of this class is registered to receive -// notifications. -// -@interface AppShellDelegate : NSObject -{ - @private - nsAppShell* mAppShell; -} - -- (id)initWithAppShell:(nsAppShell*)aAppShell; -- (void)applicationWillTerminate:(NSNotification*)aNotification; -- (void)beginMenuTracking:(NSNotification*)aNotification; -@end - -// nsAppShell implementation - -NS_IMETHODIMP -nsAppShell::ResumeNative(void) -{ - nsresult retval = nsBaseAppShell::ResumeNative(); - if (NS_SUCCEEDED(retval) && (mSuspendNativeCount == 0) && - mSkippedNativeCallback) - { - mSkippedNativeCallback = false; - ScheduleNativeEventCallback(); - } - return retval; -} - -nsAppShell::nsAppShell() -: mAutoreleasePools(nullptr) -, mDelegate(nullptr) -, mCFRunLoop(NULL) -, mCFRunLoopSource(NULL) -, mRunningEventLoop(false) -, mStarted(false) -, mTerminated(false) -, mSkippedNativeCallback(false) -, mNativeEventCallbackDepth(0) -, mNativeEventScheduledDepth(0) -{ - // A Cocoa event loop is running here if (and only if) we've been embedded - // by a Cocoa app. - mRunningCocoaEmbedded = [NSApp isRunning] ? true : false; -} - -nsAppShell::~nsAppShell() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mCFRunLoop) { - if (mCFRunLoopSource) { - ::CFRunLoopRemoveSource(mCFRunLoop, mCFRunLoopSource, - kCFRunLoopCommonModes); - ::CFRelease(mCFRunLoopSource); - } - ::CFRelease(mCFRunLoop); - } - - if (mAutoreleasePools) { - NS_ASSERTION(::CFArrayGetCount(mAutoreleasePools) == 0, - "nsAppShell destroyed without popping all autorelease pools"); - ::CFRelease(mAutoreleasePools); - } - - [mDelegate release]; - - NS_OBJC_END_TRY_ABORT_BLOCK -} - -NS_IMPL_ISUPPORTS(MacWakeLockListener, nsIDOMMozWakeLockListener) -mozilla::StaticRefPtr sWakeLockListener; - -static void -AddScreenWakeLockListener() -{ - nsCOMPtr sPowerManagerService = do_GetService( - POWERMANAGERSERVICE_CONTRACTID); - if (sPowerManagerService) { - sWakeLockListener = new MacWakeLockListener(); - sPowerManagerService->AddWakeLockListener(sWakeLockListener); - } else { - NS_WARNING("Failed to retrieve PowerManagerService, wakelocks will be broken!"); - } -} - -static void -RemoveScreenWakeLockListener() -{ - nsCOMPtr sPowerManagerService = do_GetService( - POWERMANAGERSERVICE_CONTRACTID); - if (sPowerManagerService) { - sPowerManagerService->RemoveWakeLockListener(sWakeLockListener); - sPowerManagerService = nullptr; - sWakeLockListener = nullptr; - } -} - -// An undocumented CoreGraphics framework method, present in the same form -// since at least OS X 10.5. -extern "C" CGError CGSSetDebugOptions(int options); - -// Init -// -// Loads the nib (see bug 316076c21) and sets up the CFRunLoopSource used to -// interrupt the main native run loop. -// -// public -nsresult -nsAppShell::Init() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // No event loop is running yet (unless an embedding app that uses - // NSApplicationMain() is running). - NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init]; - - // mAutoreleasePools is used as a stack of NSAutoreleasePool objects created - // by |this|. CFArray is used instead of NSArray because NSArray wants to - // retain each object you add to it, and you can't retain an - // NSAutoreleasePool. - mAutoreleasePools = ::CFArrayCreateMutable(nullptr, 0, nullptr); - NS_ENSURE_STATE(mAutoreleasePools); - - // Get the path of the nib file, which lives in the GRE location - nsCOMPtr nibFile; - nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile)); - NS_ENSURE_SUCCESS(rv, rv); - - nibFile->AppendNative(NS_LITERAL_CSTRING("res")); - nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib")); - - nsAutoCString nibPath; - rv = nibFile->GetNativePath(nibPath); - NS_ENSURE_SUCCESS(rv, rv); - - // This call initializes NSApplication unless: - // 1) we're using xre -- NSApp's already been initialized by - // MacApplicationDelegate.mm's EnsureUseCocoaDockAPI(). - // 2) an embedding app that uses NSApplicationMain() is running -- NSApp's - // already been initialized and its main run loop is already running. - [NSBundle loadNibFile: - [NSString stringWithUTF8String:(const char*)nibPath.get()] - externalNameTable: - [NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication] - forKey:@"NSOwner"] - withZone:NSDefaultMallocZone()]; - - mDelegate = [[AppShellDelegate alloc] initWithAppShell:this]; - NS_ENSURE_STATE(mDelegate); - - // Add a CFRunLoopSource to the main native run loop. The source is - // responsible for interrupting the run loop when Gecko events are ready. - - mCFRunLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; - NS_ENSURE_STATE(mCFRunLoop); - ::CFRetain(mCFRunLoop); - - CFRunLoopSourceContext context; - bzero(&context, sizeof(context)); - // context.version = 0; - context.info = this; - context.perform = ProcessGeckoEvents; - - mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); - NS_ENSURE_STATE(mCFRunLoopSource); - - ::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes); - - rv = nsBaseAppShell::Init(); - - if (!gAppShellMethodsSwizzled) { - // We should only replace the original terminate: method if we're not - // running in a Cocoa embedder. See bug 604901. - if (!mRunningCocoaEmbedded) { - nsToolkit::SwizzleMethods([NSApplication class], @selector(terminate:), - @selector(nsAppShell_NSApplication_terminate:)); - } - gAppShellMethodsSwizzled = true; - } - - if (nsCocoaFeatures::OnYosemiteOrLater()) { - // Explicitly turn off CGEvent logging. This works around bug 1092855. - // If there are already CGEvents in the log, turning off logging also - // causes those events to be written to disk. But at this point no - // CGEvents have yet been processed. CGEvents are events (usually - // input events) pulled from the WindowServer. An option of 0x80000008 - // turns on CGEvent logging. - CGSSetDebugOptions(0x80000007); - } - -#if !defined(RELEASE_OR_BETA) || defined(DEBUG) - if (Preferences::GetBool("security.sandbox.mac.track.violations", false)) { - nsSandboxViolationSink::Start(); - } -#endif - - [localPool release]; - - return rv; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// ProcessGeckoEvents -// -// The "perform" target of mCFRunLoop, called when mCFRunLoopSource is -// signalled from ScheduleNativeEventCallback. -// -// Arrange for Gecko events to be processed on demand (in response to a call -// to ScheduleNativeEventCallback(), if processing of Gecko events via "native -// methods" hasn't been suspended). This happens in NativeEventCallback(). -// -// protected static -void -nsAppShell::ProcessGeckoEvents(void* aInfo) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - PROFILER_LABEL("Events", "ProcessGeckoEvents", - js::ProfileEntry::Category::EVENTS); - - nsAppShell* self = static_cast (aInfo); - - if (self->mRunningEventLoop) { - self->mRunningEventLoop = false; - - // The run loop may be sleeping -- [NSRunLoop runMode:...] - // won't return until it's given a reason to wake up. Awaken it by - // posting a bogus event. There's no need to make the event - // presentable. - // - // But _don't_ set windowNumber to '-1' -- that can lead to nasty - // weirdness like bmo bug 397039 (a crash in [NSApp sendEvent:] on one of - // these fake events, because the -1 has gotten changed into the number - // of an actual NSWindow object, and that NSWindow object has just been - // destroyed). Setting windowNumber to '0' seems to work fine -- this - // seems to prevent the OS from ever trying to associate our bogus event - // with a particular NSWindow object. - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined - location:NSMakePoint(0,0) - modifierFlags:0 - timestamp:0 - windowNumber:0 - context:NULL - subtype:kEventSubtypeNone - data1:0 - data2:0] - atStart:NO]; - } - - if (self->mSuspendNativeCount <= 0) { - ++self->mNativeEventCallbackDepth; - self->NativeEventCallback(); - --self->mNativeEventCallbackDepth; - } else { - self->mSkippedNativeCallback = true; - } - - // Still needed to avoid crashes on quit in most Mochitests. - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined - location:NSMakePoint(0,0) - modifierFlags:0 - timestamp:0 - windowNumber:0 - context:NULL - subtype:kEventSubtypeNone - data1:0 - data2:0] - atStart:NO]; - - // Normally every call to ScheduleNativeEventCallback() results in - // exactly one call to ProcessGeckoEvents(). So each Release() here - // normally balances exactly one AddRef() in ScheduleNativeEventCallback(). - // But if Exit() is called just after ScheduleNativeEventCallback(), the - // corresponding call to ProcessGeckoEvents() will never happen. We check - // for this possibility in two different places -- here and in Exit() - // itself. If we find here that Exit() has been called (that mTerminated - // is true), it's because we've been called recursively, that Exit() was - // called from self->NativeEventCallback() above, and that we're unwinding - // the recursion. In this case we'll never be called again, and we balance - // here any extra calls to ScheduleNativeEventCallback(). - // - // When ProcessGeckoEvents() is called recursively, it's because of a - // call to ScheduleNativeEventCallback() from NativeEventCallback(). We - // balance the "extra" AddRefs here (rather than always in Exit()) in order - // to ensure that 'self' stays alive until the end of this method. We also - // make sure not to finish the balancing until all the recursion has been - // unwound. - if (self->mTerminated) { - int32_t releaseCount = 0; - if (self->mNativeEventScheduledDepth > self->mNativeEventCallbackDepth) { - releaseCount = PR_ATOMIC_SET(&self->mNativeEventScheduledDepth, - self->mNativeEventCallbackDepth); - } - while (releaseCount-- > self->mNativeEventCallbackDepth) - self->Release(); - } else { - // As best we can tell, every call to ProcessGeckoEvents() is triggered - // by a call to ScheduleNativeEventCallback(). But we've seen a few - // (non-reproducible) cases of double-frees that *might* have been caused - // by spontaneous calls (from the OS) to ProcessGeckoEvents(). So we - // deal with that possibility here. - if (PR_ATOMIC_DECREMENT(&self->mNativeEventScheduledDepth) < 0) { - PR_ATOMIC_SET(&self->mNativeEventScheduledDepth, 0); - NS_WARNING("Spontaneous call to ProcessGeckoEvents()!"); - } else { - self->Release(); - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// WillTerminate -// -// Called by the AppShellDelegate when an NSApplicationWillTerminate -// notification is posted. After this method is called, native events should -// no longer be processed. The NSApplicationWillTerminate notification is -// only posted when [NSApp terminate:] is called, which doesn't happen on a -// "normal" application quit. -// -// public -void -nsAppShell::WillTerminate() -{ - if (mTerminated) - return; - - // Make sure that the nsAppExitEvent posted by nsAppStartup::Quit() (called - // from [MacApplicationDelegate applicationShouldTerminate:]) gets run. - NS_ProcessPendingEvents(NS_GetCurrentThread()); - - mTerminated = true; -} - -// ScheduleNativeEventCallback -// -// Called (possibly on a non-main thread) when Gecko has an event that -// needs to be processed. The Gecko event needs to be processed on the -// main thread, so the native run loop must be interrupted. -// -// In nsBaseAppShell.cpp, the mNativeEventPending variable is used to -// ensure that ScheduleNativeEventCallback() is called no more than once -// per call to NativeEventCallback(). ProcessGeckoEvents() can skip its -// call to NativeEventCallback() if processing of Gecko events by native -// means is suspended (using nsIAppShell::SuspendNative()), which will -// suspend calls from nsBaseAppShell::OnDispatchedEvent() to -// ScheduleNativeEventCallback(). But when Gecko event processing by -// native means is resumed (in ResumeNative()), an extra call is made to -// ScheduleNativeEventCallback() (from ResumeNative()). This triggers -// another call to ProcessGeckoEvents(), which calls NativeEventCallback(), -// and nsBaseAppShell::OnDispatchedEvent() resumes calling -// ScheduleNativeEventCallback(). -// -// protected virtual -void -nsAppShell::ScheduleNativeEventCallback() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mTerminated) - return; - - // Each AddRef() here is normally balanced by exactly one Release() in - // ProcessGeckoEvents(). But there are exceptions, for which see - // ProcessGeckoEvents() and Exit(). - NS_ADDREF_THIS(); - PR_ATOMIC_INCREMENT(&mNativeEventScheduledDepth); - - // This will invoke ProcessGeckoEvents on the main thread. - ::CFRunLoopSourceSignal(mCFRunLoopSource); - ::CFRunLoopWakeUp(mCFRunLoop); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Undocumented Cocoa Event Manager function, present in the same form since -// at least OS X 10.6. -extern "C" EventAttributes GetEventAttributes(EventRef inEvent); - -// ProcessNextNativeEvent -// -// If aMayWait is false, process a single native event. If it is true, run -// the native run loop until stopped by ProcessGeckoEvents. -// -// Returns true if more events are waiting in the native event queue. -// -// protected virtual -bool -nsAppShell::ProcessNextNativeEvent(bool aMayWait) -{ - bool moreEvents = false; - - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - bool eventProcessed = false; - NSString* currentMode = nil; - - if (mTerminated) - return false; - - bool wasRunningEventLoop = mRunningEventLoop; - mRunningEventLoop = aMayWait; - NSDate* waitUntil = nil; - if (aMayWait) - waitUntil = [NSDate distantFuture]; - - NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop]; - - EventQueueRef currentEventQueue = GetCurrentEventQueue(); - EventTargetRef eventDispatcherTarget = GetEventDispatcherTarget(); - - if (aMayWait) { - mozilla::HangMonitor::Suspend(); - } - - // Only call -[NSApp sendEvent:] (and indirectly send user-input events to - // Gecko) if aMayWait is true. Tbis ensures most calls to -[NSApp - // sendEvent:] happen under nsAppShell::Run(), at the lowest level of - // recursion -- thereby making it less likely Gecko will process user-input - // events in the wrong order or skip some of them. It also avoids eating - // too much CPU in nsBaseAppShell::OnProcessNextEvent() (which calls - // us) -- thereby avoiding the starvation of nsIRunnable events in - // nsThread::ProcessNextEvent(). For more information see bug 996848. - do { - // No autorelease pool is provided here, because OnProcessNextEvent - // and AfterProcessNextEvent are responsible for maintaining it. - NS_ASSERTION(mAutoreleasePools && ::CFArrayGetCount(mAutoreleasePools), - "No autorelease pool for native event"); - - if (aMayWait) { - currentMode = [currentRunLoop currentMode]; - if (!currentMode) - currentMode = NSDefaultRunLoopMode; - NSEvent *nextEvent = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:waitUntil - inMode:currentMode - dequeue:YES]; - if (nextEvent) { - mozilla::HangMonitor::NotifyActivity(); - [NSApp sendEvent:nextEvent]; - eventProcessed = true; - } - } else { - // AcquireFirstMatchingEventInQueue() doesn't spin the (native) event - // loop, though it does queue up any newly available events from the - // window server. - EventRef currentEvent = AcquireFirstMatchingEventInQueue(currentEventQueue, 0, NULL, - kEventQueueOptionsNone); - if (!currentEvent) { - continue; - } - EventAttributes attrs = GetEventAttributes(currentEvent); - UInt32 eventKind = GetEventKind(currentEvent); - UInt32 eventClass = GetEventClass(currentEvent); - bool osCocoaEvent = - ((eventClass == 'appl') || (eventClass == kEventClassAppleEvent) || - ((eventClass == 'cgs ') && (eventKind != NSApplicationDefined))); - // If attrs is kEventAttributeUserEvent or kEventAttributeMonitored - // (i.e. a user input event), we shouldn't process it here while - // aMayWait is false. Likewise if currentEvent will eventually be - // turned into an OS-defined Cocoa event, or otherwise needs AppKit - // processing. Doing otherwise risks doing too much work here, and - // preventing the event from being properly processed by the AppKit - // framework. - if ((attrs != kEventAttributeNone) || osCocoaEvent) { - // Since we can't process the next event here (while aMayWait is false), - // we want moreEvents to be false on return. - eventProcessed = false; - // This call to ReleaseEvent() matches a call to RetainEvent() in - // AcquireFirstMatchingEventInQueue() above. - ReleaseEvent(currentEvent); - break; - } - // This call to RetainEvent() matches a call to ReleaseEvent() in - // RemoveEventFromQueue() below. - RetainEvent(currentEvent); - RemoveEventFromQueue(currentEventQueue, currentEvent); - SendEventToEventTarget(currentEvent, eventDispatcherTarget); - // This call to ReleaseEvent() matches a call to RetainEvent() in - // AcquireFirstMatchingEventInQueue() above. - ReleaseEvent(currentEvent); - eventProcessed = true; - } - } while (mRunningEventLoop); - - if (eventProcessed) { - moreEvents = - (AcquireFirstMatchingEventInQueue(currentEventQueue, 0, NULL, - kEventQueueOptionsNone) != NULL); - } - - mRunningEventLoop = wasRunningEventLoop; - - NS_OBJC_END_TRY_ABORT_BLOCK; - - if (!moreEvents) { - nsChildView::UpdateCurrentInputEventCount(); - } - - return moreEvents; -} - -// Run -// -// Overrides the base class's Run() method to call [NSApp run] (which spins -// the native run loop until the application quits). Since (unlike the base -// class's Run() method) we don't process any Gecko events here, they need -// to be processed elsewhere (in NativeEventCallback(), called from -// ProcessGeckoEvents()). -// -// Camino called [NSApp run] on its own (via NSApplicationMain()), and so -// didn't call nsAppShell::Run(). -// -// public -NS_IMETHODIMP -nsAppShell::Run(void) -{ - NS_ASSERTION(!mStarted, "nsAppShell::Run() called multiple times"); - if (mStarted || mTerminated) - return NS_OK; - - mStarted = true; - - AddScreenWakeLockListener(); - - NS_OBJC_TRY_ABORT([NSApp run]); - - RemoveScreenWakeLockListener(); - - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::Exit(void) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // This method is currently called more than once -- from (according to - // mento) an nsAppExitEvent dispatched by nsAppStartup::Quit() and from an - // XPCOM shutdown notification that nsBaseAppShell has registered to - // receive. So we need to ensure that multiple calls won't break anything. - // But we should also complain about it (since it isn't quite kosher). - if (mTerminated) { - NS_WARNING("nsAppShell::Exit() called redundantly"); - return NS_OK; - } - - mTerminated = true; - -#if !defined(RELEASE_OR_BETA) || defined(DEBUG) - nsSandboxViolationSink::Stop(); -#endif - - // Quoting from Apple's doc on the [NSApplication stop:] method (from their - // doc on the NSApplication class): "If this method is invoked during a - // modal event loop, it will break that loop but not the main event loop." - // nsAppShell::Exit() shouldn't be called from a modal event loop. So if - // it is we complain about it (to users of debug builds) and call [NSApp - // stop:] one extra time. (I'm not sure if modal event loops can be nested - // -- Apple's docs don't say one way or the other. But the return value - // of [NSApp _isRunningModal] doesn't change immediately after a call to - // [NSApp stop:], so we have to assume that one extra call to [NSApp stop:] - // will do the job.) - BOOL cocoaModal = [NSApp _isRunningModal]; - NS_ASSERTION(!cocoaModal, - "Don't call nsAppShell::Exit() from a modal event loop!"); - if (cocoaModal) - [NSApp stop:nullptr]; - [NSApp stop:nullptr]; - - // A call to Exit() just after a call to ScheduleNativeEventCallback() - // prevents the (normally) matching call to ProcessGeckoEvents() from - // happening. If we've been called from ProcessGeckoEvents() (as usually - // happens), we take care of it there. But if we have an unbalanced call - // to ScheduleNativeEventCallback() and ProcessGeckoEvents() isn't on the - // stack, we need to take care of the problem here. - if (!mNativeEventCallbackDepth && mNativeEventScheduledDepth) { - int32_t releaseCount = PR_ATOMIC_SET(&mNativeEventScheduledDepth, 0); - while (releaseCount-- > 0) - NS_RELEASE_THIS(); - } - - return nsBaseAppShell::Exit(); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// OnProcessNextEvent -// -// This nsIThreadObserver method is called prior to processing an event. -// Set up an autorelease pool that will service any autoreleased Cocoa -// objects during this event. This includes native events processed by -// ProcessNextNativeEvent. The autorelease pool will be popped by -// AfterProcessNextEvent, it is important for these two methods to be -// tightly coupled. -// -// public -NS_IMETHODIMP -nsAppShell::OnProcessNextEvent(nsIThreadInternal *aThread, bool aMayWait) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NS_ASSERTION(mAutoreleasePools, - "No stack on which to store autorelease pool"); - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - ::CFArrayAppendValue(mAutoreleasePools, pool); - - return nsBaseAppShell::OnProcessNextEvent(aThread, aMayWait); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// AfterProcessNextEvent -// -// This nsIThreadObserver method is called after event processing is complete. -// The Cocoa implementation cleans up the autorelease pool create by the -// previous OnProcessNextEvent call. -// -// public -NS_IMETHODIMP -nsAppShell::AfterProcessNextEvent(nsIThreadInternal *aThread, - bool aEventWasProcessed) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - CFIndex count = ::CFArrayGetCount(mAutoreleasePools); - - NS_ASSERTION(mAutoreleasePools && count, - "Processed an event, but there's no autorelease pool?"); - - const NSAutoreleasePool* pool = static_cast - (::CFArrayGetValueAtIndex(mAutoreleasePools, count - 1)); - ::CFArrayRemoveValueAtIndex(mAutoreleasePools, count - 1); - [pool release]; - - return nsBaseAppShell::AfterProcessNextEvent(aThread, aEventWasProcessed); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - - -// AppShellDelegate implementation - - -@implementation AppShellDelegate -// initWithAppShell: -// -// Constructs the AppShellDelegate object -- (id)initWithAppShell:(nsAppShell*)aAppShell -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [self init])) { - mAppShell = aAppShell; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationWillTerminate:) - name:NSApplicationWillTerminateNotification - object:NSApp]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(applicationDidBecomeActive:) - name:NSApplicationDidBecomeActiveNotification - object:NSApp]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self - selector:@selector(beginMenuTracking:) - name:@"com.apple.HIToolbox.beginMenuTrackingNotification" - object:nil]; - } - - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// applicationWillTerminate: -// -// Notify the nsAppShell that native event processing should be discontinued. -- (void)applicationWillTerminate:(NSNotification*)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mAppShell->WillTerminate(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// applicationDidBecomeActive -// -// Make sure TextInputHandler::sLastModifierState is updated when we become -// active (since we won't have received [ChildView flagsChanged:] messages -// while inactive). -- (void)applicationDidBecomeActive:(NSNotification*)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // [NSEvent modifierFlags] is valid on every kind of event, so we don't need - // to worry about getting an NSInternalInconsistencyException here. - NSEvent* currentEvent = [NSApp currentEvent]; - if (currentEvent) { - TextInputHandler::sLastModifierState = - [currentEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// beginMenuTracking -// -// Roll up our context menu (if any) when some other app (or the OS) opens -// any sort of menu. But make sure we don't do this for notifications we -// send ourselves (whose 'sender' will be @"org.mozilla.gecko.PopupWindow"). -- (void)beginMenuTracking:(NSNotification*)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSString *sender = [aNotification object]; - if (!sender || ![sender isEqualToString:@"org.mozilla.gecko.PopupWindow"]) { - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (rollupWidget) - rollupListener->Rollup(0, true, nullptr, nullptr); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -// We hook terminate: in order to make OS-initiated termination work nicely -// with Gecko's shutdown sequence. (Two ways to trigger OS-initiated -// termination: 1) Quit from the Dock menu; 2) Log out from (or shut down) -// your computer while the browser is active.) -@interface NSApplication (MethodSwizzling) -- (void)nsAppShell_NSApplication_terminate:(id)sender; -@end - -@implementation NSApplication (MethodSwizzling) - -// Called by the OS after [MacApplicationDelegate applicationShouldTerminate:] -// has returned NSTerminateNow. This method "subclasses" and replaces the -// OS's original implementation. The only thing the orginal method does which -// we need is that it posts NSApplicationWillTerminateNotification. Everything -// else is unneeded (because it's handled elsewhere), or actively interferes -// with Gecko's shutdown sequence. For example the original terminate: method -// causes the app to exit() inside [NSApp run] (called from nsAppShell::Run() -// above), which means that nothing runs after the call to nsAppStartup::Run() -// in XRE_Main(), which in particular means that ScopedXPCOMStartup's destructor -// and NS_ShutdownXPCOM() never get called. -- (void)nsAppShell_NSApplication_terminate:(id)sender -{ - [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillTerminateNotification - object:NSApp]; -} - -@end diff --git a/widget/cocoa/nsBidiKeyboard.h b/widget/cocoa/nsBidiKeyboard.h deleted file mode 100644 index e7e7ac8722..0000000000 --- a/widget/cocoa/nsBidiKeyboard.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 nsBidiKeyboard_h_ -#define nsBidiKeyboard_h_ - -#include "nsIBidiKeyboard.h" - -class nsBidiKeyboard : public nsIBidiKeyboard -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIBIDIKEYBOARD - - nsBidiKeyboard(); - -protected: - virtual ~nsBidiKeyboard(); -}; - -#endif // nsBidiKeyboard_h_ diff --git a/widget/cocoa/nsBidiKeyboard.mm b/widget/cocoa/nsBidiKeyboard.mm deleted file mode 100644 index e0fc86aeb7..0000000000 --- a/widget/cocoa/nsBidiKeyboard.mm +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 "nsBidiKeyboard.h" -#include "nsCocoaUtils.h" -#include "TextInputHandler.h" - -// This must be the last include: -#include "nsObjCExceptions.h" - -using namespace mozilla::widget; - -NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard) - -nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard() -{ - Reset(); -} - -nsBidiKeyboard::~nsBidiKeyboard() -{ -} - -NS_IMETHODIMP nsBidiKeyboard::Reset() -{ - return NS_OK; -} - -NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(bool *aIsRTL) -{ - *aIsRTL = TISInputSourceWrapper::CurrentInputSource().IsForRTLLanguage(); - return NS_OK; -} - -NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult) -{ - // not implemented yet - return NS_ERROR_NOT_IMPLEMENTED; -} diff --git a/widget/cocoa/nsChangeObserver.h b/widget/cocoa/nsChangeObserver.h deleted file mode 100644 index 1b9a001735..0000000000 --- a/widget/cocoa/nsChangeObserver.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 nsChangeObserver_h_ -#define nsChangeObserver_h_ - -class nsIContent; -class nsIDocument; -class nsIAtom; - -#define NS_DECL_CHANGEOBSERVER \ -void ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aContent, nsIAtom *aAttribute) override; \ -void ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, int32_t aIndexInContainer) override; \ -void ObserveContentInserted(nsIDocument *aDocument, nsIContent* aContainer, nsIContent *aChild) override; - -// Something that wants to be alerted to changes in attributes or changes in -// its corresponding content object. -// -// This interface is used by our menu code so we only have to have one -// nsIDocumentObserver. -// -// Any class that implements this interface must take care to unregister itself -// on deletion. -class nsChangeObserver -{ -public: - // XXX use dom::Element - virtual void ObserveAttributeChanged(nsIDocument* aDocument, - nsIContent* aContent, - nsIAtom* aAttribute)=0; - - virtual void ObserveContentRemoved(nsIDocument* aDocument, - nsIContent* aChild, - int32_t aIndexInContainer)=0; - - virtual void ObserveContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild)=0; -}; - -#endif // nsChangeObserver_h_ diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h deleted file mode 100644 index 2817c8d415..0000000000 --- a/widget/cocoa/nsChildView.h +++ /dev/null @@ -1,666 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsChildView_h_ -#define nsChildView_h_ - -// formal protocols -#include "mozView.h" -#ifdef ACCESSIBILITY -#include "mozilla/a11y/Accessible.h" -#include "mozAccessibleProtocol.h" -#endif - -#include "nsISupports.h" -#include "nsBaseWidget.h" -#include "nsWeakPtr.h" -#include "TextInputHandler.h" -#include "nsCocoaUtils.h" -#include "gfxQuartzSurface.h" -#include "GLContextTypes.h" -#include "mozilla/Mutex.h" -#include "nsRegion.h" -#include "mozilla/MouseEvents.h" -#include "mozilla/UniquePtr.h" - -#include "nsString.h" -#include "nsIDragService.h" -#include "ViewRegion.h" - -#import -#import -#import - -class nsChildView; -class nsCocoaWindow; - -namespace { -class GLPresenter; -} // namespace - -namespace mozilla { -class InputData; -class PanGestureInput; -class SwipeTracker; -struct SwipeEventQueue; -class VibrancyManager; -namespace layers { -class GLManager; -class IAPZCTreeManager; -} // namespace layers -namespace widget { -class RectTextureImage; -class WidgetRenderingContext; -} // namespace widget -} // namespace mozilla - -@class PixelHostingView; - -@interface NSEvent (Undocumented) - -// Return Cocoa event's corresponding Carbon event. Not initialized (on -// synthetic events) until the OS actually "sends" the event. This method -// has been present in the same form since at least OS X 10.2.8. -- (EventRef)_eventRef; - -@end - -@interface NSView (Undocumented) - -// Draws the title string of a window. -// Present on NSThemeFrame since at least 10.6. -// _drawTitleBar is somewhat complex, and has changed over the years -// since OS X 10.6. But in that time it's never done anything that -// would break when called outside of -[NSView drawRect:] (which we -// sometimes do), or whose output can't be redirected to a -// CGContextRef object (which we also sometimes do). This is likely -// to remain true for the indefinite future. However we should -// check _drawTitleBar in each new major version of OS X. For more -// information see bug 877767. -- (void)_drawTitleBar:(NSRect)aRect; - -// Returns an NSRect that is the bounding box for all an NSView's dirty -// rectangles (ones that need to be redrawn). The full list of dirty -// rectangles can be obtained by calling -[NSView _dirtyRegion] and then -// calling -[NSRegion getRects:count:] on what it returns. Both these -// methods have been present in the same form since at least OS X 10.5. -// Unlike -[NSView getRectsBeingDrawn:count:], these methods can be called -// outside a call to -[NSView drawRect:]. -- (NSRect)_dirtyRect; - -// Undocumented method of one or more of NSFrameView's subclasses. Called -// when one or more of the titlebar buttons needs to be repositioned, to -// disappear, or to reappear (say if the window's style changes). If -// 'redisplay' is true, the entire titlebar (the window's top 22 pixels) is -// marked as needing redisplay. This method has been present in the same -// format since at least OS X 10.5. -- (void)_tileTitlebarAndRedisplay:(BOOL)redisplay; - -// The following undocumented methods are used to work around bug 1069658, -// which is an Apple bug or design flaw that effects Yosemite. None of them -// were present prior to Yosemite (OS X 10.10). -- (NSView *)titlebarView; // Method of NSThemeFrame -- (NSView *)titlebarContainerView; // Method of NSThemeFrame -- (BOOL)transparent; // Method of NSTitlebarView and NSTitlebarContainerView -- (void)setTransparent:(BOOL)transparent; // Method of NSTitlebarView and - // NSTitlebarContainerView - -@end - -@interface ChildView : NSView< -#ifdef ACCESSIBILITY - mozAccessible, -#endif - mozView, NSTextInputClient> -{ -@private - // the nsChildView that created the view. It retains this NSView, so - // the link back to it must be weak. - nsChildView* mGeckoChild; - - // Text input handler for mGeckoChild and us. Note that this is a weak - // reference. Ideally, this should be a strong reference but a ChildView - // object can live longer than the mGeckoChild that owns it. And if - // mTextInputHandler were a strong reference, this would make it difficult - // for Gecko's leak detector to detect leaked TextInputHandler objects. - // This is initialized by [mozView installTextInputHandler:aHandler] and - // cleared by [mozView uninstallTextInputHandler]. - mozilla::widget::TextInputHandler* mTextInputHandler; // [WEAK] - - // when mouseDown: is called, we store its event here (strong) - NSEvent* mLastMouseDownEvent; - - // Needed for IME support in e10s mode. Strong. - NSEvent* mLastKeyDownEvent; - - // Whether the last mouse down event was blocked from Gecko. - BOOL mBlockedLastMouseDown; - - // when acceptsFirstMouse: is called, we store the event here (strong) - NSEvent* mClickThroughMouseDownEvent; - - // WheelStart/Stop events should always come in pairs. This BOOL records the - // last received event so that, when we receive one of the events, we make sure - // to send its pair event first, in case we didn't yet for any reason. - BOOL mExpectingWheelStop; - - // Set to YES when our GL surface has been updated and we need to call - // updateGLContext before we composite. - BOOL mNeedsGLUpdate; - - // Holds our drag service across multiple drag calls. The reference to the - // service is obtained when the mouse enters the view and is released when - // the mouse exits or there is a drop. This prevents us from having to - // re-establish the connection to the service manager many times per second - // when handling |draggingUpdated:| messages. - nsIDragService* mDragService; - - NSOpenGLContext *mGLContext; - - // Simple gestures support - // - // mGestureState is used to detect when Cocoa has called both - // magnifyWithEvent and rotateWithEvent within the same - // beginGestureWithEvent and endGestureWithEvent sequence. We - // discard the spurious gesture event so as not to confuse Gecko. - // - // mCumulativeMagnification keeps track of the total amount of - // magnification peformed during a magnify gesture so that we can - // send that value with the final MozMagnifyGesture event. - // - // mCumulativeRotation keeps track of the total amount of rotation - // performed during a rotate gesture so we can send that value with - // the final MozRotateGesture event. - enum { - eGestureState_None, - eGestureState_StartGesture, - eGestureState_MagnifyGesture, - eGestureState_RotateGesture - } mGestureState; - float mCumulativeMagnification; - float mCumulativeRotation; - -#ifdef __LP64__ - // Support for fluid swipe tracking. - BOOL* mCancelSwipeAnimation; -#endif - - // Whether this uses off-main-thread compositing. - BOOL mUsingOMTCompositor; - - // The mask image that's used when painting into the titlebar using basic - // CGContext painting (i.e. non-accelerated). - CGImageRef mTopLeftCornerMask; - - // Subviews of self, which act as container views for vibrancy views and - // non-draggable views. - NSView* mVibrancyViewsContainer; // [STRONG] - NSView* mNonDraggableViewsContainer; // [STRONG] - - // The view that does our drawing. This is a subview of self so that it can - // be ordered on top of mVibrancyViewsContainer. - PixelHostingView* mPixelHostingView; -} - -// class initialization -+ (void)initialize; - -+ (void)registerViewForDraggedTypes:(NSView*)aView; - -// these are sent to the first responder when the window key status changes -- (void)viewsWindowDidBecomeKey; -- (void)viewsWindowDidResignKey; - -// Stop NSView hierarchy being changed during [ChildView drawRect:] -- (void)delayedTearDown; - -- (void)sendFocusEvent:(mozilla::EventMessage)eventMessage; - -- (void)handleMouseMoved:(NSEvent*)aEvent; - -- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent - enter:(BOOL)aEnter - exitFrom:(mozilla::WidgetMouseEvent::ExitFrom)aExitFrom; - -- (void)updateGLContext; -- (void)_surfaceNeedsUpdate:(NSNotification*)notification; - -- (bool)preRender:(NSOpenGLContext *)aGLContext; -- (void)postRender:(NSOpenGLContext *)aGLContext; - -- (NSView*)vibrancyViewsContainer; -- (NSView*)nonDraggableViewsContainer; -- (NSView*)pixelHostingView; - -- (BOOL)isCoveringTitlebar; - -- (void)viewWillStartLiveResize; -- (void)viewDidEndLiveResize; - -- (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType; -- (NSColor*)vibrancyFontSmoothingBackgroundColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType; - -// Simple gestures support -// -// XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent, -// rotateWithEvent, and endGestureWithEvent methods are part of a -// PRIVATE interface exported by nsResponder and reverse-engineering -// was necessary to obtain the methods' prototypes. Thus, Apple may -// change the interface in the future without notice. -// -// The prototypes were obtained from the following link: -// http://cocoadex.com/2008/02/nsevent-modifications-swipe-ro.html -- (void)swipeWithEvent:(NSEvent *)anEvent; -- (void)beginGestureWithEvent:(NSEvent *)anEvent; -- (void)magnifyWithEvent:(NSEvent *)anEvent; -- (void)smartMagnifyWithEvent:(NSEvent *)anEvent; -- (void)rotateWithEvent:(NSEvent *)anEvent; -- (void)endGestureWithEvent:(NSEvent *)anEvent; - -- (void)scrollWheel:(NSEvent *)anEvent; - -- (void)setUsingOMTCompositor:(BOOL)aUseOMTC; - -- (NSEvent*)lastKeyDownEvent; -@end - -class ChildViewMouseTracker { - -public: - - static void MouseMoved(NSEvent* aEvent); - static void MouseScrolled(NSEvent* aEvent); - static void OnDestroyView(ChildView* aView); - static void OnDestroyWindow(NSWindow* aWindow); - static BOOL WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent, - ChildView* aView, BOOL isClickThrough = NO); - static void MouseExitedWindow(NSEvent* aEvent); - static void MouseEnteredWindow(NSEvent* aEvent); - static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil, ChildView* aOldView = nil); - static void ResendLastMouseMoveEvent(); - static ChildView* ViewForEvent(NSEvent* aEvent); - - static ChildView* sLastMouseEventView; - static NSEvent* sLastMouseMoveEvent; - static NSWindow* sWindowUnderMouse; - static NSPoint sLastScrollEventScreenLocation; -}; - -//------------------------------------------------------------------------- -// -// nsChildView -// -//------------------------------------------------------------------------- - -class nsChildView : public nsBaseWidget -{ -private: - typedef nsBaseWidget Inherited; - typedef mozilla::layers::IAPZCTreeManager IAPZCTreeManager; - -public: - nsChildView(); - - // nsIWidget interface - virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData = nullptr) - override; - - virtual void Destroy() override; - - NS_IMETHOD Show(bool aState) override; - virtual bool IsVisible() const override; - - NS_IMETHOD SetParent(nsIWidget* aNewParent) override; - virtual nsIWidget* GetParent(void) override; - virtual float GetDPI() override; - - NS_IMETHOD Move(double aX, double aY) override; - NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override; - NS_IMETHOD Resize(double aX, double aY, - double aWidth, double aHeight, bool aRepaint) override; - - NS_IMETHOD Enable(bool aState) override; - virtual bool IsEnabled() const override; - NS_IMETHOD SetFocus(bool aRaise) override; - virtual LayoutDeviceIntRect GetBounds() override; - virtual LayoutDeviceIntRect GetClientBounds() override; - virtual LayoutDeviceIntRect GetScreenBounds() override; - - // Returns the "backing scale factor" of the view's window, which is the - // ratio of pixels in the window's backing store to Cocoa points. Prior to - // HiDPI support in OS X 10.7, this was always 1.0, but in HiDPI mode it - // will be 2.0 (and might potentially other values as screen resolutions - // evolve). This gives the relationship between what Gecko calls "device - // pixels" and the Cocoa "points" coordinate system. - CGFloat BackingScaleFactor() const; - - mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final { - return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor()); - } - - // Call if the window's backing scale factor changes - i.e., it is moved - // between HiDPI and non-HiDPI screens - void BackingScaleFactorChanged(); - - virtual double GetDefaultScaleInternal() override; - - virtual int32_t RoundsWidgetCoordinatesTo() override; - - NS_IMETHOD Invalidate(const LayoutDeviceIntRect &aRect) override; - - virtual void* GetNativeData(uint32_t aDataType) override; - virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) override; - virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; - virtual bool ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect) override; - - static bool ConvertStatus(nsEventStatus aStatus) - { return aStatus == nsEventStatus_eConsumeNoDefault; } - NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) override; - - virtual bool WidgetTypeSupportsAcceleration() override; - virtual bool ShouldUseOffMainThreadCompositing() override; - - NS_IMETHOD SetCursor(nsCursor aCursor) override; - NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY) override; - - NS_IMETHOD SetTitle(const nsAString& title) override; - - NS_IMETHOD GetAttention(int32_t aCycleCount) override; - - virtual bool HasPendingInputEvent() override; - - NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString) override; - NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString) override; - NS_IMETHOD GetSelectionAsPlaintext(nsAString& aResult) override; - - NS_IMETHOD_(void) SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) override; - NS_IMETHOD_(InputContext) GetInputContext() override; - NS_IMETHOD_(TextEventDispatcherListener*) - GetNativeTextEventDispatcherListener() override; - NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) override; - NS_IMETHOD_(bool) ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; - bool ExecuteNativeKeyBindingRemapped( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aCocoaKeyCode); - virtual nsIMEUpdatePreference GetIMEUpdatePreference() override; - - virtual nsTransparencyMode GetTransparencyMode() override; - virtual void SetTransparencyMode(nsTransparencyMode aMode) override; - - virtual nsresult SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, - int32_t aNativeKeyCode, - uint32_t aModifierFlags, - const nsAString& aCharacters, - const nsAString& aUnmodifiedCharacters, - nsIObserver* aObserver) override; - - virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - uint32_t aModifierFlags, - nsIObserver* aObserver) override; - - virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint, - nsIObserver* aObserver) override - { return SynthesizeNativeMouseEvent(aPoint, NSMouseMoved, 0, aObserver); } - virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - double aDeltaX, - double aDeltaY, - double aDeltaZ, - uint32_t aModifierFlags, - uint32_t aAdditionalFlags, - nsIObserver* aObserver) override; - virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, - TouchPointerState aPointerState, - LayoutDeviceIntPoint aPoint, - double aPointerPressure, - uint32_t aPointerOrientation, - nsIObserver* aObserver) override; - - // Mac specific methods - - virtual bool DispatchWindowEvent(mozilla::WidgetGUIEvent& event); - - void WillPaintWindow(); - bool PaintWindow(LayoutDeviceIntRegion aRegion); - bool PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion, - mozilla::gfx::IntSize aSurfaceSize); - -#ifdef ACCESSIBILITY - already_AddRefed GetDocumentAccessible(); -#endif - - virtual void CreateCompositor() override; - virtual void PrepareWindowEffects() override; - virtual void CleanupWindowEffects() override; - virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override; - virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) override; - virtual void DrawWindowOverlay(mozilla::widget::WidgetRenderingContext* aManager, - LayoutDeviceIntRect aRect) override; - - virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) override; - - virtual void UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) override; - LayoutDeviceIntRegion GetNonDraggableRegion() { return mNonDraggableRegion.Region(); } - - virtual void ReportSwipeStarted(uint64_t aInputBlockId, bool aStartSwipe) override; - - virtual void LookUpDictionary( - const nsAString& aText, - const nsTArray& aFontRangeArray, - const bool aIsVertical, - const LayoutDeviceIntPoint& aPoint) override; - - void ResetParent(); - - static bool DoHasPendingInputEvent(); - static uint32_t GetCurrentInputEventCount(); - static void UpdateCurrentInputEventCount(); - - NSView* GetEditorView(); - - nsCocoaWindow* GetXULWindowWidget(); - - virtual void ReparentNativeWidget(nsIWidget* aNewParent) override; - - mozilla::widget::TextInputHandler* GetTextInputHandler() - { - return mTextInputHandler; - } - - void ClearVibrantAreas(); - NSColor* VibrancyFillColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType); - NSColor* VibrancyFontSmoothingBackgroundColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType); - - // unit conversion convenience functions - int32_t CocoaPointsToDevPixels(CGFloat aPts) const { - return nsCocoaUtils::CocoaPointsToDevPixels(aPts, BackingScaleFactor()); - } - LayoutDeviceIntPoint CocoaPointsToDevPixels(const NSPoint& aPt) const { - return nsCocoaUtils::CocoaPointsToDevPixels(aPt, BackingScaleFactor()); - } - LayoutDeviceIntPoint CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt) const { - return nsCocoaUtils::CocoaPointsToDevPixelsRoundDown(aPt, BackingScaleFactor()); - } - LayoutDeviceIntRect CocoaPointsToDevPixels(const NSRect& aRect) const { - return nsCocoaUtils::CocoaPointsToDevPixels(aRect, BackingScaleFactor()); - } - CGFloat DevPixelsToCocoaPoints(int32_t aPixels) const { - return nsCocoaUtils::DevPixelsToCocoaPoints(aPixels, BackingScaleFactor()); - } - NSRect DevPixelsToCocoaPoints(const LayoutDeviceIntRect& aRect) const { - return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor()); - } - - already_AddRefed - StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, - mozilla::layers::BufferMode* aBufferMode) override; - void EndRemoteDrawing() override; - void CleanupRemoteDrawing() override; - bool InitCompositor(mozilla::layers::Compositor* aCompositor) override; - - NS_IMETHOD StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent, - int32_t aPanelX, int32_t aPanelY, - nsString& aCommitted) override; - - virtual void SetPluginFocused(bool& aFocused) override; - - bool IsPluginFocused() { return mPluginFocused; } - - virtual LayoutDeviceIntPoint GetClientOffset() override; - - void DispatchAPZWheelInputEvent(mozilla::InputData& aEvent, bool aCanTriggerSwipe); - - void SwipeFinished(); - -protected: - virtual ~nsChildView(); - - void ReportMoveEvent(); - void ReportSizeEvent(); - - void TearDownView(); - - virtual already_AddRefed - AllocateChildPopupWidget() override - { - static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - nsCOMPtr widget = do_CreateInstance(kCPopUpCID); - return widget.forget(); - } - - void ConfigureAPZCTreeManager() override; - void ConfigureAPZControllerThread() override; - - void DoRemoteComposition(const LayoutDeviceIntRect& aRenderRect); - - // Overlay drawing functions for OpenGL drawing - void DrawWindowOverlay(mozilla::layers::GLManager* aManager, LayoutDeviceIntRect aRect); - void MaybeDrawResizeIndicator(mozilla::layers::GLManager* aManager); - void MaybeDrawRoundedCorners(mozilla::layers::GLManager* aManager, const LayoutDeviceIntRect& aRect); - void MaybeDrawTitlebar(mozilla::layers::GLManager* aManager); - - // Redraw the contents of mTitlebarCGContext on the main thread, as - // determined by mDirtyTitlebarRegion. - void UpdateTitlebarCGContext(); - - LayoutDeviceIntRect RectContainingTitlebarControls(); - void UpdateVibrancy(const nsTArray& aThemeGeometries); - mozilla::VibrancyManager& EnsureVibrancyManager(); - - nsIWidget* GetWidgetForListenerEvents(); - - struct SwipeInfo { - bool wantsSwipe; - uint32_t allowedDirections; - }; - - SwipeInfo SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent); - void TrackScrollEventAsSwipe(const mozilla::PanGestureInput& aSwipeStartEvent, - uint32_t aAllowedDirections); - -protected: - - ChildView* mView; // my parallel cocoa view, [STRONG] - RefPtr mTextInputHandler; - InputContext mInputContext; - - NSView* mParentView; - nsIWidget* mParentWidget; - -#ifdef ACCESSIBILITY - // weak ref to this childview's associated mozAccessible for speed reasons - // (we get queried for it *a lot* but don't want to own it) - nsWeakPtr mAccessible; -#endif - - // Protects the view from being teared down while a composition is in - // progress on the compositor thread. - mozilla::Mutex mViewTearDownLock; - - mozilla::Mutex mEffectsLock; - - // May be accessed from any thread, protected - // by mEffectsLock. - bool mShowsResizeIndicator; - LayoutDeviceIntRect mResizeIndicatorRect; - bool mHasRoundedBottomCorners; - int mDevPixelCornerRadius; - bool mIsCoveringTitlebar; - bool mIsFullscreen; - bool mIsOpaque; - LayoutDeviceIntRect mTitlebarRect; - - // The area of mTitlebarCGContext that needs to be redrawn during the next - // transaction. Accessed from any thread, protected by mEffectsLock. - LayoutDeviceIntRegion mUpdatedTitlebarRegion; - CGContextRef mTitlebarCGContext; - - // Compositor thread only - mozilla::UniquePtr mResizerImage; - mozilla::UniquePtr mCornerMaskImage; - mozilla::UniquePtr mTitlebarImage; - mozilla::UniquePtr mBasicCompositorImage; - - // The area of mTitlebarCGContext that has changed and needs to be - // uploaded to to mTitlebarImage. Main thread only. - nsIntRegion mDirtyTitlebarRegion; - - mozilla::ViewRegion mNonDraggableRegion; - - // Cached value of [mView backingScaleFactor], to avoid sending two obj-c - // messages (respondsToSelector, backingScaleFactor) every time we need to - // use it. - // ** We'll need to reinitialize this if the backing resolution changes. ** - mutable CGFloat mBackingScaleFactor; - - bool mVisible; - bool mDrawing; - bool mIsDispatchPaint; // Is a paint event being dispatched - - bool mPluginFocused; - - // Used in OMTC BasicLayers mode. Presents the BasicCompositor result - // surface to the screen using an OpenGL context. - mozilla::UniquePtr mGLPresenter; - - mozilla::UniquePtr mVibrancyManager; - RefPtr mSwipeTracker; - mozilla::UniquePtr mSwipeEventQueue; - - // Only used for drawRect-based painting in popups. - RefPtr mBackingSurface; - - // This flag is only used when APZ is off. It indicates that the current pan - // gesture was processed as a swipe. Sometimes the swipe animation can finish - // before momentum events of the pan gesture have stopped firing, so this - // flag tells us that we shouldn't allow the remaining events to cause - // scrolling. It is reset to false once a new gesture starts (as indicated by - // a PANGESTURE_(MAY)START event). - bool mCurrentPanGestureBelongsToSwipe; - - static uint32_t sLastInputEventCount; - - void ReleaseTitlebarCGContext(); - - // This is used by SynthesizeNativeTouchPoint to maintain state between - // multiple synthesized points - mozilla::UniquePtr mSynthesizedTouchInput; -}; - -#endif // nsChildView_h_ diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm deleted file mode 100644 index 868687fe16..0000000000 --- a/widget/cocoa/nsChildView.mm +++ /dev/null @@ -1,6151 +0,0 @@ -/* -*- Mode: objc; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/ArrayUtils.h" - -#include "mozilla/Logging.h" - -#include -#include - -#include "nsChildView.h" -#include "nsCocoaWindow.h" - -#include "mozilla/MiscEvents.h" -#include "mozilla/MouseEvents.h" -#include "mozilla/TextEvents.h" -#include "mozilla/TouchEvents.h" - -#include "nsArrayUtils.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsToolkit.h" -#include "nsCRT.h" - -#include "nsFontMetrics.h" -#include "nsIRollupListener.h" -#include "nsViewManager.h" -#include "nsIInterfaceRequestor.h" -#include "nsIFile.h" -#include "nsILocalFileMac.h" -#include "nsGfxCIID.h" -#include "nsIDOMSimpleGestureEvent.h" -#include "nsThemeConstants.h" -#include "nsIWidgetListener.h" -#include "nsIPresShell.h" - -#include "nsDragService.h" -#include "nsClipboard.h" -#include "nsCursorManager.h" -#include "nsWindowMap.h" -#include "nsCocoaFeatures.h" -#include "nsCocoaUtils.h" -#include "nsMenuUtilsX.h" -#include "nsMenuBarX.h" -#include "NativeKeyBindings.h" -#include "ComplexTextInputPanel.h" - -#include "gfxContext.h" -#include "gfxQuartzSurface.h" -#include "gfxUtils.h" -#include "nsRegion.h" -#include "Layers.h" -#include "ClientLayerManager.h" -#include "mozilla/layers/LayerManagerComposite.h" -#include "GfxTexturesReporter.h" -#include "GLTextureImage.h" -#include "GLContextProvider.h" -#include "GLContextCGL.h" -#include "ScopedGLHelpers.h" -#include "HeapCopyOfStackArray.h" -#include "mozilla/layers/IAPZCTreeManager.h" -#include "mozilla/layers/APZThreadUtils.h" -#include "mozilla/layers/GLManager.h" -#include "mozilla/layers/CompositorOGL.h" -#include "mozilla/layers/CompositorBridgeParent.h" -#include "mozilla/layers/BasicCompositor.h" -#include "mozilla/layers/InputAPZContext.h" -#include "mozilla/widget/CompositorWidget.h" -#include "gfxUtils.h" -#include "gfxPrefs.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/BorrowedContext.h" -#include "mozilla/gfx/MacIOSurface.h" -#ifdef ACCESSIBILITY -#include "nsAccessibilityService.h" -#include "mozilla/a11y/Platform.h" -#endif - -#include "mozilla/Preferences.h" - -#include - -#include - -#include "GeckoProfiler.h" - -#include "nsIDOMWheelEvent.h" -#include "mozilla/layers/ChromeProcessController.h" -#include "nsLayoutUtils.h" -#include "InputData.h" -#include "RectTextureImage.h" -#include "SwipeTracker.h" -#include "VibrancyManager.h" -#include "nsNativeThemeCocoa.h" -#include "nsIDOMWindowUtils.h" -#include "Units.h" -#include "UnitTransforms.h" -#include "mozilla/UniquePtrExtensions.h" - -using namespace mozilla; -using namespace mozilla::layers; -using namespace mozilla::gl; -using namespace mozilla::widget; - -using mozilla::gfx::Matrix4x4; - -#undef DEBUG_UPDATE -#undef INVALIDATE_DEBUGGING // flash areas as they are invalidated - -// Don't put more than this many rects in the dirty region, just fluff -// out to the bounding-box if there are more -#define MAX_RECTS_IN_REGION 100 - -PRLogModuleInfo* sCocoaLog = nullptr; - -extern "C" { - CG_EXTERN void CGContextResetCTM(CGContextRef); - CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); - CG_EXTERN void CGContextResetClip(CGContextRef); - - typedef CFTypeRef CGSRegionObj; - CGError CGSNewRegionWithRect(const CGRect *rect, CGSRegionObj *outRegion); - CGError CGSNewRegionWithRectList(const CGRect *rects, int rectCount, CGSRegionObj *outRegion); -} - -// defined in nsMenuBarX.mm -extern NSMenu* sApplicationMenu; // Application menu shared by all menubars - -static bool gChildViewMethodsSwizzled = false; - -extern nsIArray *gDraggedTransferables; - -ChildView* ChildViewMouseTracker::sLastMouseEventView = nil; -NSEvent* ChildViewMouseTracker::sLastMouseMoveEvent = nil; -NSWindow* ChildViewMouseTracker::sWindowUnderMouse = nil; -NSPoint ChildViewMouseTracker::sLastScrollEventScreenLocation = NSZeroPoint; - -#ifdef INVALIDATE_DEBUGGING -static void blinkRect(Rect* r); -static void blinkRgn(RgnHandle rgn); -#endif - -bool gUserCancelledDrag = false; - -uint32_t nsChildView::sLastInputEventCount = 0; - -// The view that will do our drawing or host our NSOpenGLContext or Core Animation layer. -@interface PixelHostingView : NSView { -} -@end - -@interface ChildView(Private) - -// sets up our view, attaching it to its owning gecko view -- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild; - -// set up a gecko mouse event based on a cocoa mouse event -- (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetWheelEvent*)outWheelEvent; -- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetInputEvent*)outGeckoEvent; - -- (NSMenu*)contextMenu; - -- (BOOL)isRectObscuredBySubview:(NSRect)inRect; - -- (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect; -- (BOOL)isUsingOpenGL; -- (void)drawUsingOpenGL; - -- (BOOL)hasRoundedBottomCorners; -- (CGFloat)cornerRadius; -- (void)clearCorners; - --(void)setGLOpaque:(BOOL)aOpaque; - -// Overlay drawing functions for traditional CGContext drawing -- (void)drawTitleString; -- (void)drawTitlebarHighlight; -- (void)maskTopCornersInContext:(CGContextRef)aContext; - -#if USE_CLICK_HOLD_CONTEXTMENU - // called on a timer two seconds after a mouse down to see if we should display - // a context menu (click-hold) -- (void)clickHoldCallback:(id)inEvent; -#endif - -#ifdef ACCESSIBILITY -- (id)accessible; -#endif - -- (LayoutDeviceIntPoint)convertWindowCoordinates:(NSPoint)aPoint; -- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint; - -- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent; -- (void)updateWindowDraggableState; - -- (bool)shouldConsiderStartingSwipeFromEvent:(NSEvent*)aEvent; - -@end - -@interface NSView(NSThemeFrameCornerRadius) -- (float)roundedCornerRadius; -@end - -@interface NSWindow(NSWindowShouldZoomOnDoubleClick) -+ (BOOL)_shouldZoomOnDoubleClick; // present on 10.7 and above -@end - -// Starting with 10.7 the bottom corners of all windows are rounded. -// Unfortunately, the standard rounding that OS X applies to OpenGL views -// does not use anti-aliasing and looks very crude. Since we want a smooth, -// anti-aliased curve, we'll draw it ourselves. -// Additionally, we need to turn off the OS-supplied rounding because it -// eats into our corner's curve. We do that by overriding an NSSurface method. -@interface NSSurface @end - -@implementation NSSurface(DontCutOffCorners) -- (CGSRegionObj)_createRoundedBottomRegionForRect:(CGRect)rect -{ - // Create a normal rect region without rounded bottom corners. - CGSRegionObj region; - CGSNewRegionWithRect(&rect, ®ion); - return region; -} -@end - -#pragma mark - - -// Flips a screen coordinate from a point in the cocoa coordinate system (bottom-left rect) to a point -// that is a "flipped" cocoa coordinate system (starts in the top-left). -static inline void -FlipCocoaScreenCoordinate(NSPoint &inPoint) -{ - inPoint.y = nsCocoaUtils::FlippedScreenY(inPoint.y); -} - -void EnsureLogInitialized() -{ - if (!sCocoaLog) { - sCocoaLog = PR_NewLogModule("nsCocoaWidgets"); - } -} - -namespace { - -// Used for OpenGL drawing from the compositor thread for OMTC BasicLayers. -// We need to use OpenGL for this because there seems to be no other robust -// way of drawing from a secondary thread without locking, which would cause -// deadlocks in our setup. See bug 882523. -class GLPresenter : public GLManager -{ -public: - static mozilla::UniquePtr CreateForWindow(nsIWidget* aWindow) - { - // Contrary to CompositorOGL, we allow unaccelerated OpenGL contexts to be - // used. BasicCompositor only requires very basic GL functionality. - RefPtr context = gl::GLContextProvider::CreateForWindow(aWindow, false); - return context ? MakeUnique(context) : nullptr; - } - - explicit GLPresenter(GLContext* aContext); - virtual ~GLPresenter(); - - virtual GLContext* gl() const override { return mGLContext; } - virtual ShaderProgramOGL* GetProgram(GLenum aTarget, gfx::SurfaceFormat aFormat) override - { - MOZ_ASSERT(aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB); - MOZ_ASSERT(aFormat == gfx::SurfaceFormat::R8G8B8A8); - return mRGBARectProgram.get(); - } - virtual const gfx::Matrix4x4& GetProjMatrix() const override - { - return mProjMatrix; - } - virtual void ActivateProgram(ShaderProgramOGL *aProg) override - { - mGLContext->fUseProgram(aProg->GetProgram()); - } - virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, - const gfx::Rect& aLayerRect, - const gfx::Rect& aTextureRect) override; - - void BeginFrame(LayoutDeviceIntSize aRenderSize); - void EndFrame(); - - NSOpenGLContext* GetNSOpenGLContext() - { - return GLContextCGL::Cast(mGLContext)->GetNSOpenGLContext(); - } - -protected: - RefPtr mGLContext; - mozilla::UniquePtr mRGBARectProgram; - gfx::Matrix4x4 mProjMatrix; - GLuint mQuadVBO; -}; - -} // unnamed namespace - -namespace mozilla { - -struct SwipeEventQueue { - SwipeEventQueue(uint32_t aAllowedDirections, uint64_t aInputBlockId) - : allowedDirections(aAllowedDirections) - , inputBlockId(aInputBlockId) - {} - - nsTArray queuedEvents; - uint32_t allowedDirections; - uint64_t inputBlockId; -}; - -} // namespace mozilla - -#pragma mark - - -nsChildView::nsChildView() : nsBaseWidget() -, mView(nullptr) -, mParentView(nullptr) -, mParentWidget(nullptr) -, mViewTearDownLock("ChildViewTearDown") -, mEffectsLock("WidgetEffects") -, mShowsResizeIndicator(false) -, mHasRoundedBottomCorners(false) -, mIsCoveringTitlebar(false) -, mIsFullscreen(false) -, mIsOpaque(false) -, mTitlebarCGContext(nullptr) -, mBackingScaleFactor(0.0) -, mVisible(false) -, mDrawing(false) -, mIsDispatchPaint(false) -{ - EnsureLogInitialized(); -} - -nsChildView::~nsChildView() -{ - ReleaseTitlebarCGContext(); - - if (mSwipeTracker) { - mSwipeTracker->Destroy(); - mSwipeTracker = nullptr; - } - - // Notify the children that we're gone. childView->ResetParent() can change - // our list of children while it's being iterated, so the way we iterate the - // list must allow for this. - for (nsIWidget* kid = mLastChild; kid;) { - nsChildView* childView = static_cast(kid); - kid = kid->GetPrevSibling(); - childView->ResetParent(); - } - - NS_WARNING_ASSERTION( - mOnDestroyCalled, - "nsChildView object destroyed without calling Destroy()"); - - DestroyCompositor(); - - // An nsChildView object that was in use can be destroyed without Destroy() - // ever being called on it. So we also need to do a quick, safe cleanup - // here (it's too late to just call Destroy(), which can cause crashes). - // It's particularly important to make sure widgetDestroyed is called on our - // mView -- this method NULLs mView's mGeckoChild, and NULL checks on - // mGeckoChild are used throughout the ChildView class to tell if it's safe - // to use a ChildView object. - [mView widgetDestroyed]; // Safe if mView is nil. - mParentWidget = nil; - TearDownView(); // Safe if called twice. -} - -void -nsChildView::ReleaseTitlebarCGContext() -{ - if (mTitlebarCGContext) { - CGContextRelease(mTitlebarCGContext); - mTitlebarCGContext = nullptr; - } -} - -nsresult -nsChildView::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Because the hidden window is created outside of an event loop, - // we need to provide an autorelease pool to avoid leaking cocoa objects - // (see bug 559075). - nsAutoreleasePool localPool; - - // See NSView (MethodSwizzling) below. - if (!gChildViewMethodsSwizzled) { - nsToolkit::SwizzleMethods([NSView class], @selector(mouseDownCanMoveWindow), - @selector(nsChildView_NSView_mouseDownCanMoveWindow)); - gChildViewMethodsSwizzled = true; - } - - mBounds = aRect; - - // Ensure that the toolkit is created. - nsToolkit::GetToolkit(); - - BaseCreate(aParent, aInitData); - - // inherit things from the parent view and create our parallel - // NSView in the Cocoa display system - mParentView = nil; - if (aParent) { - // inherit the top-level window. NS_NATIVE_WIDGET is always a NSView - // regardless of if we're asking a window or a view (for compatibility - // with windows). - mParentView = (NSView*)aParent->GetNativeData(NS_NATIVE_WIDGET); - mParentWidget = aParent; - } else { - // This is the normal case. When we're the root widget of the view hiararchy, - // aNativeParent will be the contentView of our window, since that's what - // nsCocoaWindow returns when asked for an NS_NATIVE_VIEW. - mParentView = reinterpret_cast*>(aNativeParent); - } - - // create our parallel NSView and hook it up to our parent. Recall - // that NS_NATIVE_WIDGET is the NSView. - CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mParentView); - NSRect r = nsCocoaUtils::DevPixelsToCocoaPoints(mBounds, scaleFactor); - mView = [[[[ChildView alloc] initWithFrame:r geckoChild:this] autorelease] retain]; - - if (!mView) { - return NS_ERROR_FAILURE; - } - - // If this view was created in a Gecko view hierarchy, the initial state - // is hidden. If the view is attached only to a native NSView but has - // no Gecko parent (as in embedding), the initial state is visible. - if (mParentWidget) - [mView setHidden:YES]; - else - mVisible = true; - - // Hook it up in the NSView hierarchy. - if (mParentView) { - [mParentView addSubview:mView]; - } - - // if this is a ChildView, make sure that our per-window data - // is set up - if ([mView isKindOfClass:[ChildView class]]) - [[WindowDataMap sharedWindowDataMap] ensureDataForWindow:[mView window]]; - - NS_ASSERTION(!mTextInputHandler, "mTextInputHandler has already existed"); - mTextInputHandler = new TextInputHandler(this, mView); - - mPluginFocused = false; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - - -void nsChildView::TearDownView() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mView) - return; - - NSWindow* win = [mView window]; - NSResponder* responder = [win firstResponder]; - - // We're being unhooked from the view hierarchy, don't leave our view - // or a child view as the window first responder. - if (responder && [responder isKindOfClass:[NSView class]] && - [(NSView*)responder isDescendantOf:mView]) { - [win makeFirstResponder:[mView superview]]; - } - - // If mView is win's contentView, win (mView's NSWindow) "owns" mView -- - // win has retained mView, and will detach it from the view hierarchy and - // release it when necessary (when win is itself destroyed (in a call to - // [win dealloc])). So all we need to do here is call [mView release] (to - // match the call to [mView retain] in nsChildView::StandardCreate()). - // Also calling [mView removeFromSuperviewWithoutNeedingDisplay] causes - // mView to be released again and dealloced, while remaining win's - // contentView. So if we do that here, win will (for a short while) have - // an invalid contentView (for the consequences see bmo bugs 381087 and - // 374260). - if ([mView isEqual:[win contentView]]) { - [mView release]; - } else { - // Stop NSView hierarchy being changed during [ChildView drawRect:] - [mView performSelectorOnMainThread:@selector(delayedTearDown) withObject:nil waitUntilDone:false]; - } - mView = nil; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsCocoaWindow* -nsChildView::GetXULWindowWidget() -{ - id windowDelegate = [[mView window] delegate]; - if (windowDelegate && [windowDelegate isKindOfClass:[WindowDelegate class]]) { - return [(WindowDelegate *)windowDelegate geckoWidget]; - } - return nullptr; -} - -void nsChildView::Destroy() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Make sure that no composition is in progress while disconnecting - // ourselves from the view. - MutexAutoLock lock(mViewTearDownLock); - - if (mOnDestroyCalled) - return; - mOnDestroyCalled = true; - - // Stuff below may delete the last ref to this - nsCOMPtr kungFuDeathGrip(this); - - [mView widgetDestroyed]; - - nsBaseWidget::Destroy(); - - NotifyWindowDestroyed(); - mParentWidget = nil; - - TearDownView(); - - nsBaseWidget::OnDestroy(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#pragma mark - - -#if 0 -static void PrintViewHierarchy(NSView *view) -{ - while (view) { - NSLog(@" view is %x, frame %@", view, NSStringFromRect([view frame])); - view = [view superview]; - } -} -#endif - -// Return native data according to aDataType -void* nsChildView::GetNativeData(uint32_t aDataType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL; - - void* retVal = nullptr; - - switch (aDataType) - { - case NS_NATIVE_WIDGET: - case NS_NATIVE_DISPLAY: - retVal = (void*)mView; - break; - - case NS_NATIVE_WINDOW: - retVal = [mView window]; - break; - - case NS_NATIVE_GRAPHIC: - NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a Mac OS X child view!"); - retVal = nullptr; - break; - - case NS_NATIVE_OFFSETX: - retVal = 0; - break; - - case NS_NATIVE_OFFSETY: - retVal = 0; - break; - - case NS_RAW_NATIVE_IME_CONTEXT: - retVal = GetPseudoIMEContext(); - if (retVal) { - break; - } - retVal = [mView inputContext]; - // If input context isn't available on this widget, we should set |this| - // instead of nullptr since if this returns nullptr, IMEStateManager - // cannot manage composition with TextComposition instance. Although, - // this case shouldn't occur. - if (NS_WARN_IF(!retVal)) { - retVal = this; - } - break; - } - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; -} - -#pragma mark - - -nsTransparencyMode nsChildView::GetTransparencyMode() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - nsCocoaWindow* windowWidget = GetXULWindowWidget(); - return windowWidget ? windowWidget->GetTransparencyMode() : eTransparencyOpaque; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque); -} - -// This is called by nsContainerFrame on the root widget for all window types -// except popup windows (when nsCocoaWindow::SetTransparencyMode is used instead). -void nsChildView::SetTransparencyMode(nsTransparencyMode aMode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsCocoaWindow* windowWidget = GetXULWindowWidget(); - if (windowWidget) { - windowWidget->SetTransparencyMode(aMode); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -bool nsChildView::IsVisible() const -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!mVisible) { - return mVisible; - } - - // mVisible does not accurately reflect the state of a hidden tabbed view - // so verify that the view has a window as well - // then check native widget hierarchy visibility - return ([mView window] != nil) && !NSIsEmptyRect([mView visibleRect]); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -// Some NSView methods (e.g. setFrame and setHidden) invalidate the view's -// bounds in our window. However, we don't want these invalidations because -// they are unnecessary and because they actually slow us down since we -// block on the compositor inside drawRect. -// When we actually need something invalidated, there will be an explicit call -// to Invalidate from Gecko, so turning these automatic invalidations off -// won't hurt us in the non-OMTC case. -// The invalidations inside these NSView methods happen via a call to the -// private method -[NSWindow _setNeedsDisplayInRect:]. Our BaseWindow -// implementation of that method is augmented to let us ignore those calls -// using -[BaseWindow disable/enableSetNeedsDisplay]. -static void -ManipulateViewWithoutNeedingDisplay(NSView* aView, void (^aCallback)()) -{ - BaseWindow* win = nil; - if ([[aView window] isKindOfClass:[BaseWindow class]]) { - win = (BaseWindow*)[aView window]; - } - [win disableSetNeedsDisplay]; - aCallback(); - [win enableSetNeedsDisplay]; -} - -// Hide or show this component -NS_IMETHODIMP nsChildView::Show(bool aState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (aState != mVisible) { - // Provide an autorelease pool because this gets called during startup - // on the "hidden window", resulting in cocoa object leakage if there's - // no pool in place. - nsAutoreleasePool localPool; - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setHidden:!aState]; - }); - - mVisible = aState; - } - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Change the parent of this widget -NS_IMETHODIMP -nsChildView::SetParent(nsIWidget* aNewParent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mOnDestroyCalled) - return NS_OK; - - nsCOMPtr kungFuDeathGrip(this); - - if (mParentWidget) { - mParentWidget->RemoveChild(this); - } - - if (aNewParent) { - ReparentNativeWidget(aNewParent); - } else { - [mView removeFromSuperview]; - mParentView = nil; - } - - mParentWidget = aNewParent; - - if (mParentWidget) { - mParentWidget->AddChild(this); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsChildView::ReparentNativeWidget(nsIWidget* aNewParent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_PRECONDITION(aNewParent, ""); - - if (mOnDestroyCalled) - return; - - NSView* newParentView = - (NSView*)aNewParent->GetNativeData(NS_NATIVE_WIDGET); - NS_ENSURE_TRUE_VOID(newParentView); - - // we hold a ref to mView, so this is safe - [mView removeFromSuperview]; - mParentView = newParentView; - [mParentView addSubview:mView]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsChildView::ResetParent() -{ - if (!mOnDestroyCalled) { - if (mParentWidget) - mParentWidget->RemoveChild(this); - if (mView) - [mView removeFromSuperview]; - } - mParentWidget = nullptr; -} - -nsIWidget* -nsChildView::GetParent() -{ - return mParentWidget; -} - -float -nsChildView::GetDPI() -{ - NSWindow* window = [mView window]; - if (window && [window isKindOfClass:[BaseWindow class]]) { - return [(BaseWindow*)window getDPI]; - } - - return 96.0; -} - -NS_IMETHODIMP nsChildView::Enable(bool aState) -{ - return NS_OK; -} - -bool nsChildView::IsEnabled() const -{ - return true; -} - -NS_IMETHODIMP nsChildView::SetFocus(bool aRaise) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindow* window = [mView window]; - if (window) - [window makeFirstResponder:mView]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Override to set the cursor on the mac -NS_IMETHODIMP nsChildView::SetCursor(nsCursor aCursor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if ([mView isDragInProgress]) - return NS_OK; // Don't change the cursor during dragging. - - nsBaseWidget::SetCursor(aCursor); - return [[nsCursorManager sharedInstance] setCursor:aCursor]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// implement to fix "hidden virtual function" warning -NS_IMETHODIMP nsChildView::SetCursor(imgIContainer* aCursor, - uint32_t aHotspotX, uint32_t aHotspotY) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsBaseWidget::SetCursor(aCursor, aHotspotX, aHotspotY); - return [[nsCursorManager sharedInstance] setCursorWithImage:aCursor hotSpotX:aHotspotX hotSpotY:aHotspotY scaleFactor:BackingScaleFactor()]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -#pragma mark - - -// Get this component dimension -LayoutDeviceIntRect -nsChildView::GetBounds() -{ - return !mView ? mBounds : CocoaPointsToDevPixels([mView frame]); -} - -LayoutDeviceIntRect -nsChildView::GetClientBounds() -{ - LayoutDeviceIntRect rect = GetBounds(); - if (!mParentWidget) { - // For top level widgets we want the position on screen, not the position - // of this view inside the window. - rect.MoveTo(WidgetToScreenOffset()); - } - return rect; -} - -LayoutDeviceIntRect -nsChildView::GetScreenBounds() -{ - LayoutDeviceIntRect rect = GetBounds(); - rect.MoveTo(WidgetToScreenOffset()); - return rect; -} - -double -nsChildView::GetDefaultScaleInternal() -{ - return BackingScaleFactor(); -} - -CGFloat -nsChildView::BackingScaleFactor() const -{ - if (mBackingScaleFactor > 0.0) { - return mBackingScaleFactor; - } - if (!mView) { - return 1.0; - } - mBackingScaleFactor = nsCocoaUtils::GetBackingScaleFactor(mView); - return mBackingScaleFactor; -} - -void -nsChildView::BackingScaleFactorChanged() -{ - CGFloat newScale = nsCocoaUtils::GetBackingScaleFactor(mView); - - // ignore notification if it hasn't really changed (or maybe we have - // disabled HiDPI mode via prefs) - if (mBackingScaleFactor == newScale) { - return; - } - - mBackingScaleFactor = newScale; - NSRect frame = [mView frame]; - mBounds = nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, newScale); - - if (mWidgetListener && !mWidgetListener->GetXULWindow()) { - nsIPresShell* presShell = mWidgetListener->GetPresShell(); - if (presShell) { - presShell->BackingScaleFactorChanged(); - } - } -} - -int32_t -nsChildView::RoundsWidgetCoordinatesTo() -{ - if (BackingScaleFactor() == 2.0) { - return 2; - } - return 1; -} - -// Move this component, aX and aY are in the parent widget coordinate system -NS_IMETHODIMP nsChildView::Move(double aX, double aY) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - int32_t x = NSToIntRound(aX); - int32_t y = NSToIntRound(aY); - - if (!mView || (mBounds.x == x && mBounds.y == y)) - return NS_OK; - - mBounds.x = x; - mBounds.y = y; - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setFrame:DevPixelsToCocoaPoints(mBounds)]; - }); - - NotifyRollupGeometryChange(); - ReportMoveEvent(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsChildView::Resize(double aWidth, double aHeight, bool aRepaint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - int32_t width = NSToIntRound(aWidth); - int32_t height = NSToIntRound(aHeight); - - if (!mView || (mBounds.width == width && mBounds.height == height)) - return NS_OK; - - mBounds.width = width; - mBounds.height = height; - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setFrame:DevPixelsToCocoaPoints(mBounds)]; - }); - - if (mVisible && aRepaint) { - [[mView pixelHostingView] setNeedsDisplay:YES]; - } - - NotifyRollupGeometryChange(); - ReportSizeEvent(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsChildView::Resize(double aX, double aY, - double aWidth, double aHeight, bool aRepaint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - int32_t x = NSToIntRound(aX); - int32_t y = NSToIntRound(aY); - int32_t width = NSToIntRound(aWidth); - int32_t height = NSToIntRound(aHeight); - - BOOL isMoving = (mBounds.x != x || mBounds.y != y); - BOOL isResizing = (mBounds.width != width || mBounds.height != height); - if (!mView || (!isMoving && !isResizing)) - return NS_OK; - - if (isMoving) { - mBounds.x = x; - mBounds.y = y; - } - if (isResizing) { - mBounds.width = width; - mBounds.height = height; - } - - ManipulateViewWithoutNeedingDisplay(mView, ^{ - [mView setFrame:DevPixelsToCocoaPoints(mBounds)]; - }); - - if (mVisible && aRepaint) { - [[mView pixelHostingView] setNeedsDisplay:YES]; - } - - NotifyRollupGeometryChange(); - if (isMoving) { - ReportMoveEvent(); - if (mOnDestroyCalled) - return NS_OK; - } - if (isResizing) - ReportSizeEvent(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -static const int32_t resizeIndicatorWidth = 15; -static const int32_t resizeIndicatorHeight = 15; -bool nsChildView::ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect) -{ - NSView *topLevelView = mView, *superView = nil; - while ((superView = [topLevelView superview])) - topLevelView = superView; - - if (![[topLevelView window] showsResizeIndicator] || - !([[topLevelView window] styleMask] & NSResizableWindowMask)) - return false; - - if (aResizerRect) { - NSSize bounds = [topLevelView bounds].size; - NSPoint corner = NSMakePoint(bounds.width, [topLevelView isFlipped] ? bounds.height : 0); - corner = [topLevelView convertPoint:corner toView:mView]; - aResizerRect->SetRect(NSToIntRound(corner.x) - resizeIndicatorWidth, - NSToIntRound(corner.y) - resizeIndicatorHeight, - resizeIndicatorWidth, resizeIndicatorHeight); - } - return true; -} - -nsresult nsChildView::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, - int32_t aNativeKeyCode, - uint32_t aModifierFlags, - const nsAString& aCharacters, - const nsAString& aUnmodifiedCharacters, - nsIObserver* aObserver) -{ - AutoObserverNotifier notifier(aObserver, "keyevent"); - return mTextInputHandler->SynthesizeNativeKeyEvent(aNativeKeyboardLayout, - aNativeKeyCode, - aModifierFlags, - aCharacters, - aUnmodifiedCharacters); -} - -nsresult nsChildView::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - uint32_t aModifierFlags, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "mouseevent"); - - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); - - // Move the mouse cursor to the requested position and reconnect it to the mouse. - CGWarpMouseCursorPosition(NSPointToCGPoint(pt)); - CGAssociateMouseAndMouseCursorPosition(true); - - // aPoint is given with the origin on the top left, but convertScreenToBase - // expects a point in a coordinate system that has its origin on the bottom left. - NSPoint screenPoint = NSMakePoint(pt.x, nsCocoaUtils::FlippedScreenY(pt.y)); - NSPoint windowPoint = - nsCocoaUtils::ConvertPointFromScreen([mView window], screenPoint); - - NSEvent* event = [NSEvent mouseEventWithType:(NSEventType)aNativeMessage - location:windowPoint - modifierFlags:aModifierFlags - timestamp:[[NSProcessInfo processInfo] systemUptime] - windowNumber:[[mView window] windowNumber] - context:nil - eventNumber:0 - clickCount:1 - pressure:0.0]; - - if (!event) - return NS_ERROR_FAILURE; - - if ([[mView window] isKindOfClass:[BaseWindow class]]) { - // Tracking area events don't end up in their tracking areas when sent - // through [NSApp sendEvent:], so pass them directly to the right methods. - BaseWindow* window = (BaseWindow*)[mView window]; - if (aNativeMessage == NSMouseEntered) { - [window mouseEntered:event]; - return NS_OK; - } - if (aNativeMessage == NSMouseExited) { - [window mouseExited:event]; - return NS_OK; - } - if (aNativeMessage == NSMouseMoved) { - [window mouseMoved:event]; - return NS_OK; - } - } - - [NSApp sendEvent:event]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsChildView::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - double aDeltaX, - double aDeltaY, - double aDeltaZ, - uint32_t aModifierFlags, - uint32_t aAdditionalFlags, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "mousescrollevent"); - - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); - - // Move the mouse cursor to the requested position and reconnect it to the mouse. - CGWarpMouseCursorPosition(NSPointToCGPoint(pt)); - CGAssociateMouseAndMouseCursorPosition(true); - - // Mostly copied from http://stackoverflow.com/a/6130349 - CGScrollEventUnit units = - (aAdditionalFlags & nsIDOMWindowUtils::MOUSESCROLL_SCROLL_LINES) - ? kCGScrollEventUnitLine : kCGScrollEventUnitPixel; - CGEventRef cgEvent = CGEventCreateScrollWheelEvent(NULL, units, 3, aDeltaY, aDeltaX, aDeltaZ); - if (!cgEvent) { - return NS_ERROR_FAILURE; - } - - CGEventPost(kCGHIDEventTap, cgEvent); - CFRelease(cgEvent); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsChildView::SynthesizeNativeTouchPoint(uint32_t aPointerId, - TouchPointerState aPointerState, - mozilla::LayoutDeviceIntPoint aPoint, - double aPointerPressure, - uint32_t aPointerOrientation, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "touchpoint"); - - MOZ_ASSERT(NS_IsMainThread()); - if (aPointerState == TOUCH_HOVER) { - return NS_ERROR_UNEXPECTED; - } - - if (!mSynthesizedTouchInput) { - mSynthesizedTouchInput = MakeUnique(); - } - - LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset(); - MultiTouchInput inputToDispatch = UpdateSynthesizedTouchState( - mSynthesizedTouchInput.get(), PR_IntervalNow(), TimeStamp::Now(), - aPointerId, aPointerState, pointInWindow, aPointerPressure, - aPointerOrientation); - DispatchTouchInput(inputToDispatch); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// First argument has to be an NSMenu representing the application's top-level -// menu bar. The returned item is *not* retained. -static NSMenuItem* NativeMenuItemWithLocation(NSMenu* menubar, NSString* locationString) -{ - NSArray* indexes = [locationString componentsSeparatedByString:@"|"]; - unsigned int indexCount = [indexes count]; - if (indexCount == 0) - return nil; - - NSMenu* currentSubmenu = [NSApp mainMenu]; - for (unsigned int i = 0; i < indexCount; i++) { - int targetIndex; - // We remove the application menu from consideration for the top-level menu - if (i == 0) - targetIndex = [[indexes objectAtIndex:i] intValue] + 1; - else - targetIndex = [[indexes objectAtIndex:i] intValue]; - int itemCount = [currentSubmenu numberOfItems]; - if (targetIndex < itemCount) { - NSMenuItem* menuItem = [currentSubmenu itemAtIndex:targetIndex]; - // if this is the last index just return the menu item - if (i == (indexCount - 1)) - return menuItem; - // if this is not the last index find the submenu and keep going - if ([menuItem hasSubmenu]) - currentSubmenu = [menuItem submenu]; - else - return nil; - } - } - - return nil; -} - -// Used for testing native menu system structure and event handling. -NS_IMETHODIMP nsChildView::ActivateNativeMenuItemAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSString* locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSMenuItem* item = NativeMenuItemWithLocation([NSApp mainMenu], locationString); - // We can't perform an action on an item with a submenu, that will raise - // an obj-c exception. - if (item && ![item hasSubmenu]) { - NSMenu* parent = [item menu]; - if (parent) { - // NSLog(@"Performing action for native menu item titled: %@\n", - // [[currentSubmenu itemAtIndex:targetIndex] title]); - [parent performActionForItemAtIndex:[parent indexOfItem:item]]; - return NS_OK; - } - } - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Used for testing native menu system structure and event handling. -NS_IMETHODIMP nsChildView::ForceUpdateNativeMenuAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsCocoaWindow *widget = GetXULWindowWidget(); - if (widget) { - nsMenuBarX* mb = widget->GetMenuBar(); - if (mb) { - if (indexString.IsEmpty()) - mb->ForceNativeMenuReload(); - else - mb->ForceUpdateNativeMenuAt(indexString); - } - } - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -#pragma mark - - -#ifdef INVALIDATE_DEBUGGING - -static Boolean KeyDown(const UInt8 theKey) -{ - KeyMap map; - GetKeys(map); - return ((*((UInt8 *)map + (theKey >> 3)) >> (theKey & 7)) & 1) != 0; -} - -static Boolean caps_lock() -{ - return KeyDown(0x39); -} - -static void blinkRect(Rect* r) -{ - StRegionFromPool oldClip; - if (oldClip != NULL) - ::GetClip(oldClip); - - ::ClipRect(r); - ::InvertRect(r); - UInt32 end = ::TickCount() + 5; - while (::TickCount() < end) ; - ::InvertRect(r); - - if (oldClip != NULL) - ::SetClip(oldClip); -} - -static void blinkRgn(RgnHandle rgn) -{ - StRegionFromPool oldClip; - if (oldClip != NULL) - ::GetClip(oldClip); - - ::SetClip(rgn); - ::InvertRgn(rgn); - UInt32 end = ::TickCount() + 5; - while (::TickCount() < end) ; - ::InvertRgn(rgn); - - if (oldClip != NULL) - ::SetClip(oldClip); -} - -#endif - -// Invalidate this component's visible area -NS_IMETHODIMP nsChildView::Invalidate(const LayoutDeviceIntRect& aRect) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mView || !mVisible) - return NS_OK; - - NS_ASSERTION(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT, - "Shouldn't need to invalidate with accelerated OMTC layers!"); - - [[mView pixelHostingView] setNeedsDisplayInRect:DevPixelsToCocoaPoints(aRect)]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -bool -nsChildView::WidgetTypeSupportsAcceleration() -{ - // Don't use OpenGL for transparent windows or for popup windows. - return mView && [[mView window] isOpaque] && - ![[mView window] isKindOfClass:[PopupWindow class]]; -} - -bool -nsChildView::ShouldUseOffMainThreadCompositing() -{ - // Don't use OMTC for transparent windows or for popup windows. - if (!mView || ![[mView window] isOpaque] || - [[mView window] isKindOfClass:[PopupWindow class]]) - return false; - - return nsBaseWidget::ShouldUseOffMainThreadCompositing(); -} - -inline uint16_t COLOR8TOCOLOR16(uint8_t color8) -{ - // return (color8 == 0xFF ? 0xFFFF : (color8 << 8)); - return (color8 << 8) | color8; /* (color8 * 257) == (color8 * 0x0101) */ -} - -#pragma mark - - -nsresult nsChildView::ConfigureChildren(const nsTArray& aConfigurations) -{ - return NS_OK; -} - -// Invokes callback and ProcessEvent methods on Event Listener object -NS_IMETHODIMP nsChildView::DispatchEvent(WidgetGUIEvent* event, - nsEventStatus& aStatus) -{ - RefPtr kungFuDeathGrip(this); - -#ifdef DEBUG - debug_DumpEvent(stdout, event->mWidget, event, "something", 0); -#endif - - NS_ASSERTION(!(mTextInputHandler && mTextInputHandler->IsIMEComposing() && - event->HasKeyEventMessage()), - "Any key events should not be fired during IME composing"); - - if (event->mFlags.mIsSynthesizedForTests) { - WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent(); - if (keyEvent) { - nsresult rv = mTextInputHandler->AttachNativeKeyEvent(*keyEvent); - NS_ENSURE_SUCCESS(rv, rv); - } - } - - aStatus = nsEventStatus_eIgnore; - - nsIWidgetListener* listener = mWidgetListener; - - // If the listener is NULL, check if the parent is a popup. If it is, then - // this child is the popup content view attached to a popup. Get the - // listener from the parent popup instead. - nsCOMPtr parentWidget = mParentWidget; - if (!listener && parentWidget) { - if (parentWidget->WindowType() == eWindowType_popup) { - // Check just in case event->mWidget isn't this widget - if (event->mWidget) { - listener = event->mWidget->GetWidgetListener(); - } - if (!listener) { - event->mWidget = parentWidget; - listener = parentWidget->GetWidgetListener(); - } - } - } - - if (listener) - aStatus = listener->HandleEvent(event, mUseAttachedEvents); - - return NS_OK; -} - -bool nsChildView::DispatchWindowEvent(WidgetGUIEvent& event) -{ - nsEventStatus status; - DispatchEvent(&event, status); - return ConvertStatus(status); -} - -nsIWidget* -nsChildView::GetWidgetForListenerEvents() -{ - // If there is no listener, use the parent popup's listener if that exists. - if (!mWidgetListener && mParentWidget && - mParentWidget->WindowType() == eWindowType_popup) { - return mParentWidget; - } - - return this; -} - -void nsChildView::WillPaintWindow() -{ - nsCOMPtr widget = GetWidgetForListenerEvents(); - - nsIWidgetListener* listener = widget->GetWidgetListener(); - if (listener) { - listener->WillPaintWindow(widget); - } -} - -bool nsChildView::PaintWindow(LayoutDeviceIntRegion aRegion) -{ - nsCOMPtr widget = GetWidgetForListenerEvents(); - - nsIWidgetListener* listener = widget->GetWidgetListener(); - if (!listener) - return false; - - bool returnValue = false; - bool oldDispatchPaint = mIsDispatchPaint; - mIsDispatchPaint = true; - returnValue = listener->PaintWindow(widget, aRegion); - - listener = widget->GetWidgetListener(); - if (listener) { - listener->DidPaintWindow(); - } - - mIsDispatchPaint = oldDispatchPaint; - return returnValue; -} - -bool -nsChildView::PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion, gfx::IntSize aSurfaceSize) -{ - if (!mBackingSurface || mBackingSurface->GetSize() != aSurfaceSize) { - mBackingSurface = - gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(aSurfaceSize, - gfx::SurfaceFormat::B8G8R8A8); - if (!mBackingSurface) { - return false; - } - } - - RefPtr targetContext = gfxContext::CreateOrNull(mBackingSurface); - MOZ_ASSERT(targetContext); // already checked the draw target above - - // Set up the clip region and clear existing contents in the backing surface. - targetContext->NewPath(); - for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - targetContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height)); - mBackingSurface->ClearRect(gfx::Rect(r.ToUnknownRect())); - } - targetContext->Clip(); - - nsAutoRetainCocoaObject kungFuDeathGrip(mView); - bool painted = false; - if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { - nsBaseWidget::AutoLayerManagerSetup - setupLayerManager(this, targetContext, BufferMode::BUFFER_NONE); - painted = PaintWindow(aRegion); - } else if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { - // We only need this so that we actually get DidPaintWindow fired - painted = PaintWindow(aRegion); - } - - uint8_t* data; - gfx::IntSize size; - int32_t stride; - gfx::SurfaceFormat format; - - if (!mBackingSurface->LockBits(&data, &size, &stride, &format)) { - return false; - } - - // Draw the backing surface onto the window. - CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, stride * size.height, NULL); - NSColorSpace* colorSpace = [[mView window] colorSpace]; - CGImageRef image = CGImageCreate(size.width, size.height, 8, 32, stride, - [colorSpace CGColorSpace], - kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst, - provider, NULL, false, kCGRenderingIntentDefault); - CGContextSaveGState(aContext); - CGContextTranslateCTM(aContext, 0, size.height); - CGContextScaleCTM(aContext, 1, -1); - CGContextSetBlendMode(aContext, kCGBlendModeCopy); - CGContextDrawImage(aContext, CGRectMake(0, 0, size.width, size.height), image); - CGImageRelease(image); - CGDataProviderRelease(provider); - CGContextRestoreGState(aContext); - - mBackingSurface->ReleaseBits(data); - - return painted; -} - -#pragma mark - - -void nsChildView::ReportMoveEvent() -{ - NotifyWindowMoved(mBounds.x, mBounds.y); -} - -void nsChildView::ReportSizeEvent() -{ - if (mWidgetListener) - mWidgetListener->WindowResized(this, mBounds.width, mBounds.height); -} - -#pragma mark - - -LayoutDeviceIntPoint nsChildView::GetClientOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSPoint origin = [mView convertPoint:NSMakePoint(0, 0) toView:nil]; - origin.y = [[mView window] frame].size.height - origin.y; - return CocoaPointsToDevPixels(origin); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0)); -} - -// Return the offset between this child view and the screen. -// @return -- widget origin in device-pixel coords -LayoutDeviceIntPoint nsChildView::WidgetToScreenOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSPoint origin = NSMakePoint(0, 0); - - // 1. First translate view origin point into window coords. - // The returned point is in bottom-left coordinates. - origin = [mView convertPoint:origin toView:nil]; - - // 2. We turn the window-coord rect's origin into screen (still bottom-left) coords. - origin = nsCocoaUtils::ConvertPointToScreen([mView window], origin); - - // 3. Since we're dealing in bottom-left coords, we need to make it top-left coords - // before we pass it back to Gecko. - FlipCocoaScreenCoordinate(origin); - - // convert to device pixels - return CocoaPointsToDevPixels(origin); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0,0)); -} - -NS_IMETHODIMP nsChildView::SetTitle(const nsAString& title) -{ - // child views don't have titles - return NS_OK; -} - -NS_IMETHODIMP nsChildView::GetAttention(int32_t aCycleCount) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - [NSApp requestUserAttention:NSInformationalRequest]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -/* static */ -bool nsChildView::DoHasPendingInputEvent() -{ - return sLastInputEventCount != GetCurrentInputEventCount(); -} - -/* static */ -uint32_t nsChildView::GetCurrentInputEventCount() -{ - // Can't use kCGAnyInputEventType because that updates too rarely for us (and - // always in increments of 30+!) and because apparently it's sort of broken - // on Tiger. So just go ahead and query the counters we care about. - static const CGEventType eventTypes[] = { - kCGEventLeftMouseDown, - kCGEventLeftMouseUp, - kCGEventRightMouseDown, - kCGEventRightMouseUp, - kCGEventMouseMoved, - kCGEventLeftMouseDragged, - kCGEventRightMouseDragged, - kCGEventKeyDown, - kCGEventKeyUp, - kCGEventScrollWheel, - kCGEventTabletPointer, - kCGEventOtherMouseDown, - kCGEventOtherMouseUp, - kCGEventOtherMouseDragged - }; - - uint32_t eventCount = 0; - for (uint32_t i = 0; i < ArrayLength(eventTypes); ++i) { - eventCount += - CGEventSourceCounterForEventType(kCGEventSourceStateCombinedSessionState, - eventTypes[i]); - } - return eventCount; -} - -/* static */ -void nsChildView::UpdateCurrentInputEventCount() -{ - sLastInputEventCount = GetCurrentInputEventCount(); -} - -bool nsChildView::HasPendingInputEvent() -{ - return DoHasPendingInputEvent(); -} - -#pragma mark - - -NS_IMETHODIMP -nsChildView::StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent, - int32_t aPanelX, int32_t aPanelY, - nsString& aCommitted) -{ - NS_ENSURE_TRUE(mView, NS_ERROR_NOT_AVAILABLE); - - ComplexTextInputPanel* ctiPanel = - ComplexTextInputPanel::GetSharedComplexTextInputPanel(); - - ctiPanel->PlacePanel(aPanelX, aPanelY); - // We deliberately don't use TextInputHandler::GetCurrentKeyEvent() to - // obtain the NSEvent* we pass to InterpretKeyEvent(). This works fine in - // non-e10s mode. But in e10s mode TextInputHandler::HandleKeyDownEvent() - // has already returned, so the relevant KeyEventState* (and its NSEvent*) - // is already out of scope. Furthermore we don't *need* to use it. - // StartPluginIME() is only ever called to start a new IME session when none - // currently exists. So nested IME should never reach here, and so it should - // be fine to use the last key-down event received by -[ChildView keyDown:] - // (as we currently do). - ctiPanel->InterpretKeyEvent([(ChildView*)mView lastKeyDownEvent], aCommitted); - - return NS_OK; -} - -void -nsChildView::SetPluginFocused(bool& aFocused) -{ - if (aFocused == mPluginFocused) { - return; - } - if (!aFocused) { - ComplexTextInputPanel* ctiPanel = - ComplexTextInputPanel::GetSharedComplexTextInputPanel(); - if (ctiPanel) { - ctiPanel->CancelComposition(); - } - } - mPluginFocused = aFocused; -} - -NS_IMETHODIMP_(void) -nsChildView::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - NS_ENSURE_TRUE_VOID(mTextInputHandler); - - if (mTextInputHandler->IsFocused()) { - if (aContext.IsPasswordEditor()) { - TextInputHandler::EnableSecureEventInput(); - } else { - TextInputHandler::EnsureSecureEventInputDisabled(); - } - } - - mInputContext = aContext; - switch (aContext.mIMEState.mEnabled) { - case IMEState::ENABLED: - case IMEState::PLUGIN: - mTextInputHandler->SetASCIICapableOnly(false); - mTextInputHandler->EnableIME(true); - if (mInputContext.mIMEState.mOpen != IMEState::DONT_CHANGE_OPEN_STATE) { - mTextInputHandler->SetIMEOpenState( - mInputContext.mIMEState.mOpen == IMEState::OPEN); - } - break; - case IMEState::DISABLED: - mTextInputHandler->SetASCIICapableOnly(false); - mTextInputHandler->EnableIME(false); - break; - case IMEState::PASSWORD: - mTextInputHandler->SetASCIICapableOnly(true); - mTextInputHandler->EnableIME(false); - break; - default: - NS_ERROR("not implemented!"); - } -} - -NS_IMETHODIMP_(InputContext) -nsChildView::GetInputContext() -{ - switch (mInputContext.mIMEState.mEnabled) { - case IMEState::ENABLED: - case IMEState::PLUGIN: - if (mTextInputHandler) { - mInputContext.mIMEState.mOpen = - mTextInputHandler->IsIMEOpened() ? IMEState::OPEN : IMEState::CLOSED; - break; - } - // If mTextInputHandler is null, set CLOSED instead... - MOZ_FALLTHROUGH; - default: - mInputContext.mIMEState.mOpen = IMEState::CLOSED; - break; - } - return mInputContext; -} - -NS_IMETHODIMP_(TextEventDispatcherListener*) -nsChildView::GetNativeTextEventDispatcherListener() -{ - if (NS_WARN_IF(!mTextInputHandler)) { - return nullptr; - } - return mTextInputHandler; -} - -NS_IMETHODIMP -nsChildView::AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) -{ - NS_ENSURE_TRUE(mTextInputHandler, NS_ERROR_NOT_AVAILABLE); - return mTextInputHandler->AttachNativeKeyEvent(aEvent); -} - -bool -nsChildView::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData, - uint32_t aGeckoKeyCode, - uint32_t aCocoaKeyCode) -{ - NSEvent *originalEvent = reinterpret_cast(aEvent.mNativeKeyEvent); - - WidgetKeyboardEvent modifiedEvent(aEvent); - modifiedEvent.mKeyCode = aGeckoKeyCode; - - unichar ch = nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(aGeckoKeyCode); - NSString *chars = - [[[NSString alloc] initWithCharacters:&ch length:1] autorelease]; - - modifiedEvent.mNativeKeyEvent = - [NSEvent keyEventWithType:[originalEvent type] - location:[originalEvent locationInWindow] - modifierFlags:[originalEvent modifierFlags] - timestamp:[originalEvent timestamp] - windowNumber:[originalEvent windowNumber] - context:[originalEvent context] - characters:chars - charactersIgnoringModifiers:chars - isARepeat:[originalEvent isARepeat] - keyCode:aCocoaKeyCode]; - - NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData); -} - -NS_IMETHODIMP_(bool) -nsChildView::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) -{ - // If the key is a cursor-movement arrow, and the current selection has - // vertical writing-mode, we'll remap so that the movement command - // generated (in terms of characters/lines) will be appropriate for - // the physical direction of the arrow. - if (aEvent.mKeyCode >= NS_VK_LEFT && aEvent.mKeyCode <= NS_VK_DOWN) { - WidgetQueryContentEvent query(true, eQuerySelectedText, this); - DispatchWindowEvent(query); - - if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) { - uint32_t geckoKey = 0; - uint32_t cocoaKey = 0; - - switch (aEvent.mKeyCode) { - case NS_VK_LEFT: - if (query.mReply.mWritingMode.IsVerticalLR()) { - geckoKey = NS_VK_UP; - cocoaKey = kVK_UpArrow; - } else { - geckoKey = NS_VK_DOWN; - cocoaKey = kVK_DownArrow; - } - break; - - case NS_VK_RIGHT: - if (query.mReply.mWritingMode.IsVerticalLR()) { - geckoKey = NS_VK_DOWN; - cocoaKey = kVK_DownArrow; - } else { - geckoKey = NS_VK_UP; - cocoaKey = kVK_UpArrow; - } - break; - - case NS_VK_UP: - geckoKey = NS_VK_LEFT; - cocoaKey = kVK_LeftArrow; - break; - - case NS_VK_DOWN: - geckoKey = NS_VK_RIGHT; - cocoaKey = kVK_RightArrow; - break; - } - - return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback, - aCallbackData, - geckoKey, cocoaKey); - } - } - - NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); -} - -nsIMEUpdatePreference -nsChildView::GetIMEUpdatePreference() -{ - // XXX Shouldn't we move floating window which shows composition string - // when plugin has focus and its parent is scrolled or the window is - // moved? - return nsIMEUpdatePreference(); -} - -NSView* nsChildView::GetEditorView() -{ - NSView* editorView = mView; - // We need to get editor's view. E.g., when the focus is in the bookmark - // dialog, the view is element of the dialog. At this time, the key - // events are processed the parent window's view that has native focus. - WidgetQueryContentEvent textContent(true, eQueryTextContent, this); - textContent.InitForQueryTextContent(0, 0); - DispatchWindowEvent(textContent); - if (textContent.mSucceeded && textContent.mReply.mFocusedWidget) { - NSView* view = static_cast*>( - textContent.mReply.mFocusedWidget->GetNativeData(NS_NATIVE_WIDGET)); - if (view) - editorView = view; - } - return editorView; -} - -#pragma mark - - -void -nsChildView::CreateCompositor() -{ - nsBaseWidget::CreateCompositor(); - if (mCompositorBridgeChild) { - [(ChildView *)mView setUsingOMTCompositor:true]; - } -} - -void -nsChildView::ConfigureAPZCTreeManager() -{ - nsBaseWidget::ConfigureAPZCTreeManager(); -} - -void -nsChildView::ConfigureAPZControllerThread() -{ - if (gfxPrefs::AsyncPanZoomSeparateEventThread()) { - // The EventThreadRunner is the controller thread, but it doesn't - // have a MessageLoop. - APZThreadUtils::SetControllerThread(nullptr); - } else { - nsBaseWidget::ConfigureAPZControllerThread(); - } -} - -LayoutDeviceIntRect -nsChildView::RectContainingTitlebarControls() -{ - // Start with a thin strip at the top of the window for the highlight line. - NSRect rect = NSMakeRect(0, 0, [mView bounds].size.width, - [(ChildView*)mView cornerRadius]); - - // If we draw the titlebar title string, increase the height to the default - // titlebar height. This height does not necessarily include all the titlebar - // controls because we may have moved them further down, but at least it will - // include the whole title text. - BaseWindow* window = (BaseWindow*)[mView window]; - if ([window wantsTitleDrawn] && [window isKindOfClass:[ToolbarWindow class]]) { - CGFloat defaultTitlebarHeight = [(ToolbarWindow*)window titlebarHeight]; - rect.size.height = std::max(rect.size.height, defaultTitlebarHeight); - } - - // Add the rects of the titlebar controls. - for (id view in [window titlebarControls]) { - rect = NSUnionRect(rect, [mView convertRect:[view bounds] fromView:view]); - } - return CocoaPointsToDevPixels(rect); -} - -void -nsChildView::PrepareWindowEffects() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - bool canBeOpaque; - { - MutexAutoLock lock(mEffectsLock); - mShowsResizeIndicator = ShowsResizeIndicator(&mResizeIndicatorRect); - mHasRoundedBottomCorners = [(ChildView*)mView hasRoundedBottomCorners]; - CGFloat cornerRadius = [(ChildView*)mView cornerRadius]; - mDevPixelCornerRadius = cornerRadius * BackingScaleFactor(); - mIsCoveringTitlebar = [(ChildView*)mView isCoveringTitlebar]; - NSInteger styleMask = [[mView window] styleMask]; - bool wasFullscreen = mIsFullscreen; - mIsFullscreen = (styleMask & NSFullScreenWindowMask) || !(styleMask & NSTitledWindowMask); - - canBeOpaque = mIsFullscreen && wasFullscreen; - if (canBeOpaque && VibrancyManager::SystemSupportsVibrancy()) { - canBeOpaque = !EnsureVibrancyManager().HasVibrantRegions(); - } - if (mIsCoveringTitlebar) { - mTitlebarRect = RectContainingTitlebarControls(); - UpdateTitlebarCGContext(); - } - } - - // If we've just transitioned into or out of full screen then update the opacity on our GLContext. - if (canBeOpaque != mIsOpaque) { - mIsOpaque = canBeOpaque; - [(ChildView*)mView setGLOpaque:canBeOpaque]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsChildView::CleanupWindowEffects() -{ - mResizerImage = nullptr; - mCornerMaskImage = nullptr; - mTitlebarImage = nullptr; -} - -bool -nsChildView::PreRender(WidgetRenderingContext* aContext) -{ - UniquePtr manager(GLManager::CreateGLManager(aContext->mLayerManager)); - if (!manager) { - return true; - } - - // The lock makes sure that we don't attempt to tear down the view while - // compositing. That would make us unable to call postRender on it when the - // composition is done, thus keeping the GL context locked forever. - mViewTearDownLock.Lock(); - - NSOpenGLContext *glContext = GLContextCGL::Cast(manager->gl())->GetNSOpenGLContext(); - - if (![(ChildView*)mView preRender:glContext]) { - mViewTearDownLock.Unlock(); - return false; - } - return true; -} - -void -nsChildView::PostRender(WidgetRenderingContext* aContext) -{ - UniquePtr manager(GLManager::CreateGLManager(aContext->mLayerManager)); - if (!manager) { - return; - } - NSOpenGLContext *glContext = GLContextCGL::Cast(manager->gl())->GetNSOpenGLContext(); - [(ChildView*)mView postRender:glContext]; - mViewTearDownLock.Unlock(); -} - -void -nsChildView::DrawWindowOverlay(WidgetRenderingContext* aContext, - LayoutDeviceIntRect aRect) -{ - mozilla::UniquePtr manager(GLManager::CreateGLManager(aContext->mLayerManager)); - if (manager) { - DrawWindowOverlay(manager.get(), aRect); - } -} - -void -nsChildView::DrawWindowOverlay(GLManager* aManager, LayoutDeviceIntRect aRect) -{ - GLContext* gl = aManager->gl(); - ScopedGLState scopedScissorTestState(gl, LOCAL_GL_SCISSOR_TEST, false); - - MaybeDrawTitlebar(aManager); - MaybeDrawResizeIndicator(aManager); - MaybeDrawRoundedCorners(aManager, aRect); -} - -static void -ClearRegion(gfx::DrawTarget *aDT, LayoutDeviceIntRegion aRegion) -{ - gfxUtils::ClipToRegion(aDT, aRegion.ToUnknownRegion()); - aDT->ClearRect(gfx::Rect(0, 0, aDT->GetSize().width, aDT->GetSize().height)); - aDT->PopClip(); -} - -static void -DrawResizer(CGContextRef aCtx) -{ - CGContextSetShouldAntialias(aCtx, false); - CGPoint points[6]; - points[0] = CGPointMake(13.0f, 4.0f); - points[1] = CGPointMake(3.0f, 14.0f); - points[2] = CGPointMake(13.0f, 8.0f); - points[3] = CGPointMake(7.0f, 14.0f); - points[4] = CGPointMake(13.0f, 12.0f); - points[5] = CGPointMake(11.0f, 14.0f); - CGContextSetRGBStrokeColor(aCtx, 0.00f, 0.00f, 0.00f, 0.15f); - CGContextStrokeLineSegments(aCtx, points, 6); - - points[0] = CGPointMake(13.0f, 5.0f); - points[1] = CGPointMake(4.0f, 14.0f); - points[2] = CGPointMake(13.0f, 9.0f); - points[3] = CGPointMake(8.0f, 14.0f); - points[4] = CGPointMake(13.0f, 13.0f); - points[5] = CGPointMake(12.0f, 14.0f); - CGContextSetRGBStrokeColor(aCtx, 0.13f, 0.13f, 0.13f, 0.54f); - CGContextStrokeLineSegments(aCtx, points, 6); - - points[0] = CGPointMake(13.0f, 6.0f); - points[1] = CGPointMake(5.0f, 14.0f); - points[2] = CGPointMake(13.0f, 10.0f); - points[3] = CGPointMake(9.0f, 14.0f); - points[5] = CGPointMake(13.0f, 13.9f); - points[4] = CGPointMake(13.0f, 14.0f); - CGContextSetRGBStrokeColor(aCtx, 0.84f, 0.84f, 0.84f, 0.55f); - CGContextStrokeLineSegments(aCtx, points, 6); -} - -void -nsChildView::MaybeDrawResizeIndicator(GLManager* aManager) -{ - MutexAutoLock lock(mEffectsLock); - if (!mShowsResizeIndicator) { - return; - } - - if (!mResizerImage) { - mResizerImage = MakeUnique(); - } - - LayoutDeviceIntSize size = mResizeIndicatorRect.Size(); - mResizerImage->UpdateIfNeeded(size, LayoutDeviceIntRegion(), ^(gfx::DrawTarget* drawTarget, const LayoutDeviceIntRegion& updateRegion) { - ClearRegion(drawTarget, updateRegion); - gfx::BorrowedCGContext borrow(drawTarget); - DrawResizer(borrow.cg); - borrow.Finish(); - }); - - mResizerImage->Draw(aManager, mResizeIndicatorRect.TopLeft()); -} - -// Draw the highlight line at the top of the titlebar. -// This function draws into the current NSGraphicsContext and assumes flippedness. -static void -DrawTitlebarHighlight(NSSize aWindowSize, CGFloat aRadius, CGFloat aDevicePixelWidth) -{ - [NSGraphicsContext saveGraphicsState]; - - // Set up the clip path. We start with the outer rectangle and cut out a - // slightly smaller inner rectangle with rounded corners. - // The outer corners of the resulting path will be square, but they will be - // masked away in a later step. - NSBezierPath* path = [NSBezierPath bezierPath]; - [path setWindingRule:NSEvenOddWindingRule]; - NSRect pathRect = NSMakeRect(0, 0, aWindowSize.width, aRadius + 2); - [path appendBezierPathWithRect:pathRect]; - pathRect = NSInsetRect(pathRect, aDevicePixelWidth, aDevicePixelWidth); - CGFloat innerRadius = aRadius - aDevicePixelWidth; - [path appendBezierPathWithRoundedRect:pathRect xRadius:innerRadius yRadius:innerRadius]; - [path addClip]; - - // Now we fill the path with a subtle highlight gradient. - // We don't use NSGradient because it's 5x to 15x slower than the manual fill, - // as indicated by the performance test in bug 880620. - for (CGFloat y = 0; y < aRadius; y += aDevicePixelWidth) { - CGFloat t = y / aRadius; - [[NSColor colorWithDeviceWhite:1.0 alpha:0.4 * (1.0 - t)] set]; - NSRectFillUsingOperation(NSMakeRect(0, y, aWindowSize.width, aDevicePixelWidth), NSCompositeSourceOver); - } - - [NSGraphicsContext restoreGraphicsState]; -} - -static CGContextRef -CreateCGContext(const LayoutDeviceIntSize& aSize) -{ - CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); - CGContextRef ctx = - CGBitmapContextCreate(NULL, - aSize.width, - aSize.height, - 8 /* bitsPerComponent */, - aSize.width * 4, - cs, - kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(cs); - - CGContextTranslateCTM(ctx, 0, aSize.height); - CGContextScaleCTM(ctx, 1, -1); - CGContextSetInterpolationQuality(ctx, kCGInterpolationLow); - - return ctx; -} - -LayoutDeviceIntSize -TextureSizeForSize(const LayoutDeviceIntSize& aSize) -{ - return LayoutDeviceIntSize(RoundUpPow2(aSize.width), - RoundUpPow2(aSize.height)); -} - -// When this method is entered, mEffectsLock is already being held. -void -nsChildView::UpdateTitlebarCGContext() -{ - if (mTitlebarRect.IsEmpty()) { - ReleaseTitlebarCGContext(); - return; - } - - NSRect titlebarRect = DevPixelsToCocoaPoints(mTitlebarRect); - NSRect dirtyRect = [mView convertRect:[(BaseWindow*)[mView window] getAndResetNativeDirtyRect] fromView:nil]; - NSRect dirtyTitlebarRect = NSIntersectionRect(titlebarRect, dirtyRect); - - LayoutDeviceIntSize texSize = TextureSizeForSize(mTitlebarRect.Size()); - if (!mTitlebarCGContext || - CGBitmapContextGetWidth(mTitlebarCGContext) != size_t(texSize.width) || - CGBitmapContextGetHeight(mTitlebarCGContext) != size_t(texSize.height)) { - dirtyTitlebarRect = titlebarRect; - - ReleaseTitlebarCGContext(); - - mTitlebarCGContext = CreateCGContext(texSize); - } - - if (NSIsEmptyRect(dirtyTitlebarRect)) { - return; - } - - CGContextRef ctx = mTitlebarCGContext; - - CGContextSaveGState(ctx); - - double scale = BackingScaleFactor(); - CGContextScaleCTM(ctx, scale, scale); - - CGContextClipToRect(ctx, NSRectToCGRect(dirtyTitlebarRect)); - CGContextClearRect(ctx, NSRectToCGRect(dirtyTitlebarRect)); - - NSGraphicsContext* oldContext = [NSGraphicsContext currentContext]; - - CGContextSaveGState(ctx); - - BaseWindow* window = (BaseWindow*)[mView window]; - NSView* frameView = [[window contentView] superview]; - if (![frameView isFlipped]) { - CGContextTranslateCTM(ctx, 0, [frameView bounds].size.height); - CGContextScaleCTM(ctx, 1, -1); - } - NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[frameView isFlipped]]; - [NSGraphicsContext setCurrentContext:context]; - - // Draw the title string. - if ([window wantsTitleDrawn] && [frameView respondsToSelector:@selector(_drawTitleBar:)]) { - [frameView _drawTitleBar:[frameView bounds]]; - } - - // Draw the titlebar controls into the titlebar image. - for (id view in [window titlebarControls]) { - NSRect viewFrame = [view frame]; - NSRect viewRect = [mView convertRect:viewFrame fromView:frameView]; - if (!NSIntersectsRect(dirtyTitlebarRect, viewRect)) { - continue; - } - // All of the titlebar controls we're interested in are subclasses of - // NSButton. - if (![view isKindOfClass:[NSButton class]]) { - continue; - } - NSButton *button = (NSButton *) view; - id cellObject = [button cell]; - if (![cellObject isKindOfClass:[NSCell class]]) { - continue; - } - NSCell *cell = (NSCell *) cellObject; - - CGContextSaveGState(ctx); - CGContextTranslateCTM(ctx, viewFrame.origin.x, viewFrame.origin.y); - - if ([context isFlipped] != [view isFlipped]) { - CGContextTranslateCTM(ctx, 0, viewFrame.size.height); - CGContextScaleCTM(ctx, 1, -1); - } - - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[view isFlipped]]]; - - if ([window useBrightTitlebarForeground] && !nsCocoaFeatures::OnYosemiteOrLater() && - view == [window standardWindowButton:NSWindowFullScreenButton]) { - // Make the fullscreen button visible on dark titlebar backgrounds by - // drawing it into a new transparency layer and turning it white. - CGRect r = NSRectToCGRect([view bounds]); - CGContextBeginTransparencyLayerWithRect(ctx, r, nullptr); - - // Draw twice for double opacity. - [cell drawWithFrame:[button bounds] inView:button]; - [cell drawWithFrame:[button bounds] inView:button]; - - // Make it white. - CGContextSetBlendMode(ctx, kCGBlendModeSourceIn); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextFillRect(ctx, r); - CGContextSetBlendMode(ctx, kCGBlendModeNormal); - - CGContextEndTransparencyLayer(ctx); - } else { - [cell drawWithFrame:[button bounds] inView:button]; - } - - [NSGraphicsContext setCurrentContext:context]; - CGContextRestoreGState(ctx); - } - - CGContextRestoreGState(ctx); - - DrawTitlebarHighlight([frameView bounds].size, [(ChildView*)mView cornerRadius], - DevPixelsToCocoaPoints(1)); - - [NSGraphicsContext setCurrentContext:oldContext]; - - CGContextRestoreGState(ctx); - - mUpdatedTitlebarRegion.OrWith(CocoaPointsToDevPixels(dirtyTitlebarRect)); -} - -// This method draws an overlay in the top of the window which contains the -// titlebar controls (e.g. close, min, zoom, fullscreen) and the titlebar -// highlight effect. -// This is necessary because the real titlebar controls are covered by our -// OpenGL context. Note that in terms of the NSView hierarchy, our ChildView -// is actually below the titlebar controls - that's why hovering and clicking -// them works as expected - but their visual representation is only drawn into -// the normal window buffer, and the window buffer surface lies below the -// GLContext surface. In order to make the titlebar controls visible, we have -// to redraw them inside the OpenGL context surface. -void -nsChildView::MaybeDrawTitlebar(GLManager* aManager) -{ - MutexAutoLock lock(mEffectsLock); - if (!mIsCoveringTitlebar || mIsFullscreen) { - return; - } - - LayoutDeviceIntRegion updatedTitlebarRegion; - updatedTitlebarRegion.And(mUpdatedTitlebarRegion, mTitlebarRect); - mUpdatedTitlebarRegion.SetEmpty(); - - if (!mTitlebarImage) { - mTitlebarImage = MakeUnique(); - } - - mTitlebarImage->UpdateFromCGContext(mTitlebarRect.Size(), - updatedTitlebarRegion, - mTitlebarCGContext); - - mTitlebarImage->Draw(aManager, mTitlebarRect.TopLeft()); -} - -static void -DrawTopLeftCornerMask(CGContextRef aCtx, int aRadius) -{ - CGContextSetRGBFillColor(aCtx, 1.0, 1.0, 1.0, 1.0); - CGContextFillEllipseInRect(aCtx, CGRectMake(0, 0, aRadius * 2, aRadius * 2)); -} - -void -nsChildView::MaybeDrawRoundedCorners(GLManager* aManager, - const LayoutDeviceIntRect& aRect) -{ - MutexAutoLock lock(mEffectsLock); - - if (!mCornerMaskImage) { - mCornerMaskImage = MakeUnique(); - } - - LayoutDeviceIntSize size(mDevPixelCornerRadius, mDevPixelCornerRadius); - mCornerMaskImage->UpdateIfNeeded(size, LayoutDeviceIntRegion(), ^(gfx::DrawTarget* drawTarget, const LayoutDeviceIntRegion& updateRegion) { - ClearRegion(drawTarget, updateRegion); - RefPtr builder = drawTarget->CreatePathBuilder(); - builder->Arc(gfx::Point(mDevPixelCornerRadius, mDevPixelCornerRadius), mDevPixelCornerRadius, 0, 2.0f * M_PI); - RefPtr path = builder->Finish(); - drawTarget->Fill(path, - gfx::ColorPattern(gfx::Color(1.0, 1.0, 1.0, 1.0)), - gfx::DrawOptions(1.0f, gfx::CompositionOp::OP_SOURCE)); - }); - - // Use operator destination in: multiply all 4 channels with source alpha. - aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA, - LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA); - - Matrix4x4 flipX = Matrix4x4::Scaling(-1, 1, 1); - Matrix4x4 flipY = Matrix4x4::Scaling(1, -1, 1); - - if (mIsCoveringTitlebar && !mIsFullscreen) { - // Mask the top corners. - mCornerMaskImage->Draw(aManager, aRect.TopLeft()); - mCornerMaskImage->Draw(aManager, aRect.TopRight(), flipX); - } - - if (mHasRoundedBottomCorners && !mIsFullscreen) { - // Mask the bottom corners. - mCornerMaskImage->Draw(aManager, aRect.BottomLeft(), flipY); - mCornerMaskImage->Draw(aManager, aRect.BottomRight(), flipY * flipX); - } - - // Reset blend mode. - aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); -} - -static int32_t -FindTitlebarBottom(const nsTArray& aThemeGeometries, - int32_t aWindowWidth) -{ - int32_t titlebarBottom = 0; - for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if ((g.mType == nsNativeThemeCocoa::eThemeGeometryTypeTitlebar) && - g.mRect.X() <= 0 && - g.mRect.XMost() >= aWindowWidth && - g.mRect.Y() <= 0) { - titlebarBottom = std::max(titlebarBottom, g.mRect.YMost()); - } - } - return titlebarBottom; -} - -static int32_t -FindUnifiedToolbarBottom(const nsTArray& aThemeGeometries, - int32_t aWindowWidth, int32_t aTitlebarBottom) -{ - int32_t unifiedToolbarBottom = aTitlebarBottom; - for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if ((g.mType == nsNativeThemeCocoa::eThemeGeometryTypeToolbar) && - g.mRect.X() <= 0 && - g.mRect.XMost() >= aWindowWidth && - g.mRect.Y() <= aTitlebarBottom) { - unifiedToolbarBottom = std::max(unifiedToolbarBottom, g.mRect.YMost()); - } - } - return unifiedToolbarBottom; -} - -static LayoutDeviceIntRect -FindFirstRectOfType(const nsTArray& aThemeGeometries, - nsITheme::ThemeGeometryType aThemeGeometryType) -{ - for (uint32_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if (g.mType == aThemeGeometryType) { - return g.mRect; - } - } - return LayoutDeviceIntRect(); -} - -void -nsChildView::UpdateThemeGeometries(const nsTArray& aThemeGeometries) -{ - if (![mView window]) - return; - - UpdateVibrancy(aThemeGeometries); - - if (![[mView window] isKindOfClass:[ToolbarWindow class]]) - return; - - // Update unified toolbar height and sheet attachment position. - int32_t windowWidth = mBounds.width; - int32_t titlebarBottom = FindTitlebarBottom(aThemeGeometries, windowWidth); - int32_t unifiedToolbarBottom = - FindUnifiedToolbarBottom(aThemeGeometries, windowWidth, titlebarBottom); - int32_t toolboxBottom = - FindFirstRectOfType(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeToolbox).YMost(); - - ToolbarWindow* win = (ToolbarWindow*)[mView window]; - bool drawsContentsIntoWindowFrame = [win drawsContentsIntoWindowFrame]; - int32_t titlebarHeight = CocoaPointsToDevPixels([win titlebarHeight]); - int32_t contentOffset = drawsContentsIntoWindowFrame ? titlebarHeight : 0; - int32_t devUnifiedHeight = titlebarHeight + unifiedToolbarBottom - contentOffset; - [win setUnifiedToolbarHeight:DevPixelsToCocoaPoints(devUnifiedHeight)]; - int32_t devSheetPosition = titlebarHeight + std::max(toolboxBottom, unifiedToolbarBottom) - contentOffset; - [win setSheetAttachmentPosition:DevPixelsToCocoaPoints(devSheetPosition)]; - - // Update titlebar control offsets. - LayoutDeviceIntRect windowButtonRect = FindFirstRectOfType(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeWindowButtons); - [win placeWindowButtons:[mView convertRect:DevPixelsToCocoaPoints(windowButtonRect) toView:nil]]; - LayoutDeviceIntRect fullScreenButtonRect = FindFirstRectOfType(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeFullscreenButton); - [win placeFullScreenButton:[mView convertRect:DevPixelsToCocoaPoints(fullScreenButtonRect) toView:nil]]; -} - -static LayoutDeviceIntRegion -GatherThemeGeometryRegion(const nsTArray& aThemeGeometries, - nsITheme::ThemeGeometryType aThemeGeometryType) -{ - LayoutDeviceIntRegion region; - for (size_t i = 0; i < aThemeGeometries.Length(); ++i) { - const nsIWidget::ThemeGeometry& g = aThemeGeometries[i]; - if (g.mType == aThemeGeometryType) { - region.OrWith(g.mRect); - } - } - return region; -} - -template -static void MakeRegionsNonOverlappingImpl(Region& aOutUnion) { } - -template -static void MakeRegionsNonOverlappingImpl(Region& aOutUnion, Region& aFirst, Regions& ... aRest) -{ - MakeRegionsNonOverlappingImpl(aOutUnion, aRest...); - aFirst.SubOut(aOutUnion); - aOutUnion.OrWith(aFirst); -} - -// Subtracts parts from regions in such a way that they don't have any overlap. -// Each region in the argument list will have the union of all the regions -// *following* it subtracted from itself. In other words, the arguments are -// sorted low priority to high priority. -template -static void MakeRegionsNonOverlapping(Region& aFirst, Regions& ... aRest) -{ - Region unionOfAll; - MakeRegionsNonOverlappingImpl(unionOfAll, aFirst, aRest...); -} - -void -nsChildView::UpdateVibrancy(const nsTArray& aThemeGeometries) -{ - if (!VibrancyManager::SystemSupportsVibrancy()) { - return; - } - - LayoutDeviceIntRegion sheetRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSheet); - LayoutDeviceIntRegion vibrantLightRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeVibrancyLight); - LayoutDeviceIntRegion vibrantDarkRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark); - LayoutDeviceIntRegion menuRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeMenu); - LayoutDeviceIntRegion tooltipRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeTooltip); - LayoutDeviceIntRegion highlightedMenuItemRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem); - LayoutDeviceIntRegion sourceListRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSourceList); - LayoutDeviceIntRegion sourceListSelectionRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSourceListSelection); - LayoutDeviceIntRegion activeSourceListSelectionRegion = - GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeActiveSourceListSelection); - - MakeRegionsNonOverlapping(sheetRegion, vibrantLightRegion, vibrantDarkRegion, - menuRegion, tooltipRegion, highlightedMenuItemRegion, - sourceListRegion, sourceListSelectionRegion, - activeSourceListSelectionRegion); - - auto& vm = EnsureVibrancyManager(); - vm.UpdateVibrantRegion(VibrancyType::LIGHT, vibrantLightRegion); - vm.UpdateVibrantRegion(VibrancyType::TOOLTIP, tooltipRegion); - vm.UpdateVibrantRegion(VibrancyType::MENU, menuRegion); - vm.UpdateVibrantRegion(VibrancyType::HIGHLIGHTED_MENUITEM, highlightedMenuItemRegion); - vm.UpdateVibrantRegion(VibrancyType::SHEET, sheetRegion); - vm.UpdateVibrantRegion(VibrancyType::SOURCE_LIST, sourceListRegion); - vm.UpdateVibrantRegion(VibrancyType::SOURCE_LIST_SELECTION, sourceListSelectionRegion); - vm.UpdateVibrantRegion(VibrancyType::ACTIVE_SOURCE_LIST_SELECTION, activeSourceListSelectionRegion); - vm.UpdateVibrantRegion(VibrancyType::DARK, vibrantDarkRegion); -} - -static VibrancyType -ThemeGeometryTypeToVibrancyType(nsITheme::ThemeGeometryType aThemeGeometryType) -{ - switch (aThemeGeometryType) { - case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyLight: - return VibrancyType::LIGHT; - case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark: - return VibrancyType::DARK; - case nsNativeThemeCocoa::eThemeGeometryTypeTooltip: - return VibrancyType::TOOLTIP; - case nsNativeThemeCocoa::eThemeGeometryTypeMenu: - return VibrancyType::MENU; - case nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem: - return VibrancyType::HIGHLIGHTED_MENUITEM; - case nsNativeThemeCocoa::eThemeGeometryTypeSheet: - return VibrancyType::SHEET; - case nsNativeThemeCocoa::eThemeGeometryTypeSourceList: - return VibrancyType::SOURCE_LIST; - case nsNativeThemeCocoa::eThemeGeometryTypeSourceListSelection: - return VibrancyType::SOURCE_LIST_SELECTION; - case nsNativeThemeCocoa::eThemeGeometryTypeActiveSourceListSelection: - return VibrancyType::ACTIVE_SOURCE_LIST_SELECTION; - default: - MOZ_CRASH(); - } -} - -NSColor* -nsChildView::VibrancyFillColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType) -{ - if (VibrancyManager::SystemSupportsVibrancy()) { - return EnsureVibrancyManager().VibrancyFillColorForType( - ThemeGeometryTypeToVibrancyType(aThemeGeometryType)); - } - return [NSColor whiteColor]; -} - -NSColor* -nsChildView::VibrancyFontSmoothingBackgroundColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType) -{ - if (VibrancyManager::SystemSupportsVibrancy()) { - return EnsureVibrancyManager().VibrancyFontSmoothingBackgroundColorForType( - ThemeGeometryTypeToVibrancyType(aThemeGeometryType)); - } - return [NSColor clearColor]; -} - -mozilla::VibrancyManager& -nsChildView::EnsureVibrancyManager() -{ - MOZ_ASSERT(mView, "Only call this once we have a view!"); - if (!mVibrancyManager) { - mVibrancyManager = MakeUnique(*this, [mView vibrancyViewsContainer]); - } - return *mVibrancyManager; -} - -nsChildView::SwipeInfo -nsChildView::SendMayStartSwipe(const mozilla::PanGestureInput& aSwipeStartEvent) -{ - nsCOMPtr kungFuDeathGrip(this); - - uint32_t direction = (aSwipeStartEvent.mPanDisplacement.x > 0.0) - ? (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_RIGHT - : (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_LEFT; - - // We're ready to start the animation. Tell Gecko about it, and at the same - // time ask it if it really wants to start an animation for this event. - // This event also reports back the directions that we can swipe in. - LayoutDeviceIntPoint position = - RoundedToInt(aSwipeStartEvent.mPanStartPoint * ScreenToLayoutDeviceScale(1)); - WidgetSimpleGestureEvent geckoEvent = - SwipeTracker::CreateSwipeGestureEvent(eSwipeGestureMayStart, this, - position); - geckoEvent.mDirection = direction; - geckoEvent.mDelta = 0.0; - geckoEvent.mAllowedDirections = 0; - bool shouldStartSwipe = DispatchWindowEvent(geckoEvent); // event cancelled == swipe should start - - SwipeInfo result = { shouldStartSwipe, geckoEvent.mAllowedDirections }; - return result; -} - -void -nsChildView::TrackScrollEventAsSwipe(const mozilla::PanGestureInput& aSwipeStartEvent, - uint32_t aAllowedDirections) -{ - // If a swipe is currently being tracked kill it -- it's been interrupted - // by another gesture event. - if (mSwipeTracker) { - mSwipeTracker->CancelSwipe(); - mSwipeTracker->Destroy(); - mSwipeTracker = nullptr; - } - - uint32_t direction = (aSwipeStartEvent.mPanDisplacement.x > 0.0) - ? (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_RIGHT - : (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_LEFT; - - mSwipeTracker = new SwipeTracker(*this, aSwipeStartEvent, - aAllowedDirections, direction); - - if (!mAPZC) { - mCurrentPanGestureBelongsToSwipe = true; - } -} - -void -nsChildView::SwipeFinished() -{ - mSwipeTracker = nullptr; -} - -already_AddRefed -nsChildView::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, - BufferMode* aBufferMode) -{ - // should have created the GLPresenter in InitCompositor. - MOZ_ASSERT(mGLPresenter); - if (!mGLPresenter) { - mGLPresenter = GLPresenter::CreateForWindow(this); - - if (!mGLPresenter) { - return nullptr; - } - } - - LayoutDeviceIntRegion dirtyRegion(aInvalidRegion); - LayoutDeviceIntSize renderSize = mBounds.Size(); - - if (!mBasicCompositorImage) { - mBasicCompositorImage = MakeUnique(); - } - - RefPtr drawTarget = - mBasicCompositorImage->BeginUpdate(renderSize, dirtyRegion); - - if (!drawTarget) { - // Composite unchanged textures. - DoRemoteComposition(mBounds); - return nullptr; - } - - aInvalidRegion = mBasicCompositorImage->GetUpdateRegion(); - *aBufferMode = BufferMode::BUFFER_NONE; - - return drawTarget.forget(); -} - -void -nsChildView::EndRemoteDrawing() -{ - mBasicCompositorImage->EndUpdate(); - DoRemoteComposition(mBounds); -} - -void -nsChildView::CleanupRemoteDrawing() -{ - mBasicCompositorImage = nullptr; - mCornerMaskImage = nullptr; - mResizerImage = nullptr; - mTitlebarImage = nullptr; - mGLPresenter = nullptr; -} - -bool -nsChildView::InitCompositor(Compositor* aCompositor) -{ - if (aCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC) { - if (!mGLPresenter) { - mGLPresenter = GLPresenter::CreateForWindow(this); - } - - return !!mGLPresenter; - } - return true; -} - -void -nsChildView::DoRemoteComposition(const LayoutDeviceIntRect& aRenderRect) -{ - if (![(ChildView*)mView preRender:mGLPresenter->GetNSOpenGLContext()]) { - return; - } - mGLPresenter->BeginFrame(aRenderRect.Size()); - - // Draw the result from the basic compositor. - mBasicCompositorImage->Draw(mGLPresenter.get(), LayoutDeviceIntPoint(0, 0)); - - // DrawWindowOverlay doesn't do anything for non-GL, so it didn't paint - // anything during the basic compositor transaction. Draw the overlay now. - DrawWindowOverlay(mGLPresenter.get(), aRenderRect); - - mGLPresenter->EndFrame(); - - [(ChildView*)mView postRender:mGLPresenter->GetNSOpenGLContext()]; -} - -@interface NonDraggableView : NSView -@end - -@implementation NonDraggableView -- (BOOL)mouseDownCanMoveWindow { return NO; } -- (NSView*)hitTest:(NSPoint)aPoint { return nil; } -@end - -void -nsChildView::UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) -{ - // mView returns YES from mouseDownCanMoveWindow, so we need to put NSViews - // that return NO from mouseDownCanMoveWindow in the places that shouldn't - // be draggable. We can't do it the other way round because returning - // YES from mouseDownCanMoveWindow doesn't have any effect if there's a - // superview that returns NO. - LayoutDeviceIntRegion nonDraggable; - nonDraggable.Sub(LayoutDeviceIntRect(0, 0, mBounds.width, mBounds.height), aRegion); - - __block bool changed = false; - - // Suppress calls to setNeedsDisplay during NSView geometry changes. - ManipulateViewWithoutNeedingDisplay(mView, ^() { - changed = mNonDraggableRegion.UpdateRegion( - nonDraggable, *this, [mView nonDraggableViewsContainer], ^() { - return [[NonDraggableView alloc] initWithFrame:NSZeroRect]; - }); - }); - - if (changed) { - // Trigger an update to the window server. This will call - // mouseDownCanMoveWindow. - // Doing this manually is only necessary because we're suppressing - // setNeedsDisplay calls above. - [[mView window] setMovableByWindowBackground:NO]; - [[mView window] setMovableByWindowBackground:YES]; - } -} - -void -nsChildView::ReportSwipeStarted(uint64_t aInputBlockId, - bool aStartSwipe) -{ - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == aInputBlockId) { - if (aStartSwipe) { - PanGestureInput& startEvent = mSwipeEventQueue->queuedEvents[0]; - TrackScrollEventAsSwipe(startEvent, mSwipeEventQueue->allowedDirections); - for (size_t i = 1; i < mSwipeEventQueue->queuedEvents.Length(); i++) { - mSwipeTracker->ProcessEvent(mSwipeEventQueue->queuedEvents[i]); - } - } - mSwipeEventQueue = nullptr; - } -} - -void -nsChildView::DispatchAPZWheelInputEvent(InputData& aEvent, bool aCanTriggerSwipe) -{ - if (mSwipeTracker && aEvent.mInputType == PANGESTURE_INPUT) { - // Give the swipe tracker a first pass at the event. If a new pan gesture - // has been started since the beginning of the swipe, the swipe tracker - // will know to ignore the event. - nsEventStatus status = mSwipeTracker->ProcessEvent(aEvent.AsPanGestureInput()); - if (status == nsEventStatus_eConsumeNoDefault) { - return; - } - } - - WidgetWheelEvent event(true, eWheel, this); - - if (mAPZC) { - uint64_t inputBlockId = 0; - ScrollableLayerGuid guid; - - nsEventStatus result = mAPZC->ReceiveInputEvent(aEvent, &guid, &inputBlockId); - if (result == nsEventStatus_eConsumeNoDefault) { - return; - } - - switch(aEvent.mInputType) { - case PANGESTURE_INPUT: { - PanGestureInput& panInput = aEvent.AsPanGestureInput(); - - event = panInput.ToWidgetWheelEvent(this); - if (aCanTriggerSwipe) { - SwipeInfo swipeInfo = SendMayStartSwipe(panInput); - event.mCanTriggerSwipe = swipeInfo.wantsSwipe; - if (swipeInfo.wantsSwipe) { - if (result == nsEventStatus_eIgnore) { - // APZ has determined and that scrolling horizontally in the - // requested direction is impossible, so it didn't do any - // scrolling for the event. - // We know now that MayStartSwipe wants a swipe, so we can start - // the swipe now. - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - } else { - // We don't know whether this event can start a swipe, so we need - // to queue up events and wait for a call to ReportSwipeStarted. - // APZ might already have started scrolling in response to the - // event if it knew that it's the right thing to do. In that case - // we'll still get a call to ReportSwipeStarted, and we will - // discard the queued events at that point. - mSwipeEventQueue = MakeUnique(swipeInfo.allowedDirections, - inputBlockId); - } - } - } - - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == inputBlockId) { - mSwipeEventQueue->queuedEvents.AppendElement(panInput); - } - break; - } - case SCROLLWHEEL_INPUT: { - event = aEvent.AsScrollWheelInput().ToWidgetWheelEvent(this); - break; - }; - default: - MOZ_CRASH("unsupported event type"); - return; - } - if (event.mMessage == eWheel && - (event.mDeltaX != 0 || event.mDeltaY != 0)) { - ProcessUntransformedAPZEvent(&event, guid, inputBlockId, result); - } - return; - } - - nsEventStatus status; - switch(aEvent.mInputType) { - case PANGESTURE_INPUT: { - PanGestureInput panInput = aEvent.AsPanGestureInput(); - if (panInput.mType == PanGestureInput::PANGESTURE_MAYSTART || - panInput.mType == PanGestureInput::PANGESTURE_START) { - mCurrentPanGestureBelongsToSwipe = false; - } - if (mCurrentPanGestureBelongsToSwipe) { - // Ignore this event. It's a momentum event from a scroll gesture - // that was processed as a swipe, and the swipe animation has - // already finished (so mSwipeTracker is already null). - MOZ_ASSERT(panInput.IsMomentum(), - "If the fingers are still on the touchpad, we should still have a SwipeTracker, and it should have consumed this event."); - return; - } - - event = panInput.ToWidgetWheelEvent(this); - if (aCanTriggerSwipe) { - SwipeInfo swipeInfo = SendMayStartSwipe(panInput); - - // We're in the non-APZ case here, but we still want to know whether - // the event was routed to a child process, so we use InputAPZContext - // to get that piece of information. - ScrollableLayerGuid guid; - InputAPZContext context(guid, 0, nsEventStatus_eIgnore); - - event.mCanTriggerSwipe = swipeInfo.wantsSwipe; - DispatchEvent(&event, status); - if (swipeInfo.wantsSwipe) { - if (context.WasRoutedToChildProcess()) { - // We don't know whether this event can start a swipe, so we need - // to queue up events and wait for a call to ReportSwipeStarted. - mSwipeEventQueue = MakeUnique(swipeInfo.allowedDirections, 0); - } else if (event.TriggersSwipe()) { - TrackScrollEventAsSwipe(panInput, swipeInfo.allowedDirections); - } - } - - if (mSwipeEventQueue && mSwipeEventQueue->inputBlockId == 0) { - mSwipeEventQueue->queuedEvents.AppendElement(panInput); - } - return; - } - break; - } - case SCROLLWHEEL_INPUT: { - event = aEvent.AsScrollWheelInput().ToWidgetWheelEvent(this); - break; - } - default: - MOZ_CRASH("unexpected event type"); - return; - } - if (event.mMessage == eWheel && - (event.mDeltaX != 0 || event.mDeltaY != 0)) { - DispatchEvent(&event, status); - } -} - -// When using 10.11, calling showDefinitionForAttributedString causes the -// following exception on LookupViewService. (rdar://26476091) -// -// Exception: decodeObjectForKey: class "TitlebarAndBackgroundColor" not -// loaded or does not exist -// -// So we set temporary color that is NSColor before calling it. - -class MOZ_RAII AutoBackgroundSetter final { -public: - explicit AutoBackgroundSetter(NSView* aView) { - if (nsCocoaFeatures::OnElCapitanOrLater() && - [[aView window] isKindOfClass:[ToolbarWindow class]]) { - mWindow = [(ToolbarWindow*)[aView window] retain]; - [mWindow setTemporaryBackgroundColor]; - } else { - mWindow = nullptr; - } - } - - ~AutoBackgroundSetter() { - if (mWindow) { - [mWindow restoreBackgroundColor]; - [mWindow release]; - } - } - -private: - ToolbarWindow* mWindow; // strong -}; - -void -nsChildView::LookUpDictionary( - const nsAString& aText, - const nsTArray& aFontRangeArray, - const bool aIsVertical, - const LayoutDeviceIntPoint& aPoint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSMutableAttributedString* attrStr = - nsCocoaUtils::GetNSMutableAttributedString(aText, aFontRangeArray, - aIsVertical, - BackingScaleFactor()); - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); - NSDictionary* attributes = [attrStr attributesAtIndex:0 effectiveRange:nil]; - NSFont* font = [attributes objectForKey:NSFontAttributeName]; - if (font) { - if (aIsVertical) { - pt.x -= [font descender]; - } else { - pt.y += [font ascender]; - } - } - - AutoBackgroundSetter setter(mView); - [mView showDefinitionForAttributedString:attrStr atPoint:pt]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#ifdef ACCESSIBILITY -already_AddRefed -nsChildView::GetDocumentAccessible() -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return nullptr; - - if (mAccessible) { - RefPtr ret; - CallQueryReferent(mAccessible.get(), - static_cast(getter_AddRefs(ret))); - return ret.forget(); - } - - // need to fetch the accessible anew, because it has gone away. - // cache the accessible in our weak ptr - RefPtr acc = GetRootAccessible(); - mAccessible = do_GetWeakReference(acc.get()); - - return acc.forget(); -} -#endif - -// GLPresenter implementation - -GLPresenter::GLPresenter(GLContext* aContext) - : mGLContext(aContext) -{ - mGLContext->MakeCurrent(); - ShaderConfigOGL config; - config.SetTextureTarget(LOCAL_GL_TEXTURE_RECTANGLE_ARB); - mRGBARectProgram = MakeUnique(mGLContext, - ProgramProfileOGL::GetProfileFor(config)); - - // Create mQuadVBO. - mGLContext->fGenBuffers(1, &mQuadVBO); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); - - // 1 quad, with the number of the quad (vertexID) encoded in w. - GLfloat vertices[] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 0.0f, - }; - HeapCopyOfStackArray verticesOnHeap(vertices); - mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, - verticesOnHeap.ByteLength(), - verticesOnHeap.Data(), - LOCAL_GL_STATIC_DRAW); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); -} - -GLPresenter::~GLPresenter() -{ - if (mQuadVBO) { - mGLContext->MakeCurrent(); - mGLContext->fDeleteBuffers(1, &mQuadVBO); - mQuadVBO = 0; - } -} - -void -GLPresenter::BindAndDrawQuad(ShaderProgramOGL *aProgram, - const gfx::Rect& aLayerRect, - const gfx::Rect& aTextureRect) -{ - mGLContext->MakeCurrent(); - - gfx::Rect layerRects[4]; - gfx::Rect textureRects[4]; - - layerRects[0] = aLayerRect; - textureRects[0] = aTextureRect; - - aProgram->SetLayerRects(layerRects); - aProgram->SetTextureRects(textureRects); - - const GLuint coordAttribIndex = 0; - - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO); - mGLContext->fVertexAttribPointer(coordAttribIndex, 4, - LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, - (GLvoid*)0); - mGLContext->fEnableVertexAttribArray(coordAttribIndex); - mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 6); - mGLContext->fDisableVertexAttribArray(coordAttribIndex); -} - -void -GLPresenter::BeginFrame(LayoutDeviceIntSize aRenderSize) -{ - mGLContext->MakeCurrent(); - - mGLContext->fViewport(0, 0, aRenderSize.width, aRenderSize.height); - - // Matrix to transform (0, 0, width, height) to viewport space (-1.0, 1.0, - // 2, 2) and flip the contents. - gfx::Matrix viewMatrix = gfx::Matrix::Translation(-1.0, 1.0); - viewMatrix.PreScale(2.0f / float(aRenderSize.width), - 2.0f / float(aRenderSize.height)); - viewMatrix.PreScale(1.0f, -1.0f); - - gfx::Matrix4x4 matrix3d = gfx::Matrix4x4::From2D(viewMatrix); - matrix3d._33 = 0.0f; - - // set the projection matrix for the next time the program is activated - mProjMatrix = matrix3d; - - // Default blend function implements "OVER" - mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, - LOCAL_GL_ONE, LOCAL_GL_ONE); - mGLContext->fEnable(LOCAL_GL_BLEND); - - mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0); - mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT); - - mGLContext->fEnable(LOCAL_GL_TEXTURE_RECTANGLE_ARB); -} - -void -GLPresenter::EndFrame() -{ - mGLContext->SwapBuffers(); - mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); -} - -class WidgetsReleaserRunnable final : public mozilla::Runnable -{ -public: - explicit WidgetsReleaserRunnable(nsTArray>&& aWidgetArray) - : mWidgetArray(aWidgetArray) - { - } - - // Do nothing; all this runnable does is hold a reference the widgets in - // mWidgetArray, and those references will be dropped when this runnable - // is destroyed. - -private: - nsTArray> mWidgetArray; -}; - -#pragma mark - - -// ViewRegionContainerView is a view class for certain subviews of ChildView -// which contain the NSViews created for ViewRegions (see ViewRegion.h). -// It doesn't do anything interesting, it only acts as a container so that it's -// easier for ChildView to control the z order of its children. -@interface ViewRegionContainerView : NSView { -} -@end - -@implementation ViewRegionContainerView - -- (NSView*)hitTest:(NSPoint)aPoint { - return nil; // Be transparent to mouse events. -} - -- (BOOL)isFlipped { - return [[self superview] isFlipped]; -} - -- (BOOL)mouseDownCanMoveWindow { - return [[self superview] mouseDownCanMoveWindow]; -} - -@end -; - -@implementation ChildView - -// globalDragPboard is non-null during native drag sessions that did not originate -// in our native NSView (it is set in |draggingEntered:|). It is unset when the -// drag session ends for this view, either with the mouse exiting or when a drop -// occurs in this view. -NSPasteboard* globalDragPboard = nil; - -// gLastDragView and gLastDragMouseDownEvent are used to communicate information -// to the drag service during drag invocation (starting a drag in from the view). -// gLastDragView is only non-null while mouseDragged is on the call stack. -NSView* gLastDragView = nil; -NSEvent* gLastDragMouseDownEvent = nil; - -+ (void)initialize -{ - static BOOL initialized = NO; - - if (!initialized) { - // Inform the OS about the types of services (from the "Services" menu) - // that we can handle. - - NSArray *sendTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil]; - NSArray *returnTypes = [[NSArray alloc] initWithObjects:NSStringPboardType,NSHTMLPboardType,nil]; - - [NSApp registerServicesMenuSendTypes:sendTypes returnTypes:returnTypes]; - - [sendTypes release]; - [returnTypes release]; - - initialized = YES; - } -} - -+ (void)registerViewForDraggedTypes:(NSView*)aView -{ - [aView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, - NSStringPboardType, - NSHTMLPboardType, - NSURLPboardType, - NSFilesPromisePboardType, - kWildcardPboardType, - kCorePboardType_url, - kCorePboardType_urld, - kCorePboardType_urln, - nil]]; -} - -// initWithFrame:geckoChild: -- (id)initWithFrame:(NSRect)inFrame geckoChild:(nsChildView*)inChild -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super initWithFrame:inFrame])) { - mGeckoChild = inChild; - mBlockedLastMouseDown = NO; - mExpectingWheelStop = NO; - - mLastMouseDownEvent = nil; - mLastKeyDownEvent = nil; - mClickThroughMouseDownEvent = nil; - mDragService = nullptr; - - mGestureState = eGestureState_None; - mCumulativeMagnification = 0.0; - mCumulativeRotation = 0.0; - - mNeedsGLUpdate = NO; - - [self setFocusRingType:NSFocusRingTypeNone]; - -#ifdef __LP64__ - mCancelSwipeAnimation = nil; -#endif - - mNonDraggableViewsContainer = [[ViewRegionContainerView alloc] initWithFrame:[self bounds]]; - mVibrancyViewsContainer = [[ViewRegionContainerView alloc] initWithFrame:[self bounds]]; - - [mNonDraggableViewsContainer setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [mVibrancyViewsContainer setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - [self addSubview:mNonDraggableViewsContainer]; - [self addSubview:mVibrancyViewsContainer]; - - mPixelHostingView = [[PixelHostingView alloc] initWithFrame:[self bounds]]; - [mPixelHostingView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - [self addSubview:mPixelHostingView]; - - mTopLeftCornerMask = NULL; - } - - // register for things we'll take from other applications - [ChildView registerViewForDraggedTypes:self]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(systemMetricsChanged) - name:NSControlTintDidChangeNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(systemMetricsChanged) - name:NSSystemColorsDidChangeNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(scrollbarSystemMetricChanged) - name:NSPreferredScrollerStyleDidChangeNotification - object:nil]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self - selector:@selector(systemMetricsChanged) - name:@"AppleAquaScrollBarVariantChanged" - object:nil - suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_surfaceNeedsUpdate:) - name:NSViewGlobalFrameDidChangeNotification - object:mPixelHostingView]; - - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// ComplexTextInputPanel's interpretKeyEvent hack won't work without this. -// It makes calls to +[NSTextInputContext currentContext], deep in system -// code, return the appropriate context. -- (NSTextInputContext *)inputContext -{ - NSTextInputContext* pluginContext = NULL; - if (mGeckoChild && mGeckoChild->IsPluginFocused()) { - ComplexTextInputPanel* ctiPanel = - ComplexTextInputPanel::GetSharedComplexTextInputPanel(); - if (ctiPanel) { - pluginContext = (NSTextInputContext*) ctiPanel->GetInputContext(); - } - } - if (pluginContext) { - return pluginContext; - } else { - if (!mGeckoChild) { - // -[ChildView widgetDestroyed] has been called, but - // -[ChildView delayedTearDown] has not yet completed. Accessing - // [super inputContext] now would uselessly recreate a text input context - // for us, under which -[ChildView validAttributesForMarkedText] would - // be called and the assertion checking for mTextInputHandler would fail. - // We return nil to avoid that. - return nil; - } - return [super inputContext]; - } -} - -- (void)installTextInputHandler:(TextInputHandler*)aHandler -{ - mTextInputHandler = aHandler; -} - -- (void)uninstallTextInputHandler -{ - mTextInputHandler = nullptr; -} - -- (bool)preRender:(NSOpenGLContext *)aGLContext -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (![self window] || - ([[self window] isKindOfClass:[BaseWindow class]] && - ![(BaseWindow*)[self window] isVisibleOrBeingShown])) { - // Before the window is shown, our GL context's front FBO is not - // framebuffer complete, so we refuse to render. - return false; - } - - if (!mGLContext) { - mGLContext = aGLContext; - [mGLContext retain]; - mNeedsGLUpdate = true; - } - - CGLLockContext((CGLContextObj)[aGLContext CGLContextObj]); - - if (mNeedsGLUpdate) { - [self updateGLContext]; - mNeedsGLUpdate = NO; - } - - return true; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -- (void)postRender:(NSOpenGLContext *)aGLContext -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - CGLUnlockContext((CGLContextObj)[aGLContext CGLContextObj]); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (NSView*)vibrancyViewsContainer { - return mVibrancyViewsContainer; -} - -- (NSView*)nonDraggableViewsContainer { - return mNonDraggableViewsContainer; -} - -- (NSView*)pixelHostingView { - return mPixelHostingView; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mGLContext release]; - [mLastMouseDownEvent release]; - [mLastKeyDownEvent release]; - [mClickThroughMouseDownEvent release]; - CGImageRelease(mTopLeftCornerMask); - ChildViewMouseTracker::OnDestroyView(self); - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; - [mVibrancyViewsContainer removeFromSuperview]; - [mVibrancyViewsContainer release]; - [mNonDraggableViewsContainer removeFromSuperview]; - [mNonDraggableViewsContainer release]; - [mPixelHostingView removeFromSuperview]; - [mPixelHostingView release]; - - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)widgetDestroyed -{ - if (mTextInputHandler) { - mTextInputHandler->OnDestroyWidget(mGeckoChild); - mTextInputHandler = nullptr; - } - mGeckoChild = nullptr; - - // Just in case we're destroyed abruptly and missed the draggingExited - // or performDragOperation message. - NS_IF_RELEASE(mDragService); -} - -// mozView method, return our gecko child view widget. Note this does not AddRef. -- (nsIWidget*) widget -{ - return static_cast(mGeckoChild); -} - -- (void)systemMetricsChanged -{ - if (mGeckoChild) - mGeckoChild->NotifyThemeChanged(); -} - -- (void)scrollbarSystemMetricChanged -{ - [self systemMetricsChanged]; - - if (mGeckoChild) { - nsIWidgetListener* listener = mGeckoChild->GetWidgetListener(); - if (listener) { - nsIPresShell* presShell = listener->GetPresShell(); - if (presShell) { - presShell->ReconstructFrames(); - } - } - } -} - -- (NSString*)description -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [NSString stringWithFormat:@"ChildView %p, gecko child %p, frame %@", self, mGeckoChild, NSStringFromRect([self frame])]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// Make the origin of this view the topLeft corner (gecko origin) rather -// than the bottomLeft corner (standard cocoa origin). -- (BOOL)isFlipped -{ - return YES; -} - -- (BOOL)isOpaque -{ - return [[self window] isOpaque]; -} - -- (void)sendFocusEvent:(EventMessage)eventMessage -{ - if (!mGeckoChild) - return; - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetGUIEvent focusGuiEvent(true, eventMessage, mGeckoChild); - focusGuiEvent.mTime = PR_IntervalNow(); - mGeckoChild->DispatchEvent(&focusGuiEvent, status); -} - -// We accept key and mouse events, so don't keep passing them up the chain. Allow -// this to be a 'focused' widget for event dispatch. -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -// Accept mouse down events on background windows -- (BOOL)acceptsFirstMouse:(NSEvent*)aEvent -{ - if (![[self window] isKindOfClass:[PopupWindow class]]) { - // We rely on this function to tell us that the mousedown was on a - // background window. Inside mouseDown we can't tell whether we were - // inactive because at that point we've already been made active. - // Unfortunately, acceptsFirstMouse is called for PopupWindows even when - // their parent window is active, so ignore this on them for now. - mClickThroughMouseDownEvent = [aEvent retain]; - } - return YES; -} - -- (BOOL)mouseDownCanMoveWindow -{ - // Return YES so that parts of this view can be draggable. The non-draggable - // parts will be covered by NSViews that return NO from - // mouseDownCanMoveWindow and thus override draggability from the inside. - // These views are assembled in nsChildView::UpdateWindowDraggingRegion. - return YES; -} - --(void)updateGLContext -{ - [mGLContext setView:mPixelHostingView]; - [mGLContext update]; -} - -- (void)_surfaceNeedsUpdate:(NSNotification*)notification -{ - if (mGLContext) { - CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]); - mNeedsGLUpdate = YES; - CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]); - } -} - -- (void)viewDidChangeBackingProperties -{ - [super viewDidChangeBackingProperties]; - if (mGeckoChild) { - // actually, it could be the color space that's changed, - // but we can't tell the difference here except by retrieving - // the backing scale factor and comparing to the old value - mGeckoChild->BackingScaleFactorChanged(); - } -} - -- (BOOL)isCoveringTitlebar -{ - return [[self window] isKindOfClass:[BaseWindow class]] && - [(BaseWindow*)[self window] mainChildView] == self && - [(BaseWindow*)[self window] drawsContentsIntoWindowFrame]; -} - -- (void)viewWillStartLiveResize -{ - nsCOMPtr observerService = mozilla::services::GetObserverService(); - - if (!observerService) { - return; - } - - observerService->NotifyObservers(nullptr, "live-resize-start", nullptr); -} - -- (void)viewDidEndLiveResize -{ - nsCOMPtr observerService = mozilla::services::GetObserverService(); - - if (!observerService) { - return; - } - - observerService->NotifyObservers(nullptr, "live-resize-end", nullptr); -} - -- (NSColor*)vibrancyFillColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType -{ - if (!mGeckoChild) { - return [NSColor whiteColor]; - } - return mGeckoChild->VibrancyFillColorForThemeGeometryType(aThemeGeometryType); -} - -- (NSColor*)vibrancyFontSmoothingBackgroundColorForThemeGeometryType:(nsITheme::ThemeGeometryType)aThemeGeometryType -{ - if (!mGeckoChild) { - return [NSColor clearColor]; - } - return mGeckoChild->VibrancyFontSmoothingBackgroundColorForThemeGeometryType(aThemeGeometryType); -} - -- (LayoutDeviceIntRegion)nativeDirtyRegionWithBoundingRect:(NSRect)aRect -{ - LayoutDeviceIntRect boundingRect = mGeckoChild->CocoaPointsToDevPixels(aRect); - const NSRect *rects; - NSInteger count; - [mPixelHostingView getRectsBeingDrawn:&rects count:&count]; - - if (count > MAX_RECTS_IN_REGION) { - return boundingRect; - } - - LayoutDeviceIntRegion region; - for (NSInteger i = 0; i < count; ++i) { - region.Or(region, mGeckoChild->CocoaPointsToDevPixels(rects[i])); - } - region.And(region, boundingRect); - return region; -} - -// The display system has told us that a portion of our view is dirty. Tell -// gecko to paint it -// This method is called from mPixelHostingView's drawRect handler. -- (void)doDrawRect:(NSRect)aRect -{ - if (!NS_IsMainThread()) { - // In the presence of CoreAnimation, this method can sometimes be called on - // a non-main thread. Ignore those calls because Gecko can only react to - // them on the main thread. - return; - } - - if (!mGeckoChild || !mGeckoChild->IsVisible()) - return; - CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - - if ([self isUsingOpenGL]) { - // Since this view is usually declared as opaque, the window's pixel - // buffer may now contain garbage which we need to prevent from reaching - // the screen. The only place where garbage can show is in the window - // corners and the vibrant regions of the window - the rest of the window - // is covered by opaque content in our OpenGL surface. - // So we need to clear the pixel buffer contents in these areas. - [self clearCorners]; - - // Force a sync OMTC composite into the OpenGL context and return. - LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds(); - LayoutDeviceIntRegion region(geckoBounds); - - mGeckoChild->PaintWindow(region); - return; - } - - PROFILER_LABEL("ChildView", "drawRect", - js::ProfileEntry::Category::GRAPHICS); - - // The CGContext that drawRect supplies us with comes with a transform that - // scales one user space unit to one Cocoa point, which can consist of - // multiple dev pixels. But Gecko expects its supplied context to be scaled - // to device pixels, so we need to reverse the scaling. - double scale = mGeckoChild->BackingScaleFactor(); - CGContextSaveGState(cgContext); - CGContextScaleCTM(cgContext, 1.0 / scale, 1.0 / scale); - - NSSize viewSize = [self bounds].size; - gfx::IntSize backingSize = gfx::IntSize::Truncate(viewSize.width * scale, viewSize.height * scale); - LayoutDeviceIntRegion region = [self nativeDirtyRegionWithBoundingRect:aRect]; - - bool painted = mGeckoChild->PaintWindowInContext(cgContext, region, backingSize); - - // Undo the scale transform so that from now on the context is in - // CocoaPoints again. - CGContextRestoreGState(cgContext); - - if (!painted && [mPixelHostingView isOpaque]) { - // Gecko refused to draw, but we've claimed to be opaque, so we have to - // draw something--fill with white. - CGContextSetRGBFillColor(cgContext, 1, 1, 1, 1); - CGContextFillRect(cgContext, NSRectToCGRect(aRect)); - } - - if ([self isCoveringTitlebar]) { - [self drawTitleString]; - [self drawTitlebarHighlight]; - [self maskTopCornersInContext:cgContext]; - } -} - -- (BOOL)isUsingOpenGL -{ - if (!mGeckoChild || ![self window]) - return NO; - - return mGLContext || mUsingOMTCompositor; -} - - -- (BOOL)hasRoundedBottomCorners -{ - return [[self window] respondsToSelector:@selector(bottomCornerRounded)] && - [[self window] bottomCornerRounded]; -} - -- (CGFloat)cornerRadius -{ - NSView* frameView = [[[self window] contentView] superview]; - if (!frameView || ![frameView respondsToSelector:@selector(roundedCornerRadius)]) - return 4.0f; - return [frameView roundedCornerRadius]; -} - --(void)setGLOpaque:(BOOL)aOpaque -{ - CGLLockContext((CGLContextObj)[mGLContext CGLContextObj]); - // Make the context opaque for fullscreen (since it performs better), and transparent - // for windowed (since we need it for rounded corners). - GLint opaque = aOpaque ? 1 : 0; - [mGLContext setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity]; - CGLUnlockContext((CGLContextObj)[mGLContext CGLContextObj]); -} - -// Accelerated windows have two NSSurfaces: -// (1) The window's pixel buffer in the back and -// (2) the OpenGL view in the front. -// These two surfaces are composited by the window manager. Drawing into the -// CGContext which is provided by drawRect ends up in (1). -// When our window has rounded corners, the OpenGL view has transparent pixels -// in the corners. In these places the contents of the window's pixel buffer -// can show through. So we need to make sure that the pixel buffer is -// transparent in the corners so that no garbage reaches the screen. -// The contents of the pixel buffer in the rest of the window don't matter -// because they're covered by opaque pixels of the OpenGL context. -// Making the corners transparent works even though our window is -// declared "opaque" (in the NSWindow's isOpaque method). -- (void)clearCorners -{ - CGFloat radius = [self cornerRadius]; - CGFloat w = [self bounds].size.width, h = [self bounds].size.height; - [[NSColor clearColor] set]; - - if ([self isCoveringTitlebar]) { - NSRectFill(NSMakeRect(0, 0, radius, radius)); - NSRectFill(NSMakeRect(w - radius, 0, radius, radius)); - } - - if ([self hasRoundedBottomCorners]) { - NSRectFill(NSMakeRect(0, h - radius, radius, radius)); - NSRectFill(NSMakeRect(w - radius, h - radius, radius, radius)); - } -} - -// This is the analog of nsChildView::MaybeDrawRoundedCorners for CGContexts. -// We only need to mask the top corners here because Cocoa does the masking -// for the window's bottom corners automatically (starting with 10.7). -- (void)maskTopCornersInContext:(CGContextRef)aContext -{ - CGFloat radius = [self cornerRadius]; - int32_t devPixelCornerRadius = mGeckoChild->CocoaPointsToDevPixels(radius); - - // First make sure that mTopLeftCornerMask is set up. - if (!mTopLeftCornerMask || - int32_t(CGImageGetWidth(mTopLeftCornerMask)) != devPixelCornerRadius) { - CGImageRelease(mTopLeftCornerMask); - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGContextRef imgCtx = CGBitmapContextCreate(NULL, - devPixelCornerRadius, - devPixelCornerRadius, - 8, devPixelCornerRadius * 4, - rgb, kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(rgb); - DrawTopLeftCornerMask(imgCtx, devPixelCornerRadius); - mTopLeftCornerMask = CGBitmapContextCreateImage(imgCtx); - CGContextRelease(imgCtx); - } - - // kCGBlendModeDestinationIn is the secret sauce which allows us to erase - // already painted pixels. It's defined as R = D * Sa: multiply all channels - // of the destination pixel with the alpha of the source pixel. In our case, - // the source is mTopLeftCornerMask. - CGContextSaveGState(aContext); - CGContextSetBlendMode(aContext, kCGBlendModeDestinationIn); - - CGRect destRect = CGRectMake(0, 0, radius, radius); - - // Erase the top left corner... - CGContextDrawImage(aContext, destRect, mTopLeftCornerMask); - - // ... and the top right corner. - CGContextTranslateCTM(aContext, [self bounds].size.width, 0); - CGContextScaleCTM(aContext, -1, 1); - CGContextDrawImage(aContext, destRect, mTopLeftCornerMask); - - CGContextRestoreGState(aContext); -} - -- (void)drawTitleString -{ - BaseWindow* window = (BaseWindow*)[self window]; - if (![window wantsTitleDrawn]) { - return; - } - - NSView* frameView = [[window contentView] superview]; - if (![frameView respondsToSelector:@selector(_drawTitleBar:)]) { - return; - } - - NSGraphicsContext* oldContext = [NSGraphicsContext currentContext]; - CGContextRef ctx = (CGContextRef)[oldContext graphicsPort]; - CGContextSaveGState(ctx); - if ([oldContext isFlipped] != [frameView isFlipped]) { - CGContextTranslateCTM(ctx, 0, [self bounds].size.height); - CGContextScaleCTM(ctx, 1, -1); - } - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:[frameView isFlipped]]]; - [frameView _drawTitleBar:[frameView bounds]]; - CGContextRestoreGState(ctx); - [NSGraphicsContext setCurrentContext:oldContext]; -} - -- (void)drawTitlebarHighlight -{ - DrawTitlebarHighlight([self bounds].size, [self cornerRadius], - mGeckoChild->DevPixelsToCocoaPoints(1)); -} - -- (void)viewWillDraw -{ - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if (mGeckoChild) { - // The OS normally *will* draw our NSWindow, no matter what we do here. - // But Gecko can delete our parent widget(s) (along with mGeckoChild) - // while processing a paint request, which closes our NSWindow and - // makes the OS throw an NSInternalInconsistencyException assertion when - // it tries to draw it. Sometimes the OS also aborts the browser process. - // So we need to retain our parent(s) here and not release it/them until - // the next time through the main thread's run loop. When we do this we - // also need to retain and release mGeckoChild, which holds a strong - // reference to us. See bug 550392. - nsIWidget* parent = mGeckoChild->GetParent(); - if (parent) { - nsTArray> widgetArray; - while (parent) { - widgetArray.AppendElement(parent); - parent = parent->GetParent(); - } - widgetArray.AppendElement(mGeckoChild); - nsCOMPtr releaserRunnable = - new WidgetsReleaserRunnable(Move(widgetArray)); - NS_DispatchToMainThread(releaserRunnable); - } - - if ([self isUsingOpenGL]) { - if (ShadowLayerForwarder* slf = mGeckoChild->GetLayerManager()->AsShadowForwarder()) { - slf->WindowOverlayChanged(); - } - } - - mGeckoChild->WillPaintWindow(); - } - [super viewWillDraw]; -} - -#if USE_CLICK_HOLD_CONTEXTMENU -// -// -clickHoldCallback: -// -// called from a timer two seconds after a mouse down to see if we should display -// a context menu (click-hold). |anEvent| is the original mouseDown event. If we're -// still in that mouseDown by this time, put up the context menu, otherwise just -// fuhgeddaboutit. |anEvent| has been retained by the OS until after this callback -// fires so we're ok there. -// -// This code currently messes in a bunch of edge cases (bugs 234751, 232964, 232314) -// so removing it until we get it straightened out. -// -- (void)clickHoldCallback:(id)theEvent; -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if( theEvent == [NSApp currentEvent] ) { - // we're still in the middle of the same mousedown event here, activate - // click-hold context menu by triggering the right mouseDown action. - NSEvent* clickHoldEvent = [NSEvent mouseEventWithType:NSRightMouseDown - location:[theEvent locationInWindow] - modifierFlags:[theEvent modifierFlags] - timestamp:[theEvent timestamp] - windowNumber:[theEvent windowNumber] - context:[theEvent context] - eventNumber:[theEvent eventNumber] - clickCount:[theEvent clickCount] - pressure:[theEvent pressure]]; - [self rightMouseDown:clickHoldEvent]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} -#endif - -// If we've just created a non-native context menu, we need to mark it as -// such and let the OS (and other programs) know when it opens and closes -// (this is how the OS knows to close other programs' context menus when -// ours open). We send the initial notification here, but others are sent -// in nsCocoaWindow::Show(). -- (void)maybeInitContextMenuTracking -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - -#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS - return; -#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */ - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE_VOID(rollupListener); - nsCOMPtr widget = rollupListener->GetRollupWidget(); - NS_ENSURE_TRUE_VOID(widget); - - NSWindow *popupWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); - if (!popupWindow || ![popupWindow isKindOfClass:[PopupWindow class]]) - return; - - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification" - object:@"org.mozilla.gecko.PopupWindow"]; - [(PopupWindow*)popupWindow setIsContextMenu:YES]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Returns true if the event should no longer be processed, false otherwise. -// This does not return whether or not anything was rolled up. -- (BOOL)maybeRollup:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - BOOL consumeEvent = NO; - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE(rollupListener, false); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (rollupWidget) { - NSWindow* currentPopup = static_cast(rollupWidget->GetNativeData(NS_NATIVE_WINDOW)); - if (!nsCocoaUtils::IsEventOverWindow(theEvent, currentPopup)) { - // event is not over the rollup window, default is to roll up - bool shouldRollup = true; - - // check to see if scroll events should roll up the popup - if ([theEvent type] == NSScrollWheel) { - shouldRollup = rollupListener->ShouldRollupOnMouseWheelEvent(); - // consume scroll events that aren't over the popup - // unless the popup is an arrow panel - consumeEvent = rollupListener->ShouldConsumeOnMouseWheelEvent(); - } - - // if we're dealing with menus, we probably have submenus and - // we don't want to rollup if the click is in a parent menu of - // the current submenu - uint32_t popupsToRollup = UINT32_MAX; - AutoTArray widgetChain; - uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain); - for (uint32_t i = 0; i < widgetChain.Length(); i++) { - nsIWidget* widget = widgetChain[i]; - NSWindow* currWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); - if (nsCocoaUtils::IsEventOverWindow(theEvent, currWindow)) { - // don't roll up if the mouse event occurred within a menu of the - // same type. If the mouse event occurred in a menu higher than - // that, roll up, but pass the number of popups to Rollup so - // that only those of the same type close up. - if (i < sameTypeCount) { - shouldRollup = false; - } - else { - popupsToRollup = sameTypeCount; - } - break; - } - } - - if (shouldRollup) { - if ([theEvent type] == NSLeftMouseDown) { - NSPoint point = [NSEvent mouseLocation]; - FlipCocoaScreenCoordinate(point); - gfx::IntPoint pos = gfx::IntPoint::Truncate(point.x, point.y); - consumeEvent = (BOOL)rollupListener->Rollup(popupsToRollup, true, &pos, nullptr); - } - else { - consumeEvent = (BOOL)rollupListener->Rollup(popupsToRollup, true, nullptr, nullptr); - } - } - } - } - - return consumeEvent; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -/* - * In OS X Mountain Lion and above, smart zoom gestures are implemented in - * smartMagnifyWithEvent. In OS X Lion, they are implemented in - * magnifyWithEvent. See inline comments for more info. - * - * The prototypes swipeWithEvent, beginGestureWithEvent, magnifyWithEvent, - * smartMagnifyWithEvent, rotateWithEvent, and endGestureWithEvent were - * obtained from the following links: - * https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSResponder_Class/Reference/Reference.html - * https://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.html - */ - -- (void)swipeWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - float deltaX = [anEvent deltaX]; // left=1.0, right=-1.0 - float deltaY = [anEvent deltaY]; // up=1.0, down=-1.0 - - // Setup the "swipe" event. - WidgetSimpleGestureEvent geckoEvent(true, eSwipeGesture, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - - // Record the left/right direction. - if (deltaX > 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_LEFT; - else if (deltaX < 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT; - - // Record the up/down direction. - if (deltaY > 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_UP; - else if (deltaY < 0.0) - geckoEvent.mDirection |= nsIDOMSimpleGestureEvent::DIRECTION_DOWN; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)beginGestureWithEvent:(NSEvent *)anEvent -{ - if (!anEvent) - return; - - mGestureState = eGestureState_StartGesture; - mCumulativeMagnification = 0; - mCumulativeRotation = 0.0; -} - -- (void)magnifyWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - float deltaZ = [anEvent deltaZ]; - - EventMessage msg; - switch (mGestureState) { - case eGestureState_StartGesture: - msg = eMagnifyGestureStart; - mGestureState = eGestureState_MagnifyGesture; - break; - - case eGestureState_MagnifyGesture: - msg = eMagnifyGestureUpdate; - break; - - case eGestureState_None: - case eGestureState_RotateGesture: - default: - return; - } - - // Setup the event. - WidgetSimpleGestureEvent geckoEvent(true, msg, mGeckoChild); - geckoEvent.mDelta = deltaZ; - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - // Keep track of the cumulative magnification for the final "magnify" event. - mCumulativeMagnification += deltaZ; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)smartMagnifyWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) { - return; - } - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // Setup the "double tap" event. - WidgetSimpleGestureEvent geckoEvent(true, eTapGesture, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - geckoEvent.mClickCount = 1; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - // Clear the gesture state - mGestureState = eGestureState_None; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rotateWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - float rotation = [anEvent rotation]; - - EventMessage msg; - switch (mGestureState) { - case eGestureState_StartGesture: - msg = eRotateGestureStart; - mGestureState = eGestureState_RotateGesture; - break; - - case eGestureState_RotateGesture: - msg = eRotateGestureUpdate; - break; - - case eGestureState_None: - case eGestureState_MagnifyGesture: - default: - return; - } - - // Setup the event. - WidgetSimpleGestureEvent geckoEvent(true, msg, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - geckoEvent.mDelta = -rotation; - if (rotation > 0.0) { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; - } else { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; - } - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - - // Keep track of the cumulative rotation for the final "rotate" event. - mCumulativeRotation += rotation; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)endGestureWithEvent:(NSEvent *)anEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!anEvent || !mGeckoChild) { - // Clear the gestures state if we cannot send an event. - mGestureState = eGestureState_None; - mCumulativeMagnification = 0.0; - mCumulativeRotation = 0.0; - return; - } - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - switch (mGestureState) { - case eGestureState_MagnifyGesture: - { - // Setup the "magnify" event. - WidgetSimpleGestureEvent geckoEvent(true, eMagnifyGesture, mGeckoChild); - geckoEvent.mDelta = mCumulativeMagnification; - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - } - break; - - case eGestureState_RotateGesture: - { - // Setup the "rotate" event. - WidgetSimpleGestureEvent geckoEvent(true, eRotateGesture, mGeckoChild); - [self convertCocoaMouseEvent:anEvent toGeckoEvent:&geckoEvent]; - geckoEvent.mDelta = -mCumulativeRotation; - if (mCumulativeRotation > 0.0) { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_COUNTERCLOCKWISE; - } else { - geckoEvent.mDirection = nsIDOMSimpleGestureEvent::ROTATION_CLOCKWISE; - } - - // Send the event. - mGeckoChild->DispatchWindowEvent(geckoEvent); - } - break; - - case eGestureState_None: - case eGestureState_StartGesture: - default: - break; - } - - // Clear the gestures state. - mGestureState = eGestureState_None; - mCumulativeMagnification = 0.0; - mCumulativeRotation = 0.0; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (bool)shouldConsiderStartingSwipeFromEvent:(NSEvent*)anEvent -{ - // This method checks whether the AppleEnableSwipeNavigateWithScrolls global - // preference is set. If it isn't, fluid swipe tracking is disabled, and a - // horizontal two-finger gesture is always a scroll (even in Safari). This - // preference can't (currently) be set from the Preferences UI -- only using - // 'defaults write'. - if (![NSEvent isSwipeTrackingFromScrollEventsEnabled]) { - return false; - } - - // Only initiate horizontal tracking for gestures that have just begun -- - // otherwise a scroll to one side of the page can have a swipe tacked on - // to it. - NSEventPhase eventPhase = nsCocoaUtils::EventPhase(anEvent); - if ([anEvent type] != NSScrollWheel || - eventPhase != NSEventPhaseBegan || - ![anEvent hasPreciseScrollingDeltas]) { - return false; - } - - // Only initiate horizontal tracking for events whose horizontal element is - // at least eight times larger than its vertical element. This minimizes - // performance problems with vertical scrolls (by minimizing the possibility - // that they'll be misinterpreted as horizontal swipes), while still - // tolerating a small vertical element to a true horizontal swipe. The number - // '8' was arrived at by trial and error. - CGFloat deltaX = [anEvent scrollingDeltaX]; - CGFloat deltaY = [anEvent scrollingDeltaY]; - return std::abs(deltaX) > std::abs(deltaY) * 8; -} - -- (void)setUsingOMTCompositor:(BOOL)aUseOMTC -{ - mUsingOMTCompositor = aUseOMTC; -} - -// Returning NO from this method only disallows ordering on mousedown - in order -// to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering] -// when handling the mousedown event. -- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)aEvent -{ - // Always using system-provided window ordering for normal windows. - if (![[self window] isKindOfClass:[PopupWindow class]]) - return NO; - - // Don't reorder when we don't have a parent window, like when we're a - // context menu or a tooltip. - return ![[self window] parentWindow]; -} - -- (void)mouseDown:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if ([self shouldDelayWindowOrderingForEvent:theEvent]) { - [NSApp preventWindowOrdering]; - } - - // If we've already seen this event due to direct dispatch from menuForEvent: - // just bail; if not, remember it. - if (mLastMouseDownEvent == theEvent) { - [mLastMouseDownEvent release]; - mLastMouseDownEvent = nil; - return; - } - else { - [mLastMouseDownEvent release]; - mLastMouseDownEvent = [theEvent retain]; - } - - [gLastDragMouseDownEvent release]; - gLastDragMouseDownEvent = [theEvent retain]; - - // We need isClickThrough because at this point the window we're in might - // already have become main, so the check for isMainWindow in - // WindowAcceptsEvent isn't enough. It also has to check isClickThrough. - BOOL isClickThrough = (theEvent == mClickThroughMouseDownEvent); - [mClickThroughMouseDownEvent release]; - mClickThroughMouseDownEvent = nil; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if ([self maybeRollup:theEvent] || - !ChildViewMouseTracker::WindowAcceptsEvent([self window], theEvent, self, isClickThrough)) { - // Remember blocking because that means we want to block mouseup as well. - mBlockedLastMouseDown = YES; - return; - } - -#if USE_CLICK_HOLD_CONTEXTMENU - // fire off timer to check for click-hold after two seconds. retains |theEvent| - [self performSelector:@selector(clickHoldCallback:) withObject:theEvent afterDelay:2.0]; -#endif - - // in order to send gecko events we'll need a gecko widget - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - NSUInteger modifierFlags = [theEvent modifierFlags]; - - WidgetMouseEvent geckoEvent(true, eMouseDown, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - - NSInteger clickCount = [theEvent clickCount]; - if (mBlockedLastMouseDown && clickCount > 1) { - // Don't send a double click if the first click of the double click was - // blocked. - clickCount--; - } - geckoEvent.mClickCount = clickCount; - - if (modifierFlags & NSControlKeyMask) - geckoEvent.button = WidgetMouseEvent::eRightButton; - else - geckoEvent.button = WidgetMouseEvent::eLeftButton; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - mBlockedLastMouseDown = NO; - - // XXX maybe call markedTextSelectionChanged:client: here? - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)mouseUp:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild || mBlockedLastMouseDown) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - if ([theEvent modifierFlags] & NSControlKeyMask) - geckoEvent.button = WidgetMouseEvent::eRightButton; - else - geckoEvent.button = WidgetMouseEvent::eLeftButton; - - // This might destroy our widget (and null out mGeckoChild). - bool defaultPrevented = - (mGeckoChild->DispatchInputEvent(&geckoEvent) == nsEventStatus_eConsumeNoDefault); - - // Check to see if we are double-clicking in the titlebar. - CGFloat locationInTitlebar = [[self window] frame].size.height - [theEvent locationInWindow].y; - LayoutDeviceIntPoint pos = geckoEvent.mRefPoint; - if (!defaultPrevented && [theEvent clickCount] == 2 && - !mGeckoChild->GetNonDraggableRegion().Contains(pos.x, pos.y) && - [[self window] isKindOfClass:[ToolbarWindow class]] && - (locationInTitlebar < [(ToolbarWindow*)[self window] titlebarHeight] || - locationInTitlebar < [(ToolbarWindow*)[self window] unifiedToolbarHeight])) { - if ([self shouldZoomOnDoubleClick]) { - [[self window] performZoom:nil]; - } else if ([self shouldMinimizeOnTitlebarDoubleClick]) { - NSButton *minimizeButton = [[self window] standardWindowButton:NSWindowMiniaturizeButton]; - [minimizeButton performClick:self]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent - enter:(BOOL)aEnter - exitFrom:(WidgetMouseEvent::ExitFrom)aExitFrom -{ - if (!mGeckoChild) - return; - - NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, [self window]); - NSPoint localEventLocation = [self convertPoint:windowEventLocation fromView:nil]; - - EventMessage msg = aEnter ? eMouseEnterIntoWidget : eMouseExitFromWidget; - WidgetMouseEvent event(true, msg, mGeckoChild, WidgetMouseEvent::eReal); - event.mRefPoint = mGeckoChild->CocoaPointsToDevPixels(localEventLocation); - - event.mExitFrom = aExitFrom; - - nsEventStatus status; // ignored - mGeckoChild->DispatchEvent(&event, status); -} - -- (void)handleMouseMoved:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)mouseDragged:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - gLastDragView = self; - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - - // Note, sending the above event might have destroyed our widget since we didn't retain. - // Fine so long as we don't access any local variables from here on. - gLastDragView = nil; - - // XXX maybe call markedTextSelectionChanged:client: here? - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rightMouseDown:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - [self maybeRollup:theEvent]; - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - // The right mouse went down, fire off a right mouse down event to gecko - WidgetMouseEvent geckoEvent(true, eMouseDown, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - geckoEvent.mClickCount = [theEvent clickCount]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - if (!mGeckoChild) - return; - - // Let the superclass do the context menu stuff. - [super rightMouseDown:theEvent]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rightMouseUp:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - geckoEvent.mClickCount = [theEvent clickCount]; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchInputEvent(&geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)rightMouseDragged:(NSEvent*)theEvent -{ - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - - // send event into Gecko by going directly to the - // the widget. - mGeckoChild->DispatchInputEvent(&geckoEvent); -} - -- (void)otherMouseDown:(NSEvent *)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if ([self maybeRollup:theEvent] || - !ChildViewMouseTracker::WindowAcceptsEvent([self window], theEvent, self)) - return; - - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseDown, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eMiddleButton; - geckoEvent.mClickCount = [theEvent clickCount]; - - mGeckoChild->DispatchInputEvent(&geckoEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)otherMouseUp:(NSEvent *)theEvent -{ - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eMiddleButton; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchInputEvent(&geckoEvent); -} - -- (void)otherMouseDragged:(NSEvent*)theEvent -{ - if (!mGeckoChild) - return; - if (mTextInputHandler->OnHandleEvent(theEvent)) { - return; - } - - WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eMiddleButton; - - // send event into Gecko by going directly to the - // the widget. - mGeckoChild->DispatchInputEvent(&geckoEvent); -} - -- (void)sendWheelStartOrStop:(EventMessage)msg forEvent:(NSEvent *)theEvent -{ - WidgetWheelEvent wheelEvent(true, msg, mGeckoChild); - [self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent]; - mExpectingWheelStop = (msg == eWheelOperationStart); - mGeckoChild->DispatchInputEvent(wheelEvent.AsInputEvent()); -} - -- (void)sendWheelCondition:(BOOL)condition - first:(EventMessage)first - second:(EventMessage)second - forEvent:(NSEvent *)theEvent -{ - if (mExpectingWheelStop == condition) { - [self sendWheelStartOrStop:first forEvent:theEvent]; - } - [self sendWheelStartOrStop:second forEvent:theEvent]; -} - -static PanGestureInput::PanGestureType -PanGestureTypeForEvent(NSEvent* aEvent) -{ - switch (nsCocoaUtils::EventPhase(aEvent)) { - case NSEventPhaseMayBegin: - return PanGestureInput::PANGESTURE_MAYSTART; - case NSEventPhaseCancelled: - return PanGestureInput::PANGESTURE_CANCELLED; - case NSEventPhaseBegan: - return PanGestureInput::PANGESTURE_START; - case NSEventPhaseChanged: - return PanGestureInput::PANGESTURE_PAN; - case NSEventPhaseEnded: - return PanGestureInput::PANGESTURE_END; - case NSEventPhaseNone: - switch (nsCocoaUtils::EventMomentumPhase(aEvent)) { - case NSEventPhaseBegan: - return PanGestureInput::PANGESTURE_MOMENTUMSTART; - case NSEventPhaseChanged: - return PanGestureInput::PANGESTURE_MOMENTUMPAN; - case NSEventPhaseEnded: - return PanGestureInput::PANGESTURE_MOMENTUMEND; - default: - NS_ERROR("unexpected event phase"); - return PanGestureInput::PANGESTURE_PAN; - } - default: - NS_ERROR("unexpected event phase"); - return PanGestureInput::PANGESTURE_PAN; - } -} - -static int32_t RoundUp(double aDouble) -{ - return aDouble < 0 ? static_cast(floor(aDouble)) : - static_cast(ceil(aDouble)); -} - -static int32_t -TakeLargestInt(gfx::Float* aFloat) -{ - int32_t result(*aFloat); // truncate towards zero - *aFloat -= result; - return result; -} - -static gfx::IntPoint -AccumulateIntegerDelta(NSEvent* aEvent) -{ - static gfx::Point sAccumulator(0.0f, 0.0f); - if (nsCocoaUtils::EventPhase(aEvent) == NSEventPhaseBegan) { - sAccumulator = gfx::Point(0.0f, 0.0f); - } - sAccumulator.x += [aEvent deltaX]; - sAccumulator.y += [aEvent deltaY]; - return gfx::IntPoint(TakeLargestInt(&sAccumulator.x), - TakeLargestInt(&sAccumulator.y)); -} - -static gfx::IntPoint -GetIntegerDeltaForEvent(NSEvent* aEvent) -{ - if (nsCocoaFeatures::OnSierraOrLater() && [aEvent hasPreciseScrollingDeltas]) { - // Pixel scroll events (events with hasPreciseScrollingDeltas == YES) - // carry pixel deltas in the scrollingDeltaX/Y fields and line scroll - // information in the deltaX/Y fields. - // Prior to 10.12, these line scroll fields would be zero for most pixel - // scroll events and non-zero for some, whenever at least a full line - // worth of pixel scrolling had accumulated. That's the behavior we want. - // Starting with 10.12 however, pixel scroll events no longer accumulate - // deltaX and deltaY; they just report floating point values for every - // single event. So we need to do our own accumulation. - return AccumulateIntegerDelta(aEvent); - } - - // For line scrolls, or pre-10.12, just use the rounded up value of deltaX / deltaY. - return gfx::IntPoint(RoundUp([aEvent deltaX]), RoundUp([aEvent deltaY])); -} - -- (void)scrollWheel:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - ChildViewMouseTracker::MouseScrolled(theEvent); - - if ([self maybeRollup:theEvent]) { - return; - } - - if (!mGeckoChild) { - return; - } - - NSEventPhase phase = nsCocoaUtils::EventPhase(theEvent); - // Fire eWheelOperationStart/End events when 2 fingers touch/release the - // touchpad. - if (phase & NSEventPhaseMayBegin) { - [self sendWheelCondition:YES - first:eWheelOperationEnd - second:eWheelOperationStart - forEvent:theEvent]; - } else if (phase & (NSEventPhaseEnded | NSEventPhaseCancelled)) { - [self sendWheelCondition:NO - first:eWheelOperationStart - second:eWheelOperationEnd - forEvent:theEvent]; - } - - if (!mGeckoChild) { - return; - } - RefPtr geckoChildDeathGrip(mGeckoChild); - - NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(theEvent, [self window]); - - // Use convertWindowCoordinatesRoundDown when converting the position to - // integer screen pixels in order to ensure that coordinates which are just - // inside the right / bottom edges of the window don't end up outside of the - // window after rounding. - ScreenPoint position = ViewAs( - [self convertWindowCoordinatesRoundDown:locationInWindow], - PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent); - - bool usePreciseDeltas = nsCocoaUtils::HasPreciseScrollingDeltas(theEvent) && - Preferences::GetBool("mousewheel.enable_pixel_scrolling", true); - bool hasPhaseInformation = nsCocoaUtils::EventHasPhaseInformation(theEvent); - - gfx::IntPoint lineOrPageDelta = -GetIntegerDeltaForEvent(theEvent); - - Modifiers modifiers = nsCocoaUtils::ModifiersForEvent(theEvent); - - NSTimeInterval beforeNow = [[NSProcessInfo processInfo] systemUptime] - [theEvent timestamp]; - PRIntervalTime eventIntervalTime = PR_IntervalNow() - PR_MillisecondsToInterval(beforeNow * 1000); - TimeStamp eventTimeStamp = TimeStamp::Now() - TimeDuration::FromSeconds(beforeNow); - - ScreenPoint preciseDelta; - if (usePreciseDeltas) { - CGFloat pixelDeltaX = 0, pixelDeltaY = 0; - nsCocoaUtils::GetScrollingDeltas(theEvent, &pixelDeltaX, &pixelDeltaY); - double scale = geckoChildDeathGrip->BackingScaleFactor(); - preciseDelta = ScreenPoint(-pixelDeltaX * scale, -pixelDeltaY * scale); - } - - if (usePreciseDeltas && hasPhaseInformation) { - PanGestureInput panEvent(PanGestureTypeForEvent(theEvent), - eventIntervalTime, eventTimeStamp, - position, preciseDelta, modifiers); - panEvent.mLineOrPageDeltaX = lineOrPageDelta.x; - panEvent.mLineOrPageDeltaY = lineOrPageDelta.y; - - if (panEvent.mType == PanGestureInput::PANGESTURE_END) { - // Check if there's a momentum start event in the event queue, so that we - // can annotate this event. - NSEvent* nextWheelEvent = - [NSApp nextEventMatchingMask:NSScrollWheelMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:NO]; - if (nextWheelEvent && - PanGestureTypeForEvent(nextWheelEvent) == PanGestureInput::PANGESTURE_MOMENTUMSTART) { - panEvent.mFollowedByMomentum = true; - } - } - - bool canTriggerSwipe = [self shouldConsiderStartingSwipeFromEvent:theEvent]; - panEvent.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection = canTriggerSwipe; - geckoChildDeathGrip->DispatchAPZWheelInputEvent(panEvent, canTriggerSwipe); - } else if (usePreciseDeltas) { - // This is on 10.6 or old touchpads that don't have any phase information. - ScrollWheelInput wheelEvent(eventIntervalTime, eventTimeStamp, modifiers, - ScrollWheelInput::SCROLLMODE_INSTANT, - ScrollWheelInput::SCROLLDELTA_PIXEL, - position, - preciseDelta.x, - preciseDelta.y, - false); - wheelEvent.mLineOrPageDeltaX = lineOrPageDelta.x; - wheelEvent.mLineOrPageDeltaY = lineOrPageDelta.y; - wheelEvent.mIsMomentum = nsCocoaUtils::IsMomentumScrollEvent(theEvent); - geckoChildDeathGrip->DispatchAPZWheelInputEvent(wheelEvent, false); - } else { - ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT; - if (gfxPrefs::SmoothScrollEnabled() && gfxPrefs::WheelSmoothScrollEnabled()) { - scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH; - } - ScrollWheelInput wheelEvent(eventIntervalTime, eventTimeStamp, modifiers, - scrollMode, - ScrollWheelInput::SCROLLDELTA_LINE, - position, - lineOrPageDelta.x, - lineOrPageDelta.y, - false); - wheelEvent.mLineOrPageDeltaX = lineOrPageDelta.x; - wheelEvent.mLineOrPageDeltaY = lineOrPageDelta.y; - geckoChildDeathGrip->DispatchAPZWheelInputEvent(wheelEvent, false); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - --(NSMenu*)menuForEvent:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!mGeckoChild) - return nil; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - [self maybeRollup:theEvent]; - if (!mGeckoChild) - return nil; - - // Cocoa doesn't always dispatch a mouseDown: for a control-click event, - // depends on what we return from menuForEvent:. Gecko always expects one - // and expects the mouse down event before the context menu event, so - // get that event sent first if this is a left mouse click. - if ([theEvent type] == NSLeftMouseDown) { - [self mouseDown:theEvent]; - if (!mGeckoChild) - return nil; - } - - WidgetMouseEvent geckoEvent(true, eContextMenu, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - geckoEvent.button = WidgetMouseEvent::eRightButton; - mGeckoChild->DispatchInputEvent(&geckoEvent); - if (!mGeckoChild) - return nil; - - [self maybeInitContextMenuTracking]; - - // Go up our view chain to fetch the correct menu to return. - return [self contextMenu]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (NSMenu*)contextMenu -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSView* superView = [self superview]; - if ([superView respondsToSelector:@selector(contextMenu)]) - return [(NSView*)superView contextMenu]; - - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetWheelEvent*)outWheelEvent -{ - [self convertCocoaMouseEvent:aMouseEvent toGeckoEvent:outWheelEvent]; - - bool usePreciseDeltas = nsCocoaUtils::HasPreciseScrollingDeltas(aMouseEvent) && - Preferences::GetBool("mousewheel.enable_pixel_scrolling", true); - - outWheelEvent->mDeltaMode = - usePreciseDeltas ? nsIDOMWheelEvent::DOM_DELTA_PIXEL - : nsIDOMWheelEvent::DOM_DELTA_LINE; - outWheelEvent->mIsMomentum = nsCocoaUtils::IsMomentumScrollEvent(aMouseEvent); -} - -- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent - toGeckoEvent:(WidgetInputEvent*)outGeckoEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ASSERTION(outGeckoEvent, "convertCocoaMouseEvent:toGeckoEvent: requires non-null aoutGeckoEvent"); - if (!outGeckoEvent) - return; - - nsCocoaUtils::InitInputEvent(*outGeckoEvent, aMouseEvent); - - // convert point to view coordinate system - NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(aMouseEvent, [self window]); - - outGeckoEvent->mRefPoint = [self convertWindowCoordinates:locationInWindow]; - - WidgetMouseEventBase* mouseEvent = outGeckoEvent->AsMouseEventBase(); - mouseEvent->buttons = 0; - NSUInteger mouseButtons = [NSEvent pressedMouseButtons]; - - if (mouseButtons & 0x01) { - mouseEvent->buttons |= WidgetMouseEvent::eLeftButtonFlag; - } - if (mouseButtons & 0x02) { - mouseEvent->buttons |= WidgetMouseEvent::eRightButtonFlag; - } - if (mouseButtons & 0x04) { - mouseEvent->buttons |= WidgetMouseEvent::eMiddleButtonFlag; - } - if (mouseButtons & 0x08) { - mouseEvent->buttons |= WidgetMouseEvent::e4thButtonFlag; - } - if (mouseButtons & 0x10) { - mouseEvent->buttons |= WidgetMouseEvent::e5thButtonFlag; - } - - switch ([aMouseEvent type]) { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSLeftMouseDragged: - case NSRightMouseDown: - case NSRightMouseUp: - case NSRightMouseDragged: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - if ([aMouseEvent subtype] == NSTabletPointEventSubtype) { - mouseEvent->pressure = [aMouseEvent pressure]; - MOZ_ASSERT(mouseEvent->pressure >= 0.0 && mouseEvent->pressure <= 1.0); - } - break; - - default: - // Don't check other NSEvents for pressure. - break; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (BOOL)shouldZoomOnDoubleClick -{ - if ([NSWindow respondsToSelector:@selector(_shouldZoomOnDoubleClick)]) { - return [NSWindow _shouldZoomOnDoubleClick]; - } - return nsCocoaFeatures::OnYosemiteOrLater(); -} - -- (BOOL)shouldMinimizeOnTitlebarDoubleClick -{ - NSString *MDAppleMiniaturizeOnDoubleClickKey = - @"AppleMiniaturizeOnDoubleClick"; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - bool shouldMinimize = [[userDefaults - objectForKey:MDAppleMiniaturizeOnDoubleClickKey] boolValue]; - - return shouldMinimize; -} - -#pragma mark - -// NSTextInputClient implementation - -- (NSRange)markedRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NS_ENSURE_TRUE(mTextInputHandler, NSMakeRange(NSNotFound, 0)); - return mTextInputHandler->MarkedRange(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0)); -} - -- (NSRange)selectedRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NS_ENSURE_TRUE(mTextInputHandler, NSMakeRange(NSNotFound, 0)); - return mTextInputHandler->SelectedRange(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakeRange(0, 0)); -} - -- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex -{ - NS_ENSURE_TRUE(mTextInputHandler, NO); - if (charIndex == NSNotFound) { - return NO; - } - return mTextInputHandler->DrawsVerticallyForCharacterAtIndex(charIndex); -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint -{ - NS_ENSURE_TRUE(mTextInputHandler, 0); - return mTextInputHandler->CharacterIndexForPoint(thePoint); -} - -- (NSArray*)validAttributesForMarkedText -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NS_ENSURE_TRUE(mTextInputHandler, [NSArray array]); - return mTextInputHandler->GetValidAttributesForMarkedText(); - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE_VOID(mGeckoChild); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - NSAttributedString* attrStr; - if ([aString isKindOfClass:[NSAttributedString class]]) { - attrStr = static_cast(aString); - } else { - attrStr = [[[NSAttributedString alloc] initWithString:aString] autorelease]; - } - - mTextInputHandler->InsertText(attrStr, &replacementRange); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild || !mTextInputHandler) { - return; - } - - const char* sel = reinterpret_cast(aSelector); - if (!mTextInputHandler->DoCommandBySelector(sel)) { - [super doCommandBySelector:aSelector]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)unmarkText -{ - NS_ENSURE_TRUE_VOID(mTextInputHandler); - mTextInputHandler->CommitIMEComposition(); -} - -- (BOOL) hasMarkedText -{ - NS_ENSURE_TRUE(mTextInputHandler, NO); - return mTextInputHandler->HasMarkedText(); -} - -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange - replacementRange:(NSRange)replacementRange -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE_VOID(mTextInputHandler); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - NSAttributedString* attrStr; - if ([aString isKindOfClass:[NSAttributedString class]]) { - attrStr = static_cast(aString); - } else { - attrStr = [[[NSAttributedString alloc] initWithString:aString] autorelease]; - } - - mTextInputHandler->SetMarkedText(attrStr, selectedRange, &replacementRange); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange - actualRange:(NSRangePointer)actualRange -{ - NS_ENSURE_TRUE(mTextInputHandler, nil); - return mTextInputHandler->GetAttributedSubstringFromRange(aRange, - actualRange); -} - -- (NSRect)firstRectForCharacterRange:(NSRange)aRange - actualRange:(NSRangePointer)actualRange -{ - NS_ENSURE_TRUE(mTextInputHandler, NSMakeRect(0.0, 0.0, 0.0, 0.0)); - return mTextInputHandler->FirstRectForCharacterRange(aRange, actualRange); -} - -- (void)quickLookWithEvent:(NSEvent*)event -{ - // Show dictionary by current point - WidgetContentCommandEvent - contentCommandEvent(true, eContentCommandLookUpDictionary, mGeckoChild); - NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil]; - contentCommandEvent.mRefPoint = mGeckoChild->CocoaPointsToDevPixels(point); - mGeckoChild->DispatchWindowEvent(contentCommandEvent); - // The widget might have been destroyed. -} - -- (NSInteger)windowLevel -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NS_ENSURE_TRUE(mTextInputHandler, [[self window] level]); - return mTextInputHandler->GetWindowLevel(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSNormalWindowLevel); -} - -#pragma mark - - -// This is a private API that Cocoa uses. -// Cocoa will call this after the menu system returns "NO" for "performKeyEquivalent:". -// We want all they key events we can get so just return YES. In particular, this fixes -// ctrl-tab - we don't get a "keyDown:" call for that without this. -- (BOOL)_wantsKeyDownForEvent:(NSEvent*)event -{ - return YES; -} - -- (NSEvent*)lastKeyDownEvent -{ - return mLastKeyDownEvent; -} - -- (void)keyDown:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mLastKeyDownEvent release]; - mLastKeyDownEvent = [theEvent retain]; - - // Weird things can happen on keyboard input if the key window isn't in the - // current space. For example see bug 1056251. To get around this, always - // make sure that, if our window is key, it's also made frontmost. Doing - // this automatically switches to whatever space our window is in. Safari - // does something similar. Our window should normally always be key -- - // otherwise why is the OS sending us a key down event? But it's just - // possible we're in Gecko's hidden window, so we check first. - NSWindow *viewWindow = [self window]; - if (viewWindow && [viewWindow isKeyWindow]) { - [viewWindow orderWindow:NSWindowAbove relativeTo:0]; - } - -#if !defined(RELEASE_OR_BETA) || defined(DEBUG) - if (!Preferences::GetBool("intl.allow-insecure-text-input", false) && - mGeckoChild && mTextInputHandler && mTextInputHandler->IsFocused()) { - if (mGeckoChild->GetInputContext().IsPasswordEditor() && - !TextInputHandler::IsSecureEventInputEnabled()) { - #define CRASH_MESSAGE "A password editor has focus, but not in secure input mode" - MOZ_CRASH(CRASH_MESSAGE); - #undef CRASH_MESSAGE - } else if (!mGeckoChild->GetInputContext().IsPasswordEditor() && - TextInputHandler::IsSecureEventInputEnabled()) { - #define CRASH_MESSAGE "A non-password editor has focus, but in secure input mode" - MOZ_CRASH(CRASH_MESSAGE); - #undef CRASH_MESSAGE - } - } -#endif // #if !defined(RELEASE_OR_BETA) || defined(DEBUG) - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - bool handled = false; - if (mGeckoChild && mTextInputHandler) { - handled = mTextInputHandler->HandleKeyDownEvent(theEvent); - } - - // We always allow keyboard events to propagate to keyDown: but if they are not - // handled we give special Application menu items a chance to act. - if (!handled && sApplicationMenu) { - [sApplicationMenu performKeyEquivalent:theEvent]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)keyUp:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE(mGeckoChild, ); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - mTextInputHandler->HandleKeyUpEvent(theEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)insertNewline:(id)sender -{ - if (mTextInputHandler) { - NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"\n"]; - mTextInputHandler->InsertText(attrStr); - [attrStr release]; - } -} - -- (void)flagsChanged:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NS_ENSURE_TRUE(mGeckoChild, ); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mTextInputHandler->HandleFlagsChanged(theEvent); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (BOOL) isFirstResponder -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSResponder* resp = [[self window] firstResponder]; - return (resp == (NSResponder*)self); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -- (BOOL)isDragInProgress -{ - if (!mDragService) - return NO; - - nsCOMPtr dragSession; - mDragService->GetCurrentSession(getter_AddRefs(dragSession)); - return dragSession != nullptr; -} - -- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent -{ - // If we're being destroyed assume the default -- return YES. - if (!mGeckoChild) - return YES; - - WidgetMouseEvent geckoEvent(true, eMouseActivate, mGeckoChild, - WidgetMouseEvent::eReal); - [self convertCocoaMouseEvent:aEvent toGeckoEvent:&geckoEvent]; - return (mGeckoChild->DispatchInputEvent(&geckoEvent) != nsEventStatus_eConsumeNoDefault); -} - -// We must always call through to our superclass, even when mGeckoChild is -// nil -- otherwise the keyboard focus can end up in the wrong NSView. -- (BOOL)becomeFirstResponder -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return [super becomeFirstResponder]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES); -} - -- (void)viewsWindowDidBecomeKey -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // check to see if the window implements the mozWindow protocol. This - // allows embedders to avoid re-entrant calls to -makeKeyAndOrderFront, - // which can happen because these activate calls propagate out - // to the embedder via nsIEmbeddingSiteWindow::SetFocus(). - BOOL isMozWindow = [[self window] respondsToSelector:@selector(setSuppressMakeKeyFront:)]; - if (isMozWindow) - [[self window] setSuppressMakeKeyFront:YES]; - - nsIWidgetListener* listener = mGeckoChild->GetWidgetListener(); - if (listener) - listener->WindowActivated(); - - if (isMozWindow) - [[self window] setSuppressMakeKeyFront:NO]; - - if (mGeckoChild->GetInputContext().IsPasswordEditor()) { - TextInputHandler::EnableSecureEventInput(); - } else { - TextInputHandler::EnsureSecureEventInputDisabled(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)viewsWindowDidResignKey -{ - if (!mGeckoChild) - return; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - nsIWidgetListener* listener = mGeckoChild->GetWidgetListener(); - if (listener) - listener->WindowDeactivated(); - - TextInputHandler::EnsureSecureEventInputDisabled(); -} - -// If the call to removeFromSuperview isn't delayed from nsChildView:: -// TearDownView(), the NSView hierarchy might get changed during calls to -// [ChildView drawRect:], which leads to "beyond bounds" exceptions in -// NSCFArray. For more info see bmo bug 373122. Apple's docs claim that -// removeFromSuperviewWithoutNeedingDisplay "can be safely invoked during -// display" (whatever "display" means). But it's _not_ true that it can be -// safely invoked during calls to [NSView drawRect:]. We use -// removeFromSuperview here because there's no longer any danger of being -// "invoked during display", and because doing do clears up bmo bug 384343. -- (void)delayedTearDown -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [self removeFromSuperview]; - [self release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#pragma mark - - -// drag'n'drop stuff -#define kDragServiceContractID "@mozilla.org/widget/dragservice;1" - -- (NSDragOperation)dragOperationFromDragAction:(int32_t)aDragAction -{ - if (nsIDragService::DRAGDROP_ACTION_LINK & aDragAction) - return NSDragOperationLink; - if (nsIDragService::DRAGDROP_ACTION_COPY & aDragAction) - return NSDragOperationCopy; - if (nsIDragService::DRAGDROP_ACTION_MOVE & aDragAction) - return NSDragOperationGeneric; - return NSDragOperationNone; -} - -- (LayoutDeviceIntPoint)convertWindowCoordinates:(NSPoint)aPoint -{ - if (!mGeckoChild) { - return LayoutDeviceIntPoint(0, 0); - } - - NSPoint localPoint = [self convertPoint:aPoint fromView:nil]; - return mGeckoChild->CocoaPointsToDevPixels(localPoint); -} - -- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint -{ - if (!mGeckoChild) { - return LayoutDeviceIntPoint(0, 0); - } - - NSPoint localPoint = [self convertPoint:aPoint fromView:nil]; - return mGeckoChild->CocoaPointsToDevPixelsRoundDown(localPoint); -} - -// This is a utility function used by NSView drag event methods -// to send events. It contains all of the logic needed for Gecko -// dragging to work. Returns the appropriate cocoa drag operation code. -- (NSDragOperation)doDragAction:(EventMessage)aMessage sender:(id)aSender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!mGeckoChild) - return NSDragOperationNone; - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView doDragAction: entered\n")); - - if (!mDragService) { - CallGetService(kDragServiceContractID, &mDragService); - NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!"); - if (!mDragService) - return NSDragOperationNone; - } - - if (aMessage == eDragEnter) { - mDragService->StartDragSession(); - } - - nsCOMPtr dragSession; - mDragService->GetCurrentSession(getter_AddRefs(dragSession)); - if (dragSession) { - if (aMessage == eDragOver) { - // fire the drag event at the source. Just ignore whether it was - // cancelled or not as there isn't actually a means to stop the drag - mDragService->FireDragEventAtSource(eDrag); - dragSession->SetCanDrop(false); - } else if (aMessage == eDrop) { - // We make the assumption that the dragOver handlers have correctly set - // the |canDrop| property of the Drag Session. - bool canDrop = false; - if (!NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)) || !canDrop) { - [self doDragAction:eDragExit sender:aSender]; - - nsCOMPtr sourceNode; - dragSession->GetSourceNode(getter_AddRefs(sourceNode)); - if (!sourceNode) { - mDragService->EndDragSession(false); - } - return NSDragOperationNone; - } - } - - unsigned int modifierFlags = [[NSApp currentEvent] modifierFlags]; - uint32_t action = nsIDragService::DRAGDROP_ACTION_MOVE; - // force copy = option, alias = cmd-option, default is move - if (modifierFlags & NSAlternateKeyMask) { - if (modifierFlags & NSCommandKeyMask) - action = nsIDragService::DRAGDROP_ACTION_LINK; - else - action = nsIDragService::DRAGDROP_ACTION_COPY; - } - dragSession->SetDragAction(action); - } - - // set up gecko event - WidgetDragEvent geckoEvent(true, aMessage, mGeckoChild); - nsCocoaUtils::InitInputEvent(geckoEvent, [NSApp currentEvent]); - - // Use our own coordinates in the gecko event. - // Convert event from gecko global coords to gecko view coords. - NSPoint draggingLoc = [aSender draggingLocation]; - - geckoEvent.mRefPoint = [self convertWindowCoordinates:draggingLoc]; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchInputEvent(&geckoEvent); - if (!mGeckoChild) - return NSDragOperationNone; - - if (dragSession) { - switch (aMessage) { - case eDragEnter: - case eDragOver: { - uint32_t dragAction; - dragSession->GetDragAction(&dragAction); - - // If TakeChildProcessDragAction returns something other than - // DRAGDROP_ACTION_UNINITIALIZED, it means that the last event was sent - // to the child process and this event is also being sent to the child - // process. In this case, use the last event's action instead. - nsDragService* dragService = static_cast(mDragService); - int32_t childDragAction = dragService->TakeChildProcessDragAction(); - if (childDragAction != nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) { - dragAction = childDragAction; - } - - return [self dragOperationFromDragAction:dragAction]; - } - case eDragExit: - case eDrop: { - nsCOMPtr sourceNode; - dragSession->GetSourceNode(getter_AddRefs(sourceNode)); - if (!sourceNode) { - // We're leaving a window while doing a drag that was - // initiated in a different app. End the drag session, - // since we're done with it for now (until the user - // drags back into mozilla). - mDragService->EndDragSession(false); - } - } - default: - break; - } - } - - return NSDragOperationGeneric; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSDragOperationNone); -} - -- (NSDragOperation)draggingEntered:(id )sender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingEntered: entered\n")); - - // there should never be a globalDragPboard when "draggingEntered:" is - // called, but just in case we'll take care of it here. - [globalDragPboard release]; - - // Set the global drag pasteboard that will be used for this drag session. - // This will be set back to nil when the drag session ends (mouse exits - // the view or a drop happens within the view). - globalDragPboard = [[sender draggingPasteboard] retain]; - - return [self doDragAction:eDragEnter sender:sender]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSDragOperationNone); -} - -- (NSDragOperation)draggingUpdated:(id )sender -{ - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingUpdated: entered\n")); - - return [self doDragAction:eDragOver sender:sender]; -} - -- (void)draggingExited:(id )sender -{ - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView draggingExited: entered\n")); - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - [self doDragAction:eDragExit sender:sender]; - NS_IF_RELEASE(mDragService); -} - -- (BOOL)performDragOperation:(id )sender -{ - nsAutoRetainCocoaObject kungFuDeathGrip(self); - BOOL handled = [self doDragAction:eDrop sender:sender] != NSDragOperationNone; - NS_IF_RELEASE(mDragService); - return handled; -} - -// NSDraggingSource -- (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint -{ - // Get the drag service if it isn't already cached. The drag service - // isn't cached when dragging over a different application. - nsCOMPtr dragService = mDragService; - if (!dragService) { - dragService = do_GetService(kDragServiceContractID); - } - - if (dragService) { - NSPoint pnt = [NSEvent mouseLocation]; - FlipCocoaScreenCoordinate(pnt); - - LayoutDeviceIntPoint devPoint = mGeckoChild->CocoaPointsToDevPixels(pnt); - dragService->DragMoved(devPoint.x, devPoint.y); - } -} - -// NSDraggingSource -- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - gDraggedTransferables = nullptr; - - NSEvent *currentEvent = [NSApp currentEvent]; - gUserCancelledDrag = ([currentEvent type] == NSKeyDown && - [currentEvent keyCode] == kVK_Escape); - - if (!mDragService) { - CallGetService(kDragServiceContractID, &mDragService); - NS_ASSERTION(mDragService, "Couldn't get a drag service - big problem!"); - } - - if (mDragService) { - // set the dragend point from the current mouse location - nsDragService* dragService = static_cast(mDragService); - NSPoint pnt = [NSEvent mouseLocation]; - FlipCocoaScreenCoordinate(pnt); - dragService->SetDragEndPoint(gfx::IntPoint::Round(pnt.x, pnt.y)); - - // XXX: dropEffect should be updated per |operation|. - // As things stand though, |operation| isn't well handled within "our" - // events, that is, when the drop happens within the window: it is set - // either to NSDragOperationGeneric or to NSDragOperationNone. - // For that reason, it's not yet possible to override dropEffect per the - // given OS value, and it's also unclear what's the correct dropEffect - // value for NSDragOperationGeneric that is passed by other applications. - // All that said, NSDragOperationNone is still reliable. - if (operation == NSDragOperationNone) { - nsCOMPtr dataTransfer; - dragService->GetDataTransfer(getter_AddRefs(dataTransfer)); - if (dataTransfer) - dataTransfer->SetDropEffectInt(nsIDragService::DRAGDROP_ACTION_NONE); - } - - mDragService->EndDragSession(true); - NS_RELEASE(mDragService); - } - - [globalDragPboard release]; - globalDragPboard = nil; - [gLastDragMouseDownEvent release]; - gLastDragMouseDownEvent = nil; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// NSDraggingSource -// this is just implemented so we comply with the NSDraggingSource informal protocol -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal -{ - return UINT_MAX; -} - -// This method is a callback typically invoked in response to a drag ending on the desktop -// or a Findow folder window; the argument passed is a path to the drop location, to be used -// in constructing a complete pathname for the file(s) we want to create as a result of -// the drag. -- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDestination -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsresult rv; - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("ChildView namesOfPromisedFilesDroppedAtDestination: entering callback for promised files\n")); - - nsCOMPtr targFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(targFile)); - nsCOMPtr macLocalFile = do_QueryInterface(targFile); - if (!macLocalFile) { - NS_ERROR("No Mac local file"); - return nil; - } - - if (!NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)dropDestination))) { - NS_ERROR("failed InitWithCFURL"); - return nil; - } - - if (!gDraggedTransferables) - return nil; - - uint32_t transferableCount; - rv = gDraggedTransferables->GetLength(&transferableCount); - if (NS_FAILED(rv)) - return nil; - - for (uint32_t i = 0; i < transferableCount; i++) { - nsCOMPtr item = do_QueryElementAt(gDraggedTransferables, i); - if (!item) { - NS_ERROR("no transferable"); - return nil; - } - - item->SetTransferData(kFilePromiseDirectoryMime, macLocalFile, sizeof(nsIFile*)); - - // now request the kFilePromiseMime data, which will invoke the data provider - // If successful, the returned data is a reference to the resulting file. - nsCOMPtr fileDataPrimitive; - uint32_t dataSize = 0; - item->GetTransferData(kFilePromiseMime, getter_AddRefs(fileDataPrimitive), &dataSize); - } - - NSPasteboard* generalPboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - NSData* data = [generalPboard dataForType:@"application/x-moz-file-promise-dest-filename"]; - NSString* name = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSArray* rslt = [NSArray arrayWithObject:name]; - - [name release]; - - return rslt; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -#pragma mark - - -// Support for the "Services" menu. We currently only support sending strings -// and HTML to system services. - -- (id)validRequestorForSendType:(NSString *)sendType - returnType:(NSString *)returnType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - // sendType contains the type of data that the service would like this - // application to send to it. sendType is nil if the service is not - // requesting any data. - // - // returnType contains the type of data the the service would like to - // return to this application (e.g., to overwrite the selection). - // returnType is nil if the service will not return any data. - // - // The following condition thus triggers when the service expects a string - // or HTML from us or no data at all AND when the service will either not - // send back any data to us or will send a string or HTML back to us. - -#define IsSupportedType(typeStr) ([typeStr isEqual:NSStringPboardType] || [typeStr isEqual:NSHTMLPboardType]) - - id result = nil; - - if ((!sendType || IsSupportedType(sendType)) && - (!returnType || IsSupportedType(returnType))) { - if (mGeckoChild) { - // Assume that this object will be able to handle this request. - result = self; - - // Keep the ChildView alive during this operation. - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - if (sendType) { - // Determine if there is a current selection (chrome/content). - if (!nsClipboard::sSelectionCache) { - result = nil; - } - } - - // Determine if we can paste (if receiving data from the service). - if (mGeckoChild && returnType) { - WidgetContentCommandEvent command(true, - eContentCommandPasteTransferable, - mGeckoChild, true); - // This might possibly destroy our widget (and null out mGeckoChild). - mGeckoChild->DispatchWindowEvent(command); - if (!mGeckoChild || !command.mSucceeded || !command.mIsEnabled) - result = nil; - } - } - } - -#undef IsSupportedType - - // Give the superclass a chance if this object will not handle this request. - if (!result) - result = [super validRequestorForSendType:sendType returnType:returnType]; - - return result; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard - types:(NSArray *)types -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - // Make sure that the service will accept strings or HTML. - if ([types containsObject:NSStringPboardType] == NO && - [types containsObject:NSHTMLPboardType] == NO) - return NO; - - // Bail out if there is no Gecko object. - if (!mGeckoChild) - return NO; - - // Transform the transferable to an NSDictionary. - NSDictionary* pasteboardOutputDict = nullptr; - - pasteboardOutputDict = nsClipboard:: - PasteboardDictFromTransferable(nsClipboard::sSelectionCache); - - if (!pasteboardOutputDict) - return NO; - - // Declare the pasteboard types. - unsigned int typeCount = [pasteboardOutputDict count]; - NSMutableArray* declaredTypes = [NSMutableArray arrayWithCapacity:typeCount]; - [declaredTypes addObjectsFromArray:[pasteboardOutputDict allKeys]]; - [pboard declareTypes:declaredTypes owner:nil]; - - // Write the data to the pasteboard. - for (unsigned int i = 0; i < typeCount; i++) { - NSString* currentKey = [declaredTypes objectAtIndex:i]; - id currentValue = [pasteboardOutputDict valueForKey:currentKey]; - - if (currentKey == NSStringPboardType || - currentKey == kCorePboardType_url || - currentKey == kCorePboardType_urld || - currentKey == kCorePboardType_urln) { - [pboard setString:currentValue forType:currentKey]; - } else if (currentKey == NSHTMLPboardType) { - [pboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue)) forType:currentKey]; - } else if (currentKey == NSTIFFPboardType) { - [pboard setData:currentValue forType:currentKey]; - } else if (currentKey == NSFilesPromisePboardType) { - [pboard setPropertyList:currentValue forType:currentKey]; - } - } - - return YES; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -// Called if the service wants us to replace the current selection. -- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard -{ - nsresult rv; - nsCOMPtr trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv); - if (NS_FAILED(rv)) - return NO; - trans->Init(nullptr); - - trans->AddDataFlavor(kUnicodeMime); - trans->AddDataFlavor(kHTMLMime); - - rv = nsClipboard::TransferableFromPasteboard(trans, pboard); - if (NS_FAILED(rv)) - return NO; - - NS_ENSURE_TRUE(mGeckoChild, false); - - WidgetContentCommandEvent command(true, - eContentCommandPasteTransferable, - mGeckoChild); - command.mTransferable = trans; - mGeckoChild->DispatchWindowEvent(command); - - return command.mSucceeded && command.mIsEnabled; -} - -NS_IMETHODIMP -nsChildView::GetSelectionAsPlaintext(nsAString& aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!nsClipboard::sSelectionCache) { - MOZ_ASSERT(aResult.IsEmpty()); - return NS_OK; - } - - // Get the current chrome or content selection. - NSDictionary* pasteboardOutputDict = nullptr; - pasteboardOutputDict = nsClipboard:: - PasteboardDictFromTransferable(nsClipboard::sSelectionCache); - - if (NS_WARN_IF(!pasteboardOutputDict)) { - return NS_ERROR_FAILURE; - } - - // Declare the pasteboard types. - unsigned int typeCount = [pasteboardOutputDict count]; - NSMutableArray* declaredTypes = [NSMutableArray arrayWithCapacity:typeCount]; - [declaredTypes addObjectsFromArray:[pasteboardOutputDict allKeys]]; - NSString* currentKey = [declaredTypes objectAtIndex:0]; - NSString* currentValue = [pasteboardOutputDict valueForKey:currentKey]; - const char* textSelection = [currentValue UTF8String]; - aResult = NS_ConvertUTF8toUTF16(textSelection); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -#pragma mark - - -#ifdef ACCESSIBILITY - -/* Every ChildView has a corresponding mozDocAccessible object that is doing all - the heavy lifting. The topmost ChildView corresponds to a mozRootAccessible - object. - - All ChildView needs to do is to route all accessibility calls (from the NSAccessibility APIs) - down to its object, pretending that they are the same. -*/ -- (id)accessible -{ - if (!mGeckoChild) - return nil; - - id nativeAccessible = nil; - - nsAutoRetainCocoaObject kungFuDeathGrip(self); - RefPtr geckoChild(mGeckoChild); - RefPtr accessible = geckoChild->GetDocumentAccessible(); - if (!accessible) - return nil; - - accessible->GetNativeInterface((void**)&nativeAccessible); - -#ifdef DEBUG_hakan - NSAssert(![nativeAccessible isExpired], @"native acc is expired!!!"); -#endif - - return nativeAccessible; -} - -/* Implementation of formal mozAccessible formal protocol (enabling mozViews - to talk to mozAccessible objects in the accessibility module). */ - -- (BOOL)hasRepresentedView -{ - return YES; -} - -- (id)representedView -{ - return self; -} - -- (BOOL)isRoot -{ - return [[self accessible] isRoot]; -} - -#ifdef DEBUG -- (void)printHierarchy -{ - [[self accessible] printHierarchy]; -} -#endif - -#pragma mark - - -// general - -- (BOOL)accessibilityIsIgnored -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityIsIgnored]; - - return [[self accessible] accessibilityIsIgnored]; -} - -- (id)accessibilityHitTest:(NSPoint)point -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityHitTest:point]; - - return [[self accessible] accessibilityHitTest:point]; -} - -- (id)accessibilityFocusedUIElement -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityFocusedUIElement]; - - return [[self accessible] accessibilityFocusedUIElement]; -} - -// actions - -- (NSArray*)accessibilityActionNames -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityActionNames]; - - return [[self accessible] accessibilityActionNames]; -} - -- (NSString*)accessibilityActionDescription:(NSString*)action -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityActionDescription:action]; - - return [[self accessible] accessibilityActionDescription:action]; -} - -- (void)accessibilityPerformAction:(NSString*)action -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityPerformAction:action]; - - return [[self accessible] accessibilityPerformAction:action]; -} - -// attributes - -- (NSArray*)accessibilityAttributeNames -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityAttributeNames]; - - return [[self accessible] accessibilityAttributeNames]; -} - -- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute -{ - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityIsAttributeSettable:attribute]; - - return [[self accessible] accessibilityIsAttributeSettable:attribute]; -} - -- (id)accessibilityAttributeValue:(NSString*)attribute -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!mozilla::a11y::ShouldA11yBeEnabled()) - return [super accessibilityAttributeValue:attribute]; - - id accessible = [self accessible]; - - // if we're the root (topmost) accessible, we need to return our native AXParent as we - // traverse outside to the hierarchy of whoever embeds us. thus, fall back on NSView's - // default implementation for this attribute. - if ([attribute isEqualToString:NSAccessibilityParentAttribute] && [accessible isRoot]) { - id parentAccessible = [super accessibilityAttributeValue:attribute]; - return parentAccessible; - } - - return [accessible accessibilityAttributeValue:attribute]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -#endif /* ACCESSIBILITY */ - -@end - -@implementation PixelHostingView - -- (BOOL)isFlipped { - return YES; -} - -- (NSView*)hitTest:(NSPoint)aPoint { - return nil; -} - -- (void)drawRect:(NSRect)aRect { - [(ChildView*)[self superview] doDrawRect:aRect]; -} - -- (BOOL)wantsBestResolutionOpenGLSurface { - return nsCocoaUtils::HiDPIEnabled() ? YES : NO; -} - -@end - -#pragma mark - - -void -ChildViewMouseTracker::OnDestroyView(ChildView* aView) -{ - if (sLastMouseEventView == aView) { - sLastMouseEventView = nil; - [sLastMouseMoveEvent release]; - sLastMouseMoveEvent = nil; - } -} - -void -ChildViewMouseTracker::OnDestroyWindow(NSWindow* aWindow) -{ - if (sWindowUnderMouse == aWindow) { - sWindowUnderMouse = nil; - } -} - -void -ChildViewMouseTracker::MouseEnteredWindow(NSEvent* aEvent) -{ - sWindowUnderMouse = [aEvent window]; - ReEvaluateMouseEnterState(aEvent); -} - -void -ChildViewMouseTracker::MouseExitedWindow(NSEvent* aEvent) -{ - if (sWindowUnderMouse == [aEvent window]) { - sWindowUnderMouse = nil; - ReEvaluateMouseEnterState(aEvent); - } -} - -void -ChildViewMouseTracker::ReEvaluateMouseEnterState(NSEvent* aEvent, ChildView* aOldView) -{ - ChildView* oldView = aOldView ? aOldView : sLastMouseEventView; - sLastMouseEventView = ViewForEvent(aEvent); - if (sLastMouseEventView != oldView) { - // Send enter and / or exit events. - WidgetMouseEvent::ExitFrom exitFrom = - [sLastMouseEventView window] == [oldView window] ? - WidgetMouseEvent::eChild : WidgetMouseEvent::eTopLevel; - [oldView sendMouseEnterOrExitEvent:aEvent - enter:NO - exitFrom:exitFrom]; - // After the cursor exits the window set it to a visible regular arrow cursor. - if (exitFrom == WidgetMouseEvent::eTopLevel) { - [[nsCursorManager sharedInstance] setCursor:eCursor_standard]; - } - [sLastMouseEventView sendMouseEnterOrExitEvent:aEvent - enter:YES - exitFrom:exitFrom]; - } -} - -void -ChildViewMouseTracker::ResendLastMouseMoveEvent() -{ - if (sLastMouseMoveEvent) { - MouseMoved(sLastMouseMoveEvent); - } -} - -void -ChildViewMouseTracker::MouseMoved(NSEvent* aEvent) -{ - MouseEnteredWindow(aEvent); - [sLastMouseEventView handleMouseMoved:aEvent]; - if (sLastMouseMoveEvent != aEvent) { - [sLastMouseMoveEvent release]; - sLastMouseMoveEvent = [aEvent retain]; - } -} - -void -ChildViewMouseTracker::MouseScrolled(NSEvent* aEvent) -{ - if (!nsCocoaUtils::IsMomentumScrollEvent(aEvent)) { - // Store the position so we can pin future momentum scroll events. - sLastScrollEventScreenLocation = nsCocoaUtils::ScreenLocationForEvent(aEvent); - } -} - -ChildView* -ChildViewMouseTracker::ViewForEvent(NSEvent* aEvent) -{ - NSWindow* window = sWindowUnderMouse; - if (!window) - return nil; - - NSPoint windowEventLocation = nsCocoaUtils::EventLocationForWindow(aEvent, window); - NSView* view = [[[window contentView] superview] hitTest:windowEventLocation]; - - if (![view isKindOfClass:[ChildView class]]) - return nil; - - ChildView* childView = (ChildView*)view; - // If childView is being destroyed return nil. - if (![childView widget]) - return nil; - return WindowAcceptsEvent(window, aEvent, childView) ? childView : nil; -} - -BOOL -ChildViewMouseTracker::WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent, - ChildView* aView, BOOL aIsClickThrough) -{ - // Right mouse down events may get through to all windows, even to a top level - // window with an open sheet. - if (!aWindow || [aEvent type] == NSRightMouseDown) - return YES; - - id delegate = [aWindow delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) - return YES; - - nsIWidget *windowWidget = [(WindowDelegate *)delegate geckoWidget]; - if (!windowWidget) - return YES; - - NSWindow* topLevelWindow = nil; - - switch (windowWidget->WindowType()) { - case eWindowType_popup: - // If this is a context menu, it won't have a parent. So we'll always - // accept mouse move events on context menus even when none of our windows - // is active, which is the right thing to do. - // For panels, the parent window is the XUL window that owns the panel. - return WindowAcceptsEvent([aWindow parentWindow], aEvent, aView, aIsClickThrough); - - case eWindowType_toplevel: - case eWindowType_dialog: - if ([aWindow attachedSheet]) - return NO; - - topLevelWindow = aWindow; - break; - case eWindowType_sheet: { - nsIWidget* parentWidget = windowWidget->GetSheetWindowParent(); - if (!parentWidget) - return YES; - - topLevelWindow = (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW); - break; - } - - default: - return YES; - } - - if (!topLevelWindow || - ([topLevelWindow isMainWindow] && !aIsClickThrough) || - [aEvent type] == NSOtherMouseDown || - (([aEvent modifierFlags] & NSCommandKeyMask) != 0 && - [aEvent type] != NSMouseMoved)) - return YES; - - // If we're here then we're dealing with a left click or mouse move on an - // inactive window or something similar. Ask Gecko what to do. - return [aView inactiveWindowAcceptsMouseEvent:aEvent]; -} - -#pragma mark - - -@interface NSView (MethodSwizzling) -- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow; -@end - -@implementation NSView (MethodSwizzling) - -// All top-level browser windows belong to the ToolbarWindow class and have -// NSTexturedBackgroundWindowMask turned on in their "style" (see particularly -// [ToolbarWindow initWithContentRect:...] in nsCocoaWindow.mm). This style -// normally means the window "may be moved by clicking and dragging anywhere -// in the window background", but we've suppressed this by giving the -// ChildView class a mouseDownCanMoveWindow method that always returns NO. -// Normally a ToolbarWindow's contentView (not a ChildView) returns YES when -// NSTexturedBackgroundWindowMask is turned on. But normally this makes no -// difference. However, under some (probably very unusual) circumstances -// (and only on Leopard) it *does* make a difference -- for example it -// triggers bmo bugs 431902 and 476393. So here we make sure that a -// ToolbarWindow's contentView always returns NO from the -// mouseDownCanMoveWindow method. -- (BOOL)nsChildView_NSView_mouseDownCanMoveWindow -{ - NSWindow *ourWindow = [self window]; - NSView *contentView = [ourWindow contentView]; - if ([ourWindow isKindOfClass:[ToolbarWindow class]] && (self == contentView)) - return [ourWindow isMovableByWindowBackground]; - return [self nsChildView_NSView_mouseDownCanMoveWindow]; -} - -@end diff --git a/widget/cocoa/nsClipboard.h b/widget/cocoa/nsClipboard.h deleted file mode 100644 index 45871efe10..0000000000 --- a/widget/cocoa/nsClipboard.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsClipboard_h_ -#define nsClipboard_h_ - -#include "nsIClipboard.h" -#include "nsXPIDLString.h" -#include "mozilla/StaticPtr.h" - -#import - -class nsITransferable; - -class nsClipboard : public nsIClipboard -{ - -public: - nsClipboard(); - - NS_DECL_ISUPPORTS - NS_DECL_NSICLIPBOARD - - // On macOS, cache the transferable of the current selection (chrome/content) - // in the parent process. This is needed for the services menu which - // requires synchronous access to the current selection. - static mozilla::StaticRefPtr sSelectionCache; - - // Helper methods, used also by nsDragService - static NSDictionary* PasteboardDictFromTransferable(nsITransferable *aTransferable); - static bool IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType); - static NSString* WrapHtmlForSystemPasteboard(NSString* aString); - static nsresult TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *pboard); - -protected: - - // impelement the native clipboard behavior - NS_IMETHOD SetNativeClipboardData(int32_t aWhichClipboard); - NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable, int32_t aWhichClipboard); - void ClearSelectionCache(); - void SetSelectionCache(nsITransferable* aTransferable); - -private: - virtual ~nsClipboard(); - int32_t mCachedClipboard; - int32_t mChangeCount; // Set to the native change count after any modification of the clipboard. - - bool mIgnoreEmptyNotification; - nsCOMPtr mClipboardOwner; - nsCOMPtr mTransferable; -}; - -#endif // nsClipboard_h_ diff --git a/widget/cocoa/nsClipboard.mm b/widget/cocoa/nsClipboard.mm deleted file mode 100644 index 4146f17851..0000000000 --- a/widget/cocoa/nsClipboard.mm +++ /dev/null @@ -1,775 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/Unused.h" - -#include "gfxPlatform.h" -#include "nsArrayUtils.h" -#include "nsCOMPtr.h" -#include "nsClipboard.h" -#include "nsString.h" -#include "nsISupportsPrimitives.h" -#include "nsXPIDLString.h" -#include "nsPrimitiveHelpers.h" -#include "nsMemory.h" -#include "nsIFile.h" -#include "nsStringStream.h" -#include "nsDragService.h" -#include "nsEscape.h" -#include "nsPrintfCString.h" -#include "nsObjCExceptions.h" -#include "imgIContainer.h" -#include "nsCocoaUtils.h" - -using mozilla::gfx::DataSourceSurface; -using mozilla::gfx::SourceSurface; -using mozilla::LogLevel; - -// Screenshots use the (undocumented) png pasteboard type. -#define IMAGE_PASTEBOARD_TYPES NSTIFFPboardType, @"Apple PNG pasteboard type", nil - -extern PRLogModuleInfo* sCocoaLog; - -extern void EnsureLogInitialized(); - -mozilla::StaticRefPtr nsClipboard::sSelectionCache; - -nsClipboard::nsClipboard() - : mCachedClipboard(-1) - , mChangeCount(0) - , mIgnoreEmptyNotification(false) -{ - EnsureLogInitialized(); -} - -nsClipboard::~nsClipboard() -{ - EmptyClipboard(kGlobalClipboard); - EmptyClipboard(kFindClipboard); - ClearSelectionCache(); -} - -NS_IMPL_ISUPPORTS(nsClipboard, nsIClipboard) - -// We separate this into its own function because after an @try, all local -// variables within that function get marked as volatile, and our C++ type -// system doesn't like volatile things. -static NSData* -GetDataFromPasteboard(NSPasteboard* aPasteboard, NSString* aType) -{ - NSData *data = nil; - @try { - data = [aPasteboard dataForType:aType]; - } @catch (NSException* e) { - NS_WARNING(nsPrintfCString("Exception raised while getting data from the pasteboard: \"%s - %s\"", - [[e name] UTF8String], [[e reason] UTF8String]).get()); - mozilla::Unused << e; - } - return data; -} - -void -nsClipboard::SetSelectionCache(nsITransferable *aTransferable) -{ - sSelectionCache = aTransferable; -} - -void -nsClipboard::ClearSelectionCache() -{ - sSelectionCache = nullptr; -} - -NS_IMETHODIMP -nsClipboard::SetNativeClipboardData(int32_t aWhichClipboard) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !mTransferable) - return NS_ERROR_FAILURE; - - mIgnoreEmptyNotification = true; - - NSDictionary* pasteboardOutputDict = PasteboardDictFromTransferable(mTransferable); - if (!pasteboardOutputDict) - return NS_ERROR_FAILURE; - - unsigned int outputCount = [pasteboardOutputDict count]; - NSArray* outputKeys = [pasteboardOutputDict allKeys]; - NSPasteboard* cocoaPasteboard; - if (aWhichClipboard == kFindClipboard) { - cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard]; - [cocoaPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; - } else { - // Write everything else out to the general pasteboard. - cocoaPasteboard = [NSPasteboard generalPasteboard]; - [cocoaPasteboard declareTypes:outputKeys owner:nil]; - } - - for (unsigned int i = 0; i < outputCount; i++) { - NSString* currentKey = [outputKeys objectAtIndex:i]; - id currentValue = [pasteboardOutputDict valueForKey:currentKey]; - if (aWhichClipboard == kFindClipboard) { - if (currentKey == NSStringPboardType) - [cocoaPasteboard setString:currentValue forType:currentKey]; - } else { - if (currentKey == NSStringPboardType || - currentKey == kCorePboardType_url || - currentKey == kCorePboardType_urld || - currentKey == kCorePboardType_urln) { - [cocoaPasteboard setString:currentValue forType:currentKey]; - } else if (currentKey == NSHTMLPboardType) { - [cocoaPasteboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue)) - forType:currentKey]; - } else { - [cocoaPasteboard setData:currentValue forType:currentKey]; - } - } - } - - mCachedClipboard = aWhichClipboard; - mChangeCount = [cocoaPasteboard changeCount]; - - mIgnoreEmptyNotification = false; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult -nsClipboard::TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *cocoaPasteboard) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // get flavor list that includes all acceptable flavors (including ones obtained through conversion) - nsCOMPtr flavorList; - nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; - - uint32_t flavorCount; - flavorList->GetLength(&flavorCount); - - for (uint32_t i = 0; i < flavorCount; i++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); // i has a flavr - - // printf("looking for clipboard data of type %s\n", flavorStr.get()); - - NSString *pboardType = nil; - if (nsClipboard::IsStringType(flavorStr, &pboardType)) { - NSString* pString = [cocoaPasteboard stringForType:pboardType]; - if (!pString) - continue; - - NSData* stringData; - if ([pboardType isEqualToString:NSRTFPboardType]) { - stringData = [pString dataUsingEncoding:NSASCIIStringEncoding]; - } else { - stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding]; - } - unsigned int dataLength = [stringData length]; - void* clipboardDataPtr = malloc(dataLength); - if (!clipboardDataPtr) - return NS_ERROR_OUT_OF_MEMORY; - [stringData getBytes:clipboardDataPtr]; - - // The DOM only wants LF, so convert from MacOS line endings to DOM line endings. - int32_t signedDataLength = dataLength; - nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength); - dataLength = signedDataLength; - - // skip BOM (Byte Order Mark to distinguish little or big endian) - char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr; - if ((dataLength > 2) && - ((clipboardDataPtrNoBOM[0] == 0xFEFF) || - (clipboardDataPtrNoBOM[0] == 0xFFFE))) { - dataLength -= sizeof(char16_t); - clipboardDataPtrNoBOM += 1; - } - - nsCOMPtr genericDataWrapper; - nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength, - getter_AddRefs(genericDataWrapper)); - aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength); - free(clipboardDataPtr); - break; - } - else if (flavorStr.EqualsLiteral(kCustomTypesMime)) { - NSString* type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]]; - if (!type) { - continue; - } - - NSData* pasteboardData = GetDataFromPasteboard(cocoaPasteboard, type); - if (!pasteboardData) { - continue; - } - - unsigned int dataLength = [pasteboardData length]; - void* clipboardDataPtr = malloc(dataLength); - if (!clipboardDataPtr) { - return NS_ERROR_OUT_OF_MEMORY; - } - [pasteboardData getBytes:clipboardDataPtr]; - - nsCOMPtr genericDataWrapper; - nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength, - getter_AddRefs(genericDataWrapper)); - - aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength); - free(clipboardDataPtr); - } - else if (flavorStr.EqualsLiteral(kJPEGImageMime) || - flavorStr.EqualsLiteral(kJPGImageMime) || - flavorStr.EqualsLiteral(kPNGImageMime) || - flavorStr.EqualsLiteral(kGIFImageMime)) { - // Figure out if there's data on the pasteboard we can grab (sanity check) - NSString *type = [cocoaPasteboard availableTypeFromArray:[NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]]; - if (!type) - continue; - - // Read data off the clipboard - NSData *pasteboardData = GetDataFromPasteboard(cocoaPasteboard, type); - if (!pasteboardData) - continue; - - // Figure out what type we're converting to - CFStringRef outputType = NULL; - if (flavorStr.EqualsLiteral(kJPEGImageMime) || - flavorStr.EqualsLiteral(kJPGImageMime)) - outputType = CFSTR("public.jpeg"); - else if (flavorStr.EqualsLiteral(kPNGImageMime)) - outputType = CFSTR("public.png"); - else if (flavorStr.EqualsLiteral(kGIFImageMime)) - outputType = CFSTR("com.compuserve.gif"); - else - continue; - - // Use ImageIO to interpret the data on the clipboard and transcode. - // Note that ImageIO, like all CF APIs, allows NULLs to propagate freely - // and safely in most cases (like ObjC). A notable exception is CFRelease. - NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: - (NSNumber*)kCFBooleanTrue, kCGImageSourceShouldAllowFloat, - (type == NSTIFFPboardType ? @"public.tiff" : @"public.png"), - kCGImageSourceTypeIdentifierHint, nil]; - - CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)pasteboardData, - (CFDictionaryRef)options); - NSMutableData *encodedData = [NSMutableData data]; - CGImageDestinationRef dest = CGImageDestinationCreateWithData((CFMutableDataRef)encodedData, - outputType, - 1, NULL); - CGImageDestinationAddImageFromSource(dest, source, 0, NULL); - bool successfullyConverted = CGImageDestinationFinalize(dest); - - if (successfullyConverted) { - // Put the converted data in a form Gecko can understand - nsCOMPtr byteStream; - NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)[encodedData bytes], - [encodedData length], NS_ASSIGNMENT_COPY); - - aTransferable->SetTransferData(flavorStr, byteStream, sizeof(nsIInputStream*)); - } - - if (dest) - CFRelease(dest); - if (source) - CFRelease(source); - - if (successfullyConverted) - break; - else - continue; - } - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable, int32_t aWhichClipboard) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !aTransferable) - return NS_ERROR_FAILURE; - - NSPasteboard* cocoaPasteboard; - if (aWhichClipboard == kFindClipboard) { - cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard]; - } else { - cocoaPasteboard = [NSPasteboard generalPasteboard]; - } - if (!cocoaPasteboard) - return NS_ERROR_FAILURE; - - // get flavor list that includes all acceptable flavors (including ones obtained through conversion) - nsCOMPtr flavorList; - nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; - - uint32_t flavorCount; - flavorList->GetLength(&flavorCount); - - // If we were the last ones to put something on the pasteboard, then just use the cached - // transferable. Otherwise clear it because it isn't relevant any more. - if (mCachedClipboard == aWhichClipboard && - mChangeCount == [cocoaPasteboard changeCount]) { - if (mTransferable) { - for (uint32_t i = 0; i < flavorCount; i++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - - nsCOMPtr dataSupports; - uint32_t dataSize = 0; - rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize); - if (NS_SUCCEEDED(rv)) { - aTransferable->SetTransferData(flavorStr, dataSupports, dataSize); - return NS_OK; // maybe try to fill in more types? Is there a point? - } - } - } - } else { - EmptyClipboard(aWhichClipboard); - } - - // at this point we can't satisfy the request from cache data so let's look - // for things other people put on the system clipboard - - return nsClipboard::TransferableFromPasteboard(aTransferable, cocoaPasteboard); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// returns true if we have *any* of the passed in flavors available for pasting -NS_IMETHODIMP -nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, uint32_t aLength, - int32_t aWhichClipboard, bool* outResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *outResult = false; - - if ((aWhichClipboard != kGlobalClipboard) || !aFlavorList) - return NS_OK; - - // first see if we have data for this in our cached transferable - if (mTransferable) { - nsCOMPtr transferableFlavorList; - nsresult rv = mTransferable->FlavorsTransferableCanImport(getter_AddRefs(transferableFlavorList)); - if (NS_SUCCEEDED(rv)) { - uint32_t transferableFlavorCount; - transferableFlavorList->GetLength(&transferableFlavorCount); - for (uint32_t j = 0; j < transferableFlavorCount; j++) { - nsCOMPtr currentTransferableFlavor = - do_QueryElementAt(transferableFlavorList, j); - if (!currentTransferableFlavor) - continue; - nsXPIDLCString transferableFlavorStr; - currentTransferableFlavor->ToString(getter_Copies(transferableFlavorStr)); - - for (uint32_t k = 0; k < aLength; k++) { - if (transferableFlavorStr.Equals(aFlavorList[k])) { - *outResult = true; - return NS_OK; - } - } - } - } - } - - NSPasteboard* generalPBoard = [NSPasteboard generalPasteboard]; - - for (uint32_t i = 0; i < aLength; i++) { - nsDependentCString mimeType(aFlavorList[i]); - NSString *pboardType = nil; - - if (nsClipboard::IsStringType(mimeType, &pboardType)) { - NSString* availableType = [generalPBoard availableTypeFromArray:[NSArray arrayWithObject:pboardType]]; - if (availableType && [availableType isEqualToString:pboardType]) { - *outResult = true; - break; - } - } else if (!strcmp(aFlavorList[i], kCustomTypesMime)) { - NSString* availableType = [generalPBoard availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]]; - if (availableType) { - *outResult = true; - break; - } - } else if (!strcmp(aFlavorList[i], kJPEGImageMime) || - !strcmp(aFlavorList[i], kJPGImageMime) || - !strcmp(aFlavorList[i], kPNGImageMime) || - !strcmp(aFlavorList[i], kGIFImageMime)) { - NSString* availableType = [generalPBoard availableTypeFromArray: - [NSArray arrayWithObjects:IMAGE_PASTEBOARD_TYPES]]; - if (availableType) { - *outResult = true; - break; - } - } - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsClipboard::SupportsFindClipboard(bool *_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - *_retval = true; - return NS_OK; -} - -// This function converts anything that other applications might understand into the system format -// and puts it into a dictionary which it returns. -// static -NSDictionary* -nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!aTransferable) - return nil; - - NSMutableDictionary* pasteboardOutputDict = [NSMutableDictionary dictionary]; - - nsCOMPtr flavorList; - nsresult rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList)); - if (NS_FAILED(rv)) - return nil; - - uint32_t flavorCount; - flavorList->GetLength(&flavorCount); - for (uint32_t i = 0; i < flavorCount; i++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("writing out clipboard data of type %s (%d)\n", flavorStr.get(), i)); - - NSString *pboardType = nil; - - if (nsClipboard::IsStringType(flavorStr, &pboardType)) { - void* data = nullptr; - uint32_t dataSize = 0; - nsCOMPtr genericDataWrapper; - rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize); - nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize); - - NSString* nativeString; - if (data) - nativeString = [NSString stringWithCharacters:(const unichar*)data length:(dataSize / sizeof(char16_t))]; - else - nativeString = [NSString string]; - - // be nice to Carbon apps, normalize the receiver's contents using Form C. - nativeString = [nativeString precomposedStringWithCanonicalMapping]; - - [pasteboardOutputDict setObject:nativeString forKey:pboardType]; - - free(data); - } - else if (flavorStr.EqualsLiteral(kCustomTypesMime)) { - void* data = nullptr; - uint32_t dataSize = 0; - nsCOMPtr genericDataWrapper; - rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize); - nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize); - - if (data) { - NSData* nativeData = [NSData dataWithBytes:data length:dataSize]; - - [pasteboardOutputDict setObject:nativeData forKey:kCustomTypesPboardType]; - free(data); - } - } - else if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) || - flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime) || - flavorStr.EqualsLiteral(kNativeImageMime)) { - uint32_t dataSize = 0; - nsCOMPtr transferSupports; - aTransferable->GetTransferData(flavorStr, getter_AddRefs(transferSupports), &dataSize); - nsCOMPtr ptrPrimitive(do_QueryInterface(transferSupports)); - if (!ptrPrimitive) - continue; - - nsCOMPtr primitiveData; - ptrPrimitive->GetData(getter_AddRefs(primitiveData)); - - nsCOMPtr image(do_QueryInterface(primitiveData)); - if (!image) { - NS_WARNING("Image isn't an imgIContainer in transferable"); - continue; - } - - RefPtr surface = - image->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - if (!surface) { - continue; - } - CGImageRef imageRef = NULL; - rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef); - if (NS_FAILED(rv) || !imageRef) { - continue; - } - - // Convert the CGImageRef to TIFF data. - CFMutableDataRef tiffData = CFDataCreateMutable(kCFAllocatorDefault, 0); - CGImageDestinationRef destRef = CGImageDestinationCreateWithData(tiffData, - CFSTR("public.tiff"), - 1, - NULL); - CGImageDestinationAddImage(destRef, imageRef, NULL); - bool successfullyConverted = CGImageDestinationFinalize(destRef); - - CGImageRelease(imageRef); - if (destRef) - CFRelease(destRef); - - if (!successfullyConverted) { - if (tiffData) - CFRelease(tiffData); - continue; - } - - [pasteboardOutputDict setObject:(NSMutableData*)tiffData forKey:NSTIFFPboardType]; - if (tiffData) - CFRelease(tiffData); - } - else if (flavorStr.EqualsLiteral(kFileMime)) { - uint32_t len = 0; - nsCOMPtr genericFile; - rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericFile), &len); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr file(do_QueryInterface(genericFile)); - if (!file) { - nsCOMPtr ptr(do_QueryInterface(genericFile)); - - if (ptr) { - ptr->GetData(getter_AddRefs(genericFile)); - file = do_QueryInterface(genericFile); - } - } - - if (!file) { - continue; - } - - nsAutoString fileURI; - rv = file->GetPath(fileURI); - if (NS_FAILED(rv)) { - continue; - } - - NSString* str = nsCocoaUtils::ToNSString(fileURI); - NSArray* fileList = [NSArray arrayWithObjects:str, nil]; - [pasteboardOutputDict setObject:fileList forKey:NSFilenamesPboardType]; - } - else if (flavorStr.EqualsLiteral(kFilePromiseMime)) { - [pasteboardOutputDict setObject:[NSArray arrayWithObject:@""] forKey:NSFilesPromisePboardType]; - } - else if (flavorStr.EqualsLiteral(kURLMime)) { - uint32_t len = 0; - nsCOMPtr genericURL; - rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(genericURL), &len); - nsCOMPtr urlObject(do_QueryInterface(genericURL)); - - nsAutoString url; - urlObject->GetData(url); - - // A newline embedded in the URL means that the form is actually URL + title. - int32_t newlinePos = url.FindChar(char16_t('\n')); - if (newlinePos >= 0) { - url.Truncate(newlinePos); - - nsAutoString urlTitle; - urlObject->GetData(urlTitle); - urlTitle.Mid(urlTitle, newlinePos + 1, len - (newlinePos + 1)); - - NSString *nativeTitle = [[NSString alloc] initWithCharacters:reinterpret_cast(urlTitle.get()) - length:urlTitle.Length()]; - // be nice to Carbon apps, normalize the receiver's contents using Form C. - [pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urln]; - // Also put the title out as 'urld', since some recipients will look for that. - [pasteboardOutputDict setObject:[nativeTitle precomposedStringWithCanonicalMapping] forKey:kCorePboardType_urld]; - [nativeTitle release]; - } - - // The Finder doesn't like getting random binary data aka - // Unicode, so change it into an escaped URL containing only - // ASCII. - nsAutoCString utf8Data = NS_ConvertUTF16toUTF8(url.get(), url.Length()); - nsAutoCString escData; - NS_EscapeURL(utf8Data.get(), utf8Data.Length(), esc_OnlyNonASCII|esc_AlwaysCopy, escData); - - // printf("Escaped url is %s, length %d\n", escData.get(), escData.Length()); - - NSString *nativeURL = [NSString stringWithUTF8String:escData.get()]; - [pasteboardOutputDict setObject:nativeURL forKey:kCorePboardType_url]; - } - // If it wasn't a type that we recognize as exportable we don't put it on the system - // clipboard. We'll just access it from our cached transferable when we need it. - } - - return pasteboardOutputDict; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -bool nsClipboard::IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType) -{ - if (aMIMEType.EqualsLiteral(kUnicodeMime)) { - *aPasteboardType = NSStringPboardType; - return true; - } else if (aMIMEType.EqualsLiteral(kRTFMime)) { - *aPasteboardType = NSRTFPboardType; - return true; - } else if (aMIMEType.EqualsLiteral(kHTMLMime)) { - *aPasteboardType = NSHTMLPboardType; - return true; - } else { - return false; - } -} - -NSString* nsClipboard::WrapHtmlForSystemPasteboard(NSString* aString) -{ - NSString* wrapped = - [NSString stringWithFormat: - @"" - "" - "" - "" - "" - "%@" - "" - "", aString]; - return wrapped; -} - -/** - * Sets the transferable object - * - */ -NS_IMETHODIMP -nsClipboard::SetData(nsITransferable* aTransferable, nsIClipboardOwner* anOwner, - int32_t aWhichClipboard) -{ - NS_ASSERTION (aTransferable, "clipboard given a null transferable"); - - if (aWhichClipboard == kSelectionCache) { - if (aTransferable) { - SetSelectionCache(aTransferable); - return NS_OK; - } - return NS_ERROR_FAILURE; - } - - if (aTransferable == mTransferable && anOwner == mClipboardOwner) { - return NS_OK; - } - bool selectClipPresent; - SupportsSelectionClipboard(&selectClipPresent); - bool findClipPresent; - SupportsFindClipboard(&findClipPresent); - if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) { - return NS_ERROR_FAILURE; - } - - EmptyClipboard(aWhichClipboard); - - mClipboardOwner = anOwner; - mTransferable = aTransferable; - - nsresult rv = NS_ERROR_FAILURE; - if (mTransferable) { - rv = SetNativeClipboardData(aWhichClipboard); - } - - return rv; -} - -/** - * Gets the transferable object - * - */ -NS_IMETHODIMP -nsClipboard::GetData(nsITransferable* aTransferable, int32_t aWhichClipboard) -{ - NS_ASSERTION (aTransferable, "clipboard given a null transferable"); - - bool selectClipPresent; - SupportsSelectionClipboard(&selectClipPresent); - bool findClipPresent; - SupportsFindClipboard(&findClipPresent); - if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) - return NS_ERROR_FAILURE; - - if (aTransferable) { - return GetNativeClipboardData(aTransferable, aWhichClipboard); - } - - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -nsClipboard::EmptyClipboard(int32_t aWhichClipboard) -{ - if (aWhichClipboard == kSelectionCache) { - ClearSelectionCache(); - return NS_OK; - } - - bool selectClipPresent; - SupportsSelectionClipboard(&selectClipPresent); - bool findClipPresent; - SupportsFindClipboard(&findClipPresent); - if (!selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard) { - return NS_ERROR_FAILURE; - } - - if (mIgnoreEmptyNotification) { - return NS_OK; - } - - if (mClipboardOwner) { - mClipboardOwner->LosingOwnership(mTransferable); - mClipboardOwner = nullptr; - } - - mTransferable = nullptr; - return NS_OK; -} - -NS_IMETHODIMP -nsClipboard::SupportsSelectionClipboard(bool* _retval) -{ - *_retval = false; // we don't support the selection clipboard by default. - return NS_OK; -} diff --git a/widget/cocoa/nsCocoaDebugUtils.h b/widget/cocoa/nsCocoaDebugUtils.h deleted file mode 100644 index 814f060878..0000000000 --- a/widget/cocoa/nsCocoaDebugUtils.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsCocoaDebugUtils_h_ -#define nsCocoaDebugUtils_h_ - -#include - -// Definitions and declarations of stuff used by us from the CoreSymbolication -// framework. This is an undocumented, private framework available on OS X -// 10.6 and up. It's used by Apple utilities like dtrace, atos, ReportCrash -// and crashreporterd. - -typedef struct _CSTypeRef { - unsigned long type; - void* contents; -} CSTypeRef; - -typedef CSTypeRef CSSymbolicatorRef; -typedef CSTypeRef CSSymbolOwnerRef; -typedef CSTypeRef CSSymbolRef; -typedef CSTypeRef CSSourceInfoRef; - -typedef struct _CSRange { - unsigned long long location; - unsigned long long length; -} CSRange; - -typedef unsigned long long CSArchitecture; - -#define kCSNow LONG_MAX - -extern "C" { - -CSSymbolicatorRef -CSSymbolicatorCreateWithPid(pid_t pid); - -CSSymbolicatorRef -CSSymbolicatorCreateWithPidFlagsAndNotification(pid_t pid, - uint32_t flags, - uint32_t notification); - -CSArchitecture -CSSymbolicatorGetArchitecture(CSSymbolicatorRef symbolicator); - -CSSymbolOwnerRef -CSSymbolicatorGetSymbolOwnerWithAddressAtTime(CSSymbolicatorRef symbolicator, - unsigned long long address, - long time); - -const char* -CSSymbolOwnerGetName(CSSymbolOwnerRef owner); - -unsigned long long -CSSymbolOwnerGetBaseAddress(CSSymbolOwnerRef owner); - -CSSymbolRef -CSSymbolOwnerGetSymbolWithAddress(CSSymbolOwnerRef owner, - unsigned long long address); - -CSSourceInfoRef -CSSymbolOwnerGetSourceInfoWithAddress(CSSymbolOwnerRef owner, - unsigned long long address); - -const char* -CSSymbolGetName(CSSymbolRef symbol); - -CSRange -CSSymbolGetRange(CSSymbolRef symbol); - -const char* -CSSourceInfoGetFilename(CSSourceInfoRef info); - -uint32_t -CSSourceInfoGetLineNumber(CSSourceInfoRef info); - -CSTypeRef -CSRetain(CSTypeRef); - -void -CSRelease(CSTypeRef); - -bool -CSIsNull(CSTypeRef); - -void -CSShow(CSTypeRef); - -const char* -CSArchitectureGetFamilyName(CSArchitecture); - -} // extern "C" - -class nsCocoaDebugUtils -{ -public: - // Like NSLog() but records more information (for example the full path to - // the executable and the "thread name"). Like NSLog(), writes to both - // stdout and the system log. - static void DebugLog(const char* aFormat, ...); - - // Logs a stack trace of the current point of execution, to both stdout and - // the system log. - static void PrintStackTrace(); - - // Returns the name of the module that "owns" aAddress. This must be - // free()ed by the caller. - static char* GetOwnerName(void* aAddress); - - // Returns a symbolicated representation of aAddress. This must be - // free()ed by the caller. - static char* GetAddressString(void* aAddress); - -private: - static void DebugLogInt(bool aDecorate, const char* aFormat, ...); - static void DebugLogV(bool aDecorate, CFStringRef aFormat, va_list aArgs); - - static void PrintAddress(void* aAddress); - - // The values returned by GetOwnerNameInt() and GetAddressStringInt() must - // be free()ed by the caller. - static char* GetOwnerNameInt(void* aAddress, - CSTypeRef aOwner = sInitializer); - static char* GetAddressStringInt(void* aAddress, - CSTypeRef aOwner = sInitializer); - - static CSSymbolicatorRef GetSymbolicatorRef(); - static void ReleaseSymbolicator(); - - static CSTypeRef sInitializer; - static CSSymbolicatorRef sSymbolicator; -}; - -#endif // nsCocoaDebugUtils_h_ diff --git a/widget/cocoa/nsCocoaDebugUtils.mm b/widget/cocoa/nsCocoaDebugUtils.mm deleted file mode 100644 index 35896dc401..0000000000 --- a/widget/cocoa/nsCocoaDebugUtils.mm +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsCocoaDebugUtils.h" - -#include -#include -#include -#include -#include -#include - -static char gProcPath[PROC_PIDPATHINFO_MAXSIZE] = {0}; -static char gBundleID[MAXPATHLEN] = {0}; - -static void MaybeGetPathAndID() -{ - if (!gProcPath[0]) { - proc_pidpath(getpid(), gProcPath, sizeof(gProcPath)); - } - if (!gBundleID[0]) { - // Apple's CFLog() uses "com.apple.console" (in its call to asl_open()) if - // it can't find the bundle id. - CFStringRef bundleID = NULL; - CFBundleRef mainBundle = CFBundleGetMainBundle(); - if (mainBundle) { - bundleID = CFBundleGetIdentifier(mainBundle); - } - if (!bundleID) { - strcpy(gBundleID, "com.apple.console"); - } else { - CFStringGetCString(bundleID, gBundleID, sizeof(gBundleID), - kCFStringEncodingUTF8); - } - } -} - -static void GetThreadName(char* aName, size_t aSize) -{ - pthread_getname_np(pthread_self(), aName, aSize); -} - -void -nsCocoaDebugUtils::DebugLog(const char* aFormat, ...) -{ - va_list args; - va_start(args, aFormat); - CFStringRef formatCFSTR = - CFStringCreateWithCString(kCFAllocatorDefault, aFormat, - kCFStringEncodingUTF8); - DebugLogV(true, formatCFSTR, args); - CFRelease(formatCFSTR); - va_end(args); -} - -void -nsCocoaDebugUtils::DebugLogInt(bool aDecorate, const char* aFormat, ...) -{ - va_list args; - va_start(args, aFormat); - CFStringRef formatCFSTR = - CFStringCreateWithCString(kCFAllocatorDefault, aFormat, - kCFStringEncodingUTF8); - DebugLogV(aDecorate, formatCFSTR, args); - CFRelease(formatCFSTR); - va_end(args); -} - -void -nsCocoaDebugUtils::DebugLogV(bool aDecorate, CFStringRef aFormat, - va_list aArgs) -{ - MaybeGetPathAndID(); - - CFStringRef message = - CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, - aFormat, aArgs); - - int msgLength = - CFStringGetMaximumSizeForEncoding(CFStringGetLength(message), - kCFStringEncodingUTF8); - char* msgUTF8 = (char*) calloc(msgLength, 1); - CFStringGetCString(message, msgUTF8, msgLength, kCFStringEncodingUTF8); - CFRelease(message); - - int finishedLength = msgLength + PROC_PIDPATHINFO_MAXSIZE; - char* finished = (char*) calloc(finishedLength, 1); - const time_t currentTime = time(NULL); - char timestamp[30] = {0}; - ctime_r(¤tTime, timestamp); - if (aDecorate) { - char threadName[MAXPATHLEN] = {0}; - GetThreadName(threadName, sizeof(threadName)); - snprintf(finished, finishedLength, "(%s) %s[%u] %s[%p] %s\n", - timestamp, gProcPath, getpid(), threadName, pthread_self(), msgUTF8); - } else { - snprintf(finished, finishedLength, "%s\n", msgUTF8); - } - free(msgUTF8); - - fputs(finished, stdout); - - // Use the Apple System Log facility, as NSLog and CFLog do. - aslclient asl = asl_open(NULL, gBundleID, ASL_OPT_NO_DELAY); - aslmsg msg = asl_new(ASL_TYPE_MSG); - asl_set(msg, ASL_KEY_LEVEL, "4"); // kCFLogLevelWarning, used by NSLog() - asl_set(msg, ASL_KEY_MSG, finished); - asl_send(asl, msg); - asl_free(msg); - asl_close(asl); - - free(finished); -} - -CSTypeRef -nsCocoaDebugUtils::sInitializer = {0}; - -CSSymbolicatorRef -nsCocoaDebugUtils::sSymbolicator = {0}; - -#define STACK_MAX 256 - -void -nsCocoaDebugUtils::PrintStackTrace() -{ - void** addresses = (void**) calloc(STACK_MAX, sizeof(void*)); - if (!addresses) { - return; - } - - CSSymbolicatorRef symbolicator = GetSymbolicatorRef(); - if (CSIsNull(symbolicator)) { - free(addresses); - return; - } - - uint32_t count = backtrace(addresses, STACK_MAX); - for (uint32_t i = 0; i < count; ++i) { - PrintAddress(addresses[i]); - } - - ReleaseSymbolicator(); - free(addresses); -} - -void -nsCocoaDebugUtils::PrintAddress(void* aAddress) -{ - const char* ownerName = "unknown"; - const char* addressString = "unknown + 0"; - - char* allocatedOwnerName = nullptr; - char* allocatedAddressString = nullptr; - - CSSymbolOwnerRef owner = {0}; - CSSymbolicatorRef symbolicator = GetSymbolicatorRef(); - - if (!CSIsNull(symbolicator)) { - owner = - CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, - (unsigned long long) aAddress, - kCSNow); - } - if (!CSIsNull(owner)) { - ownerName = allocatedOwnerName = GetOwnerNameInt(aAddress, owner); - addressString = allocatedAddressString = GetAddressStringInt(aAddress, owner); - } - DebugLogInt(false, " (%s) %s", ownerName, addressString); - - free(allocatedOwnerName); - free(allocatedAddressString); - - ReleaseSymbolicator(); -} - -char* -nsCocoaDebugUtils::GetOwnerName(void* aAddress) -{ - return GetOwnerNameInt(aAddress); -} - -char* -nsCocoaDebugUtils::GetOwnerNameInt(void* aAddress, CSTypeRef aOwner) -{ - char* retval = (char*) calloc(MAXPATHLEN, 1); - - const char* ownerName = "unknown"; - - CSSymbolicatorRef symbolicator = GetSymbolicatorRef(); - CSTypeRef owner = aOwner; - - if (CSIsNull(owner) && !CSIsNull(symbolicator)) { - owner = - CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, - (unsigned long long) aAddress, - kCSNow); - } - - if (!CSIsNull(owner)) { - ownerName = CSSymbolOwnerGetName(owner); - } - - snprintf(retval, MAXPATHLEN, "%s", ownerName); - ReleaseSymbolicator(); - - return retval; -} - -char* -nsCocoaDebugUtils::GetAddressString(void* aAddress) -{ - return GetAddressStringInt(aAddress); -} - -char* -nsCocoaDebugUtils::GetAddressStringInt(void* aAddress, CSTypeRef aOwner) -{ - char* retval = (char*) calloc(MAXPATHLEN, 1); - - const char* addressName = "unknown"; - unsigned long long addressOffset = 0; - - CSSymbolicatorRef symbolicator = GetSymbolicatorRef(); - CSTypeRef owner = aOwner; - - if (CSIsNull(owner) && !CSIsNull(symbolicator)) { - owner = - CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, - (unsigned long long) aAddress, - kCSNow); - } - - if (!CSIsNull(owner)) { - CSSymbolRef symbol = - CSSymbolOwnerGetSymbolWithAddress(owner, - (unsigned long long) aAddress); - if (!CSIsNull(symbol)) { - addressName = CSSymbolGetName(symbol); - CSRange range = CSSymbolGetRange(symbol); - addressOffset = (unsigned long long) aAddress - range.location; - } else { - addressOffset = (unsigned long long) - aAddress - CSSymbolOwnerGetBaseAddress(owner); - } - } - - snprintf(retval, MAXPATHLEN, "%s + 0x%llx", - addressName, addressOffset); - ReleaseSymbolicator(); - - return retval; -} - -CSSymbolicatorRef -nsCocoaDebugUtils::GetSymbolicatorRef() -{ - if (CSIsNull(sSymbolicator)) { - // 0x40e0000 is the value returned by - // uint32_t CSSymbolicatorGetFlagsForNListOnlyData(void). We don't use - // this method directly because it doesn't exist on OS X 10.6. Unless - // we limit ourselves to NList data, it will take too long to get a - // stack trace where Dwarf debugging info is available (about 15 seconds - // with Firefox). This means we won't be able to get a CSSourceInfoRef, - // or line number information. Oh well. - sSymbolicator = - CSSymbolicatorCreateWithPidFlagsAndNotification(getpid(), - 0x40e0000, 0); - } - // Retaining just after creation prevents crashes when calling symbolicator - // code (for example from PrintStackTrace()) as Firefox is quitting. Not - // sure why. Doing this may mean that we leak sSymbolicator on quitting - // (if we ever created it). No particular harm in that, though. - return CSRetain(sSymbolicator); -} - -void -nsCocoaDebugUtils::ReleaseSymbolicator() -{ - if (!CSIsNull(sSymbolicator)) { - CSRelease(sSymbolicator); - } -} diff --git a/widget/cocoa/nsCocoaFeatures.h b/widget/cocoa/nsCocoaFeatures.h deleted file mode 100644 index a9cab95d56..0000000000 --- a/widget/cocoa/nsCocoaFeatures.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsCocoaFeatures_h_ -#define nsCocoaFeatures_h_ - -#include - -/// Note that this class assumes we support the platform we are running on. -/// For better or worse, if the version is unknown or less than what we -/// support, we set it to the minimum supported version. GetSystemVersion -/// is the only call that returns the unadjusted values. -class nsCocoaFeatures { -public: - static int32_t macOSVersion(); - static int32_t macOSVersionMajor(); - static int32_t macOSVersionMinor(); - static int32_t macOSVersionBugFix(); - static bool OnYosemiteOrLater(); - static bool OnElCapitanOrLater(); - static bool OnSierraOrLater(); - static bool OnHighSierraOrLater(); - static bool OnMojaveOrLater(); - static bool OnCatalinaOrLater(); - static bool OnBigSurOrLater(); - - static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0); - - // These are utilities that do not change or depend on the value of mOSXVersion - // and instead just encapsulate the encoding algorithm. Note that GetVersion - // actually adjusts to the lowest supported OS, so it will always return - // a "supported" version. GetSystemVersion does not make any modifications. - static void GetSystemVersion(int &aMajor, int &aMinor, int &aBugFix); - static int32_t GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix); - static int32_t ExtractMajorVersion(int32_t aVersion); - static int32_t ExtractMinorVersion(int32_t aVersion); - static int32_t ExtractBugFixVersion(int32_t aVersion); - -private: - static void InitializeVersionNumbers(); - - static int32_t mOSVersion; -}; -#endif // nsCocoaFeatures_h_ diff --git a/widget/cocoa/nsCocoaFeatures.mm b/widget/cocoa/nsCocoaFeatures.mm deleted file mode 100644 index e0fafb7d96..0000000000 --- a/widget/cocoa/nsCocoaFeatures.mm +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * 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/. */ - -// This file makes some assumptions about the versions of macOS. -// We are assuming that the major, minor and bugfix versions are each less than -// 256. -// There are MOZ_ASSERTs for that. - -// The formula for the version integer is (major << 16) + (minor << 8) + bugfix. - -#define MACOS_VERSION_MASK 0x00FFFFFF -#define MACOS_MAJOR_VERSION_MASK 0x00FFFFFF -#define MACOS_MINOR_VERSION_MASK 0x00FFFFFF -#define MACOS_BUGFIX_VERSION_MASK 0x00FFFFFF -#define MACOS_VERSION_10_0_HEX 0x000A0000 -#define MACOS_VERSION_10_7_HEX 0x000A0700 -#define MACOS_VERSION_10_8_HEX 0x000A0800 -#define MACOS_VERSION_10_9_HEX 0x000A0900 -#define MACOS_VERSION_10_10_HEX 0x000A0A00 -#define MACOS_VERSION_10_11_HEX 0x000A0B00 -#define MACOS_VERSION_10_12_HEX 0x000A0C00 -#define MACOS_VERSION_10_13_HEX 0x000A0D00 -#define MACOS_VERSION_10_14_HEX 0x000A0E00 -#define MACOS_VERSION_10_15_HEX 0x000A0F00 -#define MACOS_VERSION_10_16_HEX 0x000A1000 -#define MACOS_VERSION_11_0_HEX 0x000B0000 - -#include "nsCocoaFeatures.h" -#include "nsCocoaUtils.h" -#include "nsDebug.h" -#include "nsObjCExceptions.h" - -#import - -int32_t nsCocoaFeatures::mOSVersion = 0; - -// This should not be called with unchecked aMajor, which should be >= 10. -inline int32_t AssembleVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) -{ - MOZ_ASSERT(aMajor >= 10); - return (aMajor << 16) + (aMinor << 8) + aBugFix; -} - -int32_t nsCocoaFeatures::ExtractMajorVersion(int32_t aVersion) -{ - MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion); - return (aVersion & 0xFF0000) >> 16; -} - -int32_t nsCocoaFeatures::ExtractMinorVersion(int32_t aVersion) -{ - MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion); - return (aVersion & 0xFF00) >> 8; -} - -int32_t nsCocoaFeatures::ExtractBugFixVersion(int32_t aVersion) -{ - MOZ_ASSERT((aVersion & MACOS_VERSION_MASK) == aVersion); - return aVersion & 0xFF; -} - -static int intAtStringIndex(NSArray *array, int index) -{ - return [(NSString*)[array objectAtIndex:index] integerValue]; -} - -void nsCocoaFeatures::GetSystemVersion(int &major, int &minor, int &bugfix) -{ - major = minor = bugfix = 0; - - NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile: - @"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"]; - NSArray* versions = [versionString componentsSeparatedByString:@"."]; - NSUInteger count = [versions count]; - if (count > 0) { - major = intAtStringIndex(versions, 0); - if (count > 1) { - minor = intAtStringIndex(versions, 1); - if (count > 2) { - bugfix = intAtStringIndex(versions, 2); - } - } - } -} - -int32_t nsCocoaFeatures::GetVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) -{ - int32_t macOSVersion; - if (aMajor < 10) { - aMajor = 10; - NS_ERROR("Couldn't determine macOS version, assuming 10.7"); - macOSVersion = MACOS_VERSION_10_7_HEX; - } else if (aMajor == 10 && aMinor < 7) { - aMinor = 7; - NS_ERROR("macOS version too old, assuming 10.7"); - macOSVersion = MACOS_VERSION_10_7_HEX; - } else { - MOZ_ASSERT(aMajor >= 10); - MOZ_ASSERT(aMajor < 256); - MOZ_ASSERT(aMinor >= 0); - MOZ_ASSERT(aMinor < 256); - MOZ_ASSERT(aBugFix >= 0); - MOZ_ASSERT(aBugFix < 256); - macOSVersion = AssembleVersion(aMajor, aMinor, aBugFix); - } - MOZ_ASSERT(aMajor == ExtractMajorVersion(macOSVersion)); - MOZ_ASSERT(aMinor == ExtractMinorVersion(macOSVersion)); - MOZ_ASSERT(aBugFix == ExtractBugFixVersion(macOSVersion)); - return macOSVersion; -} - -/*static*/ void -nsCocoaFeatures::InitializeVersionNumbers() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Provide an autorelease pool to avoid leaking Cocoa objects, - // as this gets called before the main autorelease pool is in place. - nsAutoreleasePool localPool; - - int major, minor, bugfix; - GetSystemVersion(major, minor, bugfix); - mOSVersion = GetVersion(major, minor, bugfix); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -/* static */ int32_t -nsCocoaFeatures::macOSVersion() -{ - // Don't let this be called while we're first setting the value... - MOZ_ASSERT((mOSVersion & MACOS_VERSION_MASK) >= 0); - if (!mOSVersion) { - mOSVersion = -1; - InitializeVersionNumbers(); - } - return mOSVersion; -} - -/* static */ int32_t -nsCocoaFeatures::macOSVersionMajor() -{ - return ExtractMajorVersion(macOSVersion()); -} - -/* static */ int32_t -nsCocoaFeatures::macOSVersionMinor() -{ - return ExtractMinorVersion(macOSVersion()); -} - -/* static */ int32_t -nsCocoaFeatures::macOSVersionBugFix() -{ - return ExtractBugFixVersion(macOSVersion()); -} - -/* static */ bool -nsCocoaFeatures::OnYosemiteOrLater() -{ - return (macOSVersion() >= MACOS_VERSION_10_10_HEX); -} - -/* static */ bool -nsCocoaFeatures::OnElCapitanOrLater() -{ - return (macOSVersion() >= MACOS_VERSION_10_11_HEX); -} - -/* static */ bool -nsCocoaFeatures::OnSierraOrLater() -{ - return (macOSVersion() >= MACOS_VERSION_10_12_HEX); -} - -/* static */ bool -nsCocoaFeatures::OnHighSierraOrLater() -{ - return (macOSVersion() >= MACOS_VERSION_10_13_HEX); -} - -/* static */ bool -nsCocoaFeatures::OnMojaveOrLater() -{ - return (macOSVersion() >= MACOS_VERSION_10_14_HEX); -} - -/* static */ bool -nsCocoaFeatures::OnCatalinaOrLater() -{ - return (macOSVersion() >= MACOS_VERSION_10_15_HEX); -} - -/* static */ bool -nsCocoaFeatures::OnBigSurOrLater() -{ - // Account for the version being 10.16 (which occurs when the - // application is linked with an older SDK) or 11.0 on Big Sur. - return ((macOSVersion() >= MACOS_VERSION_10_16_HEX) || - (macOSVersion() >= MACOS_VERSION_11_0_HEX)); -} - -/* static */ bool -nsCocoaFeatures::IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix) -{ - return macOSVersion() >= GetVersion(aMajor, aMinor, aBugFix); -} diff --git a/widget/cocoa/nsCocoaUtils.h b/widget/cocoa/nsCocoaUtils.h deleted file mode 100644 index 139e76b4ad..0000000000 --- a/widget/cocoa/nsCocoaUtils.h +++ /dev/null @@ -1,389 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsCocoaUtils_h_ -#define nsCocoaUtils_h_ - -#import - -#include "nsRect.h" -#include "imgIContainer.h" -#include "npapi.h" -#include "nsTArray.h" -#include "Units.h" - -// This must be the last include: -#include "nsObjCExceptions.h" - -#include "mozilla/EventForwards.h" - -// Declare the backingScaleFactor method that we want to call -// on NSView/Window/Screen objects, if they recognize it. -@interface NSObject (BackingScaleFactorCategory) -- (CGFloat)backingScaleFactor; -@end - -#if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 -enum { - NSEventPhaseMayBegin = 0x1 << 5 -}; -#endif - -class nsIWidget; - -namespace mozilla { -namespace gfx { -class SourceSurface; -} // namespace gfx -} // namespace mozilla - -// Used to retain a Cocoa object for the remainder of a method's execution. -class nsAutoRetainCocoaObject { -public: -explicit nsAutoRetainCocoaObject(id anObject) -{ - mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]); -} -~nsAutoRetainCocoaObject() -{ - NS_OBJC_TRY_ABORT([mObject release]); -} -private: - id mObject; // [STRONG] -}; - -// Provide a local autorelease pool for the remainder of a method's execution. -class nsAutoreleasePool { -public: - nsAutoreleasePool() - { - mLocalPool = [[NSAutoreleasePool alloc] init]; - } - ~nsAutoreleasePool() - { - [mLocalPool release]; - } -private: - NSAutoreleasePool *mLocalPool; -}; - -@interface NSApplication (Undocumented) - -// Present in all versions of OS X from (at least) 10.2.8 through 10.5. -- (BOOL)_isRunningModal; -- (BOOL)_isRunningAppModal; - -// It's sometimes necessary to explicitly remove a window from the "window -// cache" in order to deactivate it. The "window cache" is an undocumented -// subsystem, all of whose methods are included in the NSWindowCache category -// of the NSApplication class (in header files generated using class-dump). -// Present in all versions of OS X from (at least) 10.2.8 through 10.5. -- (void)_removeWindowFromCache:(NSWindow *)aWindow; - -// Send an event to the current Cocoa app-modal session. Present in all -// versions of OS X from (at least) 10.2.8 through 10.5. -- (void)_modalSession:(NSModalSession)aSession sendEvent:(NSEvent *)theEvent; - -@end - -struct KeyBindingsCommand -{ - SEL selector; - id data; -}; - -@interface NativeKeyBindingsRecorder : NSResponder -{ -@private - nsTArray* mCommands; -} - -- (void)startRecording:(nsTArray&)aCommands; - -- (void)doCommandBySelector:(SEL)aSelector; - -- (void)insertText:(id)aString; - -@end // NativeKeyBindingsRecorder - -class nsCocoaUtils -{ - typedef mozilla::gfx::SourceSurface SourceSurface; - typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint; - typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect; - -public: - - // Get the backing scale factor from an object that supports this selector - // (NSView/Window/Screen, on 10.7 or later), returning 1.0 if not supported - static CGFloat - GetBackingScaleFactor(id aObject) - { - if (HiDPIEnabled() && - [aObject respondsToSelector:@selector(backingScaleFactor)]) { - return [aObject backingScaleFactor]; - } - return 1.0; - } - - // Conversions between Cocoa points and device pixels, given the backing - // scale factor from a view/window/screen. - static int32_t - CocoaPointsToDevPixels(CGFloat aPts, CGFloat aBackingScale) - { - return NSToIntRound(aPts * aBackingScale); - } - - static LayoutDeviceIntPoint - CocoaPointsToDevPixels(const NSPoint& aPt, CGFloat aBackingScale) - { - return LayoutDeviceIntPoint(NSToIntRound(aPt.x * aBackingScale), - NSToIntRound(aPt.y * aBackingScale)); - } - - static LayoutDeviceIntPoint - CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt, CGFloat aBackingScale) - { - return LayoutDeviceIntPoint(NSToIntFloor(aPt.x * aBackingScale), - NSToIntFloor(aPt.y * aBackingScale)); - } - - static LayoutDeviceIntRect - CocoaPointsToDevPixels(const NSRect& aRect, CGFloat aBackingScale) - { - return LayoutDeviceIntRect(NSToIntRound(aRect.origin.x * aBackingScale), - NSToIntRound(aRect.origin.y * aBackingScale), - NSToIntRound(aRect.size.width * aBackingScale), - NSToIntRound(aRect.size.height * aBackingScale)); - } - - static CGFloat - DevPixelsToCocoaPoints(int32_t aPixels, CGFloat aBackingScale) - { - return (CGFloat)aPixels / aBackingScale; - } - - static NSPoint - DevPixelsToCocoaPoints(const mozilla::LayoutDeviceIntPoint& aPt, - CGFloat aBackingScale) - { - return NSMakePoint((CGFloat)aPt.x / aBackingScale, - (CGFloat)aPt.y / aBackingScale); - } - - // Implements an NSPoint equivalent of -[NSWindow convertRectFromScreen:]. - static NSPoint - ConvertPointFromScreen(NSWindow* aWindow, const NSPoint& aPt) - { - return [aWindow convertRectFromScreen:NSMakeRect(aPt.x, aPt.y, 0, 0)].origin; - } - - // Implements an NSPoint equivalent of -[NSWindow convertRectToScreen:]. - static NSPoint - ConvertPointToScreen(NSWindow* aWindow, const NSPoint& aPt) - { - return [aWindow convertRectToScreen:NSMakeRect(aPt.x, aPt.y, 0, 0)].origin; - } - - static NSRect - DevPixelsToCocoaPoints(const LayoutDeviceIntRect& aRect, - CGFloat aBackingScale) - { - return NSMakeRect((CGFloat)aRect.x / aBackingScale, - (CGFloat)aRect.y / aBackingScale, - (CGFloat)aRect.width / aBackingScale, - (CGFloat)aRect.height / aBackingScale); - } - - // Returns the given y coordinate, which must be in screen coordinates, - // flipped from Gecko to Cocoa or Cocoa to Gecko. - static float FlippedScreenY(float y); - - // The following functions come in "DevPix" variants that work with - // backing-store (device pixel) coordinates, as well as the original - // versions that expect coordinates in Cocoa points/CSS pixels. - // The difference becomes important in HiDPI display modes, where Cocoa - // points and backing-store pixels are no longer 1:1. - - // Gecko rects (nsRect) contain an origin (x,y) in a coordinate - // system with (0,0) in the top-left of the primary screen. Cocoa rects - // (NSRect) contain an origin (x,y) in a coordinate system with (0,0) - // in the bottom-left of the primary screen. Both nsRect and NSRect - // contain width/height info, with no difference in their use. - // This function does no scaling, so the Gecko coordinates are - // expected to be desktop pixels, which are equal to Cocoa points - // (by definition). - static NSRect GeckoRectToCocoaRect(const mozilla::DesktopIntRect &geckoRect); - - // Converts aGeckoRect in dev pixels to points in Cocoa coordinates - static NSRect - GeckoRectToCocoaRectDevPix(const mozilla::LayoutDeviceIntRect &aGeckoRect, - CGFloat aBackingScale); - - // See explanation for geckoRectToCocoaRect, guess what this does... - static mozilla::DesktopIntRect CocoaRectToGeckoRect(const NSRect &cocoaRect); - - static mozilla::LayoutDeviceIntRect CocoaRectToGeckoRectDevPix( - const NSRect& aCocoaRect, CGFloat aBackingScale); - - // Gives the location for the event in screen coordinates. Do not call this - // unless the window the event was originally targeted at is still alive! - // anEvent may be nil -- in that case the current mouse location is returned. - static NSPoint ScreenLocationForEvent(NSEvent* anEvent); - - // Determines if an event happened over a window, whether or not the event - // is for the window. Does not take window z-order into account. - static BOOL IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow); - - // Events are set up so that their coordinates refer to the window to which they - // were originally sent. If we reroute the event somewhere else, we'll have - // to get the window coordinates this way. Do not call this unless the window - // the event was originally targeted at is still alive! - static NSPoint EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow); - - // Compatibility wrappers for the -[NSEvent phase], -[NSEvent momentumPhase], - // -[NSEvent hasPreciseScrollingDeltas] and -[NSEvent scrollingDeltaX/Y] APIs - // that became availaible starting with the 10.7 SDK. - // All of these can be removed once we drop support for 10.6. - static NSEventPhase EventPhase(NSEvent* aEvent); - static NSEventPhase EventMomentumPhase(NSEvent* aEvent); - static BOOL IsMomentumScrollEvent(NSEvent* aEvent); - static BOOL HasPreciseScrollingDeltas(NSEvent* aEvent); - static void GetScrollingDeltas(NSEvent* aEvent, CGFloat* aOutDeltaX, CGFloat* aOutDeltaY); - static BOOL EventHasPhaseInformation(NSEvent* aEvent); - - // Hides the Menu bar and the Dock. Multiple hide/show requests can be nested. - static void HideOSChromeOnScreen(bool aShouldHide); - - static nsIWidget* GetHiddenWindowWidget(); - - static void PrepareForNativeAppModalDialog(); - static void CleanUpAfterNativeAppModalDialog(); - - // 3 utility functions to go from a frame of imgIContainer to CGImage and then to NSImage - // Convert imgIContainer -> CGImageRef, caller owns result - - /** Creates a CGImageRef from a frame contained in an imgIContainer. - Copies the pixel data from the indicated frame of the imgIContainer into a new CGImageRef. - The caller owns the CGImageRef. - @param aFrame the frame to convert - @param aResult the resulting CGImageRef - @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise - */ - static nsresult CreateCGImageFromSurface(SourceSurface* aSurface, - CGImageRef* aResult); - - /** Creates a Cocoa NSImage from a CGImageRef. - Copies the pixel data from the CGImageRef into a new NSImage. - The caller owns the NSImage. - @param aInputImage the image to convert - @param aResult the resulting NSImage - @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise - */ - static nsresult CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult); - - /** Creates a Cocoa NSImage from a frame of an imgIContainer. - Combines the two methods above. The caller owns the NSImage. - @param aImage the image to extract a frame from - @param aWhichFrame the frame to extract (see imgIContainer FRAME_*) - @param aResult the resulting NSImage - @param scaleFactor the desired scale factor of the NSImage (2 for a retina display) - @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise - */ - static nsresult CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor); - - /** - * Returns nsAString for aSrc. - */ - static void GetStringForNSString(const NSString *aSrc, nsAString& aDist); - - /** - * Makes NSString instance for aString. - */ - static NSString* ToNSString(const nsAString& aString); - - /** - * Returns NSRect for aGeckoRect. - * Just copies values between the two types; it does no coordinate-system - * conversion, so both rects must have the same coordinate origin/direction. - */ - static void GeckoRectToNSRect(const nsIntRect& aGeckoRect, - NSRect& aOutCocoaRect); - - /** - * Returns Gecko rect for aCocoaRect. - * Just copies values between the two types; it does no coordinate-system - * conversion, so both rects must have the same coordinate origin/direction. - */ - static void NSRectToGeckoRect(const NSRect& aCocoaRect, - nsIntRect& aOutGeckoRect); - - /** - * Makes NSEvent instance for aEventTytpe and aEvent. - */ - static NSEvent* MakeNewCocoaEventWithType(NSEventType aEventType, - NSEvent *aEvent); - - /** - * Initializes aNPCocoaEvent. - */ - static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent); - - /** - * Initializes WidgetInputEvent for aNativeEvent or aModifiers. - */ - static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent, - NSEvent* aNativeEvent); - - /** - * Converts the native modifiers from aNativeEvent into WidgetMouseEvent - * Modifiers. aNativeEvent can be null. - */ - static mozilla::Modifiers ModifiersForEvent(NSEvent* aNativeEvent); - - /** - * ConvertToCarbonModifier() returns carbon modifier flags for the cocoa - * modifier flags. - * NOTE: The result never includes right*Key. - */ - static UInt32 ConvertToCarbonModifier(NSUInteger aCocoaModifier); - - /** - * Whether to support HiDPI rendering. For testing purposes, to be removed - * once we're comfortable with the HiDPI behavior. - */ - static bool HiDPIEnabled(); - - /** - * Keys can optionally be bound by system or user key bindings to one or more - * commands based on selectors. This collects any such commands in the - * provided array. - */ - static void GetCommandsFromKeyEvent(NSEvent* aEvent, - nsTArray& aCommands); - - /** - * Converts the string name of a Gecko key (like "VK_HOME") to the - * corresponding Cocoa Unicode character. - */ - static uint32_t ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName); - - /** - * Converts a Gecko key code (like NS_VK_HOME) to the corresponding Cocoa - * Unicode character. - */ - static uint32_t ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode); - - /** - * Convert string with font attribute to NSMutableAttributedString - */ - static NSMutableAttributedString* GetNSMutableAttributedString( - const nsAString& aText, - const nsTArray& aFontRanges, - const bool aIsVertical, - const CGFloat aBackingScaleFactor); -}; - -#endif // nsCocoaUtils_h_ diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm deleted file mode 100644 index 3138245aa7..0000000000 --- a/widget/cocoa/nsCocoaUtils.mm +++ /dev/null @@ -1,1022 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 - -#include "gfx2DGlue.h" -#include "gfxPlatform.h" -#include "gfxUtils.h" -#include "ImageRegion.h" -#include "nsCocoaUtils.h" -#include "nsChildView.h" -#include "nsMenuBarX.h" -#include "nsCocoaWindow.h" -#include "nsCOMPtr.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIAppShellService.h" -#include "nsIXULWindow.h" -#include "nsIBaseWindow.h" -#include "nsIServiceManager.h" -#include "nsMenuUtilsX.h" -#include "nsToolkit.h" -#include "nsCRT.h" -#include "SVGImageContext.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/MiscEvents.h" -#include "mozilla/Preferences.h" -#include "mozilla/TextEvents.h" - -using namespace mozilla; -using namespace mozilla::widget; - -using mozilla::gfx::BackendType; -using mozilla::gfx::DataSourceSurface; -using mozilla::gfx::DrawTarget; -using mozilla::gfx::Factory; -using mozilla::gfx::SamplingFilter; -using mozilla::gfx::IntPoint; -using mozilla::gfx::IntRect; -using mozilla::gfx::IntSize; -using mozilla::gfx::SurfaceFormat; -using mozilla::gfx::SourceSurface; -using mozilla::image::ImageRegion; -using std::ceil; - -static float -MenuBarScreenHeight() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSArray* allScreens = [NSScreen screens]; - if ([allScreens count]) { - return [[allScreens objectAtIndex:0] frame].size.height; - } - - return 0.0; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0.0); -} - -float -nsCocoaUtils::FlippedScreenY(float y) -{ - return MenuBarScreenHeight() - y; -} - -NSRect nsCocoaUtils::GeckoRectToCocoaRect(const DesktopIntRect &geckoRect) -{ - // We only need to change the Y coordinate by starting with the primary screen - // height and subtracting the gecko Y coordinate of the bottom of the rect. - return NSMakeRect(geckoRect.x, - MenuBarScreenHeight() - geckoRect.YMost(), - geckoRect.width, - geckoRect.height); -} - -NSRect -nsCocoaUtils::GeckoRectToCocoaRectDevPix(const LayoutDeviceIntRect &aGeckoRect, - CGFloat aBackingScale) -{ - return NSMakeRect(aGeckoRect.x / aBackingScale, - MenuBarScreenHeight() - aGeckoRect.YMost() / aBackingScale, - aGeckoRect.width / aBackingScale, - aGeckoRect.height / aBackingScale); -} - -DesktopIntRect nsCocoaUtils::CocoaRectToGeckoRect(const NSRect &cocoaRect) -{ - // We only need to change the Y coordinate by starting with the primary screen - // height and subtracting both the cocoa y origin and the height of the - // cocoa rect. - DesktopIntRect rect; - rect.x = NSToIntRound(cocoaRect.origin.x); - rect.y = NSToIntRound(FlippedScreenY(cocoaRect.origin.y + cocoaRect.size.height)); - rect.width = NSToIntRound(cocoaRect.origin.x + cocoaRect.size.width) - rect.x; - rect.height = NSToIntRound(FlippedScreenY(cocoaRect.origin.y)) - rect.y; - return rect; -} - -LayoutDeviceIntRect nsCocoaUtils::CocoaRectToGeckoRectDevPix( - const NSRect& aCocoaRect, CGFloat aBackingScale) -{ - LayoutDeviceIntRect rect; - rect.x = NSToIntRound(aCocoaRect.origin.x * aBackingScale); - rect.y = NSToIntRound(FlippedScreenY(aCocoaRect.origin.y + aCocoaRect.size.height) * aBackingScale); - rect.width = NSToIntRound((aCocoaRect.origin.x + aCocoaRect.size.width) * aBackingScale) - rect.x; - rect.height = NSToIntRound(FlippedScreenY(aCocoaRect.origin.y) * aBackingScale) - rect.y; - return rect; -} - -NSPoint nsCocoaUtils::ScreenLocationForEvent(NSEvent* anEvent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - // Don't trust mouse locations of mouse move events, see bug 443178. - if (!anEvent || [anEvent type] == NSMouseMoved) - return [NSEvent mouseLocation]; - - // Pin momentum scroll events to the location of the last user-controlled - // scroll event. - if (IsMomentumScrollEvent(anEvent)) - return ChildViewMouseTracker::sLastScrollEventScreenLocation; - - return nsCocoaUtils::ConvertPointToScreen([anEvent window], [anEvent locationInWindow]); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakePoint(0.0, 0.0)); -} - -BOOL nsCocoaUtils::IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return NSPointInRect(ScreenLocationForEvent(anEvent), [aWindow frame]); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -NSPoint nsCocoaUtils::EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return nsCocoaUtils::ConvertPointFromScreen(aWindow, ScreenLocationForEvent(anEvent)); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NSMakePoint(0.0, 0.0)); -} - -@interface NSEvent (ScrollPhase) -// 10.5 and 10.6 -- (long long)_scrollPhase; -// 10.7 and above -- (NSEventPhase)phase; -- (NSEventPhase)momentumPhase; -@end - -NSEventPhase nsCocoaUtils::EventPhase(NSEvent* aEvent) -{ - if ([aEvent respondsToSelector:@selector(phase)]) { - return [aEvent phase]; - } - return NSEventPhaseNone; -} - -NSEventPhase nsCocoaUtils::EventMomentumPhase(NSEvent* aEvent) -{ - if ([aEvent respondsToSelector:@selector(momentumPhase)]) { - return [aEvent momentumPhase]; - } - if ([aEvent respondsToSelector:@selector(_scrollPhase)]) { - switch ([aEvent _scrollPhase]) { - case 1: return NSEventPhaseBegan; - case 2: return NSEventPhaseChanged; - case 3: return NSEventPhaseEnded; - default: return NSEventPhaseNone; - } - } - return NSEventPhaseNone; -} - -BOOL nsCocoaUtils::IsMomentumScrollEvent(NSEvent* aEvent) -{ - return [aEvent type] == NSScrollWheel && - EventMomentumPhase(aEvent) != NSEventPhaseNone; -} - -@interface NSEvent (HasPreciseScrollingDeltas) -// 10.7 and above -- (BOOL)hasPreciseScrollingDeltas; -// For 10.6 and below, see the comment in nsChildView.h about _eventRef -- (EventRef)_eventRef; -@end - -BOOL nsCocoaUtils::HasPreciseScrollingDeltas(NSEvent* aEvent) -{ - if ([aEvent respondsToSelector:@selector(hasPreciseScrollingDeltas)]) { - return [aEvent hasPreciseScrollingDeltas]; - } - - // For events that don't contain pixel scrolling information, the event - // kind of their underlaying carbon event is kEventMouseWheelMoved instead - // of kEventMouseScroll. - EventRef carbonEvent = [aEvent _eventRef]; - return carbonEvent && ::GetEventKind(carbonEvent) == kEventMouseScroll; -} - -@interface NSEvent (ScrollingDeltas) -// 10.6 and below -- (CGFloat)deviceDeltaX; -- (CGFloat)deviceDeltaY; -// 10.7 and above -- (CGFloat)scrollingDeltaX; -- (CGFloat)scrollingDeltaY; -@end - -void nsCocoaUtils::GetScrollingDeltas(NSEvent* aEvent, CGFloat* aOutDeltaX, CGFloat* aOutDeltaY) -{ - if ([aEvent respondsToSelector:@selector(scrollingDeltaX)]) { - *aOutDeltaX = [aEvent scrollingDeltaX]; - *aOutDeltaY = [aEvent scrollingDeltaY]; - return; - } - if ([aEvent respondsToSelector:@selector(deviceDeltaX)] && - HasPreciseScrollingDeltas(aEvent)) { - // Calling deviceDeltaX/Y on those events that do not contain pixel - // scrolling information triggers a Cocoa assertion and an - // Objective-C NSInternalInconsistencyException. - *aOutDeltaX = [aEvent deviceDeltaX]; - *aOutDeltaY = [aEvent deviceDeltaY]; - return; - } - - // This is only hit pre-10.7 when we are called on a scroll event that does - // not contain pixel scrolling information. - CGFloat lineDeltaPixels = 12; - *aOutDeltaX = [aEvent deltaX] * lineDeltaPixels; - *aOutDeltaY = [aEvent deltaY] * lineDeltaPixels; -} - -BOOL nsCocoaUtils::EventHasPhaseInformation(NSEvent* aEvent) -{ - if (![aEvent respondsToSelector:@selector(phase)]) { - return NO; - } - return EventPhase(aEvent) != NSEventPhaseNone || - EventMomentumPhase(aEvent) != NSEventPhaseNone; -} - -void nsCocoaUtils::HideOSChromeOnScreen(bool aShouldHide) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Keep track of how many hiding requests have been made, so that they can - // be nested. - static int sHiddenCount = 0; - - sHiddenCount += aShouldHide ? 1 : -1; - NS_ASSERTION(sHiddenCount >= 0, "Unbalanced HideMenuAndDockForWindow calls"); - - NSApplicationPresentationOptions options = - sHiddenCount <= 0 ? NSApplicationPresentationDefault : - NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; - [NSApp setPresentationOptions:options]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" -nsIWidget* nsCocoaUtils::GetHiddenWindowWidget() -{ - nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); - if (!appShell) { - NS_WARNING("Couldn't get AppShellService in order to get hidden window ref"); - return nullptr; - } - - nsCOMPtr hiddenWindow; - appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow)); - if (!hiddenWindow) { - // Don't warn, this happens during shutdown, bug 358607. - return nullptr; - } - - nsCOMPtr baseHiddenWindow; - baseHiddenWindow = do_GetInterface(hiddenWindow); - if (!baseHiddenWindow) { - NS_WARNING("Couldn't get nsIBaseWindow from hidden window (nsIXULWindow)"); - return nullptr; - } - - nsCOMPtr hiddenWindowWidget; - if (NS_FAILED(baseHiddenWindow->GetMainWidget(getter_AddRefs(hiddenWindowWidget)))) { - NS_WARNING("Couldn't get nsIWidget from hidden window (nsIBaseWindow)"); - return nullptr; - } - - return hiddenWindowWidget; -} - -void nsCocoaUtils::PrepareForNativeAppModalDialog() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Don't do anything if this is embedding. We'll assume that if there is no hidden - // window we shouldn't do anything, and that should cover the embedding case. - nsMenuBarX* hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar(); - if (!hiddenWindowMenuBar) - return; - - // First put up the hidden window menu bar so that app menu event handling is correct. - hiddenWindowMenuBar->Paint(); - - NSMenu* mainMenu = [NSApp mainMenu]; - NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - - // Create new menu bar for use with modal dialog - NSMenu* newMenuBar = [[NSMenu alloc] initWithTitle:@""]; - - // Swap in our app menu. Note that the event target is whatever window is up when - // the app modal dialog goes up. - NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain]; - [mainMenu removeItemAtIndex:0]; - [newMenuBar insertItem:firstMenuItem atIndex:0]; - [firstMenuItem release]; - - // Add standard edit menu - [newMenuBar addItem:nsMenuUtilsX::GetStandardEditMenuItem()]; - - // Show the new menu bar - [NSApp setMainMenu:newMenuBar]; - [newMenuBar release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaUtils::CleanUpAfterNativeAppModalDialog() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Don't do anything if this is embedding. We'll assume that if there is no hidden - // window we shouldn't do anything, and that should cover the embedding case. - nsMenuBarX* hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar(); - if (!hiddenWindowMenuBar) - return; - - NSWindow* mainWindow = [NSApp mainWindow]; - if (!mainWindow) - hiddenWindowMenuBar->Paint(); - else - [WindowDelegate paintMenubarForWindow:mainWindow]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void data_ss_release_callback(void *aDataSourceSurface, - const void *data, - size_t size) -{ - if (aDataSourceSurface) { - static_cast(aDataSourceSurface)->Unmap(); - static_cast(aDataSourceSurface)->Release(); - } -} - -nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface, - CGImageRef* aResult) -{ - RefPtr dataSurface; - - if (aSurface->GetFormat() == SurfaceFormat::B8G8R8A8) { - dataSurface = aSurface->GetDataSurface(); - } else { - // CGImageCreate only supports 16- and 32-bit bit-depth - // Convert format to SurfaceFormat::B8G8R8A8 - dataSurface = gfxUtils:: - CopySurfaceToDataSourceSurfaceWithFormat(aSurface, - SurfaceFormat::B8G8R8A8); - } - - NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); - - int32_t width = dataSurface->GetSize().width; - int32_t height = dataSurface->GetSize().height; - if (height < 1 || width < 1) { - return NS_ERROR_FAILURE; - } - - DataSourceSurface::MappedSurface map; - if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) { - return NS_ERROR_FAILURE; - } - // The Unmap() call happens in data_ss_release_callback - - // Create a CGImageRef with the bits from the image, taking into account - // the alpha ordering and endianness of the machine so we don't have to - // touch the bits ourselves. - CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(dataSurface.forget().take(), - map.mData, - map.mStride * height, - data_ss_release_callback); - CGColorSpaceRef colorSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - *aResult = ::CGImageCreate(width, - height, - 8, - 32, - map.mStride, - colorSpace, - kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst, - dataProvider, - NULL, - 0, - kCGRenderingIntentDefault); - ::CGColorSpaceRelease(colorSpace); - ::CGDataProviderRelease(dataProvider); - return *aResult ? NS_OK : NS_ERROR_FAILURE; -} - -nsresult nsCocoaUtils::CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Be very careful when creating the NSImage that the backing NSImageRep is - // exactly 1:1 with the input image. On a retina display, both [NSImage - // lockFocus] and [NSImage initWithCGImage:size:] will create an image with a - // 2x backing NSImageRep. This prevents NSCursor from recognizing a retina - // cursor, which only occurs if pixelsWide and pixelsHigh are exactly 2x the - // size of the NSImage. - // - // For example, if a 32x32 SVG cursor is rendered on a retina display, then - // aInputImage will be 64x64. The resulting NSImage will be scaled back down - // to 32x32 so it stays the correct size on the screen by changing its size - // (resizing a NSImage only scales the image and doesn't resample the data). - // If aInputImage is converted using [NSImage initWithCGImage:size:] then the - // bitmap will be 128x128 and NSCursor won't recognize a retina cursor, since - // it will expect a 64x64 bitmap. - - int32_t width = ::CGImageGetWidth(aInputImage); - int32_t height = ::CGImageGetHeight(aInputImage); - NSRect imageRect = ::NSMakeRect(0.0, 0.0, width, height); - - NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:NSAlphaFirstBitmapFormat - bytesPerRow:0 - bitsPerPixel:0]; - - NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]; - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:context]; - - // Get the Quartz context and draw. - CGContextRef imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - ::CGContextDrawImage(imageContext, *(CGRect*)&imageRect, aInputImage); - - [NSGraphicsContext restoreGraphicsState]; - - *aResult = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; - [*aResult addRepresentation:offscreenRep]; - [offscreenRep release]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor) -{ - RefPtr surface; - int32_t width = 0, height = 0; - aImage->GetWidth(&width); - aImage->GetHeight(&height); - - // Render a vector image at the correct resolution on a retina display - if (aImage->GetType() == imgIContainer::TYPE_VECTOR && scaleFactor != 1.0f) { - IntSize scaledSize = IntSize::Ceil(width * scaleFactor, height * scaleFactor); - - RefPtr drawTarget = gfxPlatform::GetPlatform()-> - CreateOffscreenContentDrawTarget(scaledSize, SurfaceFormat::B8G8R8A8); - if (!drawTarget || !drawTarget->IsValid()) { - NS_ERROR("Failed to create valid DrawTarget"); - return NS_ERROR_FAILURE; - } - - RefPtr context = gfxContext::CreateOrNull(drawTarget); - MOZ_ASSERT(context); - - mozilla::image::DrawResult res = - aImage->Draw(context, scaledSize, ImageRegion::Create(scaledSize), - aWhichFrame, SamplingFilter::POINT, - /* no SVGImageContext */ Nothing(), - imgIContainer::FLAG_SYNC_DECODE); - - if (res != mozilla::image::DrawResult::SUCCESS) { - return NS_ERROR_FAILURE; - } - - surface = drawTarget->Snapshot(); - } else { - surface = aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE); - } - - NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - - CGImageRef imageRef = NULL; - nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef); - if (NS_FAILED(rv) || !imageRef) { - return NS_ERROR_FAILURE; - } - - rv = nsCocoaUtils::CreateNSImageFromCGImage(imageRef, aResult); - if (NS_FAILED(rv) || !aResult) { - return NS_ERROR_FAILURE; - } - ::CGImageRelease(imageRef); - - // Ensure the image will be rendered the correct size on a retina display - NSSize size = NSMakeSize(width, height); - [*aResult setSize:size]; - [[[*aResult representations] objectAtIndex:0] setSize:size]; - return NS_OK; -} - -// static -void -nsCocoaUtils::GetStringForNSString(const NSString *aSrc, nsAString& aDist) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!aSrc) { - aDist.Truncate(); - return; - } - - aDist.SetLength([aSrc length]); - [aSrc getCharacters: reinterpret_cast(aDist.BeginWriting())]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// static -NSString* -nsCocoaUtils::ToNSString(const nsAString& aString) -{ - if (aString.IsEmpty()) { - return [NSString string]; - } - return [NSString stringWithCharacters:reinterpret_cast(aString.BeginReading()) - length:aString.Length()]; -} - -// static -void -nsCocoaUtils::GeckoRectToNSRect(const nsIntRect& aGeckoRect, - NSRect& aOutCocoaRect) -{ - aOutCocoaRect.origin.x = aGeckoRect.x; - aOutCocoaRect.origin.y = aGeckoRect.y; - aOutCocoaRect.size.width = aGeckoRect.width; - aOutCocoaRect.size.height = aGeckoRect.height; -} - -// static -void -nsCocoaUtils::NSRectToGeckoRect(const NSRect& aCocoaRect, - nsIntRect& aOutGeckoRect) -{ - aOutGeckoRect.x = NSToIntRound(aCocoaRect.origin.x); - aOutGeckoRect.y = NSToIntRound(aCocoaRect.origin.y); - aOutGeckoRect.width = NSToIntRound(aCocoaRect.origin.x + aCocoaRect.size.width) - aOutGeckoRect.x; - aOutGeckoRect.height = NSToIntRound(aCocoaRect.origin.y + aCocoaRect.size.height) - aOutGeckoRect.y; -} - -// static -NSEvent* -nsCocoaUtils::MakeNewCocoaEventWithType(NSEventType aEventType, NSEvent *aEvent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSEvent* newEvent = - [NSEvent keyEventWithType:aEventType - location:[aEvent locationInWindow] - modifierFlags:[aEvent modifierFlags] - timestamp:[aEvent timestamp] - windowNumber:[aEvent windowNumber] - context:[aEvent context] - characters:[aEvent characters] - charactersIgnoringModifiers:[aEvent charactersIgnoringModifiers] - isARepeat:[aEvent isARepeat] - keyCode:[aEvent keyCode]]; - return newEvent; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// static -void -nsCocoaUtils::InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent) -{ - memset(aNPCocoaEvent, 0, sizeof(NPCocoaEvent)); -} - -// static -void -nsCocoaUtils::InitInputEvent(WidgetInputEvent& aInputEvent, - NSEvent* aNativeEvent) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - aInputEvent.mModifiers = ModifiersForEvent(aNativeEvent); - aInputEvent.mTime = PR_IntervalNow(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// static -Modifiers -nsCocoaUtils::ModifiersForEvent(NSEvent* aNativeEvent) -{ - NSUInteger modifiers = - aNativeEvent ? [aNativeEvent modifierFlags] : [NSEvent modifierFlags]; - Modifiers result = 0; - if (modifiers & NSShiftKeyMask) { - result |= MODIFIER_SHIFT; - } - if (modifiers & NSControlKeyMask) { - result |= MODIFIER_CONTROL; - } - if (modifiers & NSAlternateKeyMask) { - result |= MODIFIER_ALT; - // Mac's option key is similar to other platforms' AltGr key. - // Let's set AltGr flag when option key is pressed for consistency with - // other platforms. - result |= MODIFIER_ALTGRAPH; - } - if (modifiers & NSCommandKeyMask) { - result |= MODIFIER_META; - } - - if (modifiers & NSAlphaShiftKeyMask) { - result |= MODIFIER_CAPSLOCK; - } - // Mac doesn't have NumLock key. We can assume that NumLock is always locked - // if user is using a keyboard which has numpad. Otherwise, if user is using - // a keyboard which doesn't have numpad, e.g., MacBook's keyboard, we can - // assume that NumLock is always unlocked. - // Unfortunately, we cannot know whether current keyboard has numpad or not. - // We should notify locked state only when keys in numpad are pressed. - // By this, web applications may not be confused by unexpected numpad key's - // key event with unlocked state. - if (modifiers & NSNumericPadKeyMask) { - result |= MODIFIER_NUMLOCK; - } - - // Be aware, NSFunctionKeyMask is included when arrow keys, home key or some - // other keys are pressed. We cannot check whether 'fn' key is pressed or - // not by the flag. - - return result; -} - -// static -UInt32 -nsCocoaUtils::ConvertToCarbonModifier(NSUInteger aCocoaModifier) -{ - UInt32 carbonModifier = 0; - if (aCocoaModifier & NSAlphaShiftKeyMask) { - carbonModifier |= alphaLock; - } - if (aCocoaModifier & NSControlKeyMask) { - carbonModifier |= controlKey; - } - if (aCocoaModifier & NSAlternateKeyMask) { - carbonModifier |= optionKey; - } - if (aCocoaModifier & NSShiftKeyMask) { - carbonModifier |= shiftKey; - } - if (aCocoaModifier & NSCommandKeyMask) { - carbonModifier |= cmdKey; - } - if (aCocoaModifier & NSNumericPadKeyMask) { - carbonModifier |= kEventKeyModifierNumLockMask; - } - if (aCocoaModifier & NSFunctionKeyMask) { - carbonModifier |= kEventKeyModifierFnMask; - } - return carbonModifier; -} - -// While HiDPI support is not 100% complete and tested, we'll have a pref -// to allow it to be turned off in case of problems (or for testing purposes). - -// gfx.hidpi.enabled is an integer with the meaning: -// <= 0 : HiDPI support is disabled -// 1 : HiDPI enabled provided all screens have the same backing resolution -// > 1 : HiDPI enabled even if there are a mixture of screen modes - -// All the following code is to be removed once HiDPI work is more complete. - -static bool sHiDPIEnabled = false; -static bool sHiDPIPrefInitialized = false; - -// static -bool -nsCocoaUtils::HiDPIEnabled() -{ - if (!sHiDPIPrefInitialized) { - sHiDPIPrefInitialized = true; - - int prefSetting = Preferences::GetInt("gfx.hidpi.enabled", 1); - if (prefSetting <= 0) { - return false; - } - - // prefSetting is at least 1, need to check attached screens... - - int scaleFactors = 0; // used as a bitset to track the screen types found - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - while (NSScreen *screen = [screenEnum nextObject]) { - NSDictionary *desc = [screen deviceDescription]; - if ([desc objectForKey:NSDeviceIsScreen] == nil) { - continue; - } - CGFloat scale = - [screen respondsToSelector:@selector(backingScaleFactor)] ? - [screen backingScaleFactor] : 1.0; - // Currently, we only care about differentiating "1.0" and "2.0", - // so we set one of the two low bits to record which. - if (scale > 1.0) { - scaleFactors |= 2; - } else { - scaleFactors |= 1; - } - } - - // Now scaleFactors will be: - // 0 if no screens (supporting backingScaleFactor) found - // 1 if only lo-DPI screens - // 2 if only hi-DPI screens - // 3 if both lo- and hi-DPI screens - // We'll enable HiDPI support if there's only a single screen type, - // OR if the pref setting is explicitly greater than 1. - sHiDPIEnabled = (scaleFactors <= 2) || (prefSetting > 1); - } - - return sHiDPIEnabled; -} - -void -nsCocoaUtils::GetCommandsFromKeyEvent(NSEvent* aEvent, - nsTArray& aCommands) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - MOZ_ASSERT(aEvent); - - static NativeKeyBindingsRecorder* sNativeKeyBindingsRecorder; - if (!sNativeKeyBindingsRecorder) { - sNativeKeyBindingsRecorder = [NativeKeyBindingsRecorder new]; - } - - [sNativeKeyBindingsRecorder startRecording:aCommands]; - - // This will trigger 0 - N calls to doCommandBySelector: and insertText: - [sNativeKeyBindingsRecorder - interpretKeyEvents:[NSArray arrayWithObject:aEvent]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@implementation NativeKeyBindingsRecorder - -- (void)startRecording:(nsTArray&)aCommands -{ - mCommands = &aCommands; - mCommands->Clear(); -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - KeyBindingsCommand command = { - aSelector, - nil - }; - - mCommands->AppendElement(command); -} - -- (void)insertText:(id)aString -{ - KeyBindingsCommand command = { - @selector(insertText:), - aString - }; - - mCommands->AppendElement(command); -} - -@end // NativeKeyBindingsRecorder - -struct KeyConversionData -{ - const char* str; - size_t strLength; - uint32_t geckoKeyCode; - uint32_t charCode; -}; - -static const KeyConversionData gKeyConversions[] = { - -#define KEYCODE_ENTRY(aStr, aCode) \ - {#aStr, sizeof(#aStr) - 1, NS_##aStr, aCode} - -// Some keycodes may have different name in nsIDOMKeyEvent from its key name. -#define KEYCODE_ENTRY2(aStr, aNSName, aCode) \ - {#aStr, sizeof(#aStr) - 1, NS_##aNSName, aCode} - - KEYCODE_ENTRY(VK_CANCEL, 0x001B), - KEYCODE_ENTRY(VK_DELETE, NSDeleteFunctionKey), - KEYCODE_ENTRY(VK_BACK, NSBackspaceCharacter), - KEYCODE_ENTRY2(VK_BACK_SPACE, VK_BACK, NSBackspaceCharacter), - KEYCODE_ENTRY(VK_TAB, NSTabCharacter), - KEYCODE_ENTRY(VK_CLEAR, NSClearLineFunctionKey), - KEYCODE_ENTRY(VK_RETURN, NSEnterCharacter), - KEYCODE_ENTRY(VK_SHIFT, 0), - KEYCODE_ENTRY(VK_CONTROL, 0), - KEYCODE_ENTRY(VK_ALT, 0), - KEYCODE_ENTRY(VK_PAUSE, NSPauseFunctionKey), - KEYCODE_ENTRY(VK_CAPS_LOCK, 0), - KEYCODE_ENTRY(VK_ESCAPE, 0), - KEYCODE_ENTRY(VK_SPACE, ' '), - KEYCODE_ENTRY(VK_PAGE_UP, NSPageUpFunctionKey), - KEYCODE_ENTRY(VK_PAGE_DOWN, NSPageDownFunctionKey), - KEYCODE_ENTRY(VK_END, NSEndFunctionKey), - KEYCODE_ENTRY(VK_HOME, NSHomeFunctionKey), - KEYCODE_ENTRY(VK_LEFT, NSLeftArrowFunctionKey), - KEYCODE_ENTRY(VK_UP, NSUpArrowFunctionKey), - KEYCODE_ENTRY(VK_RIGHT, NSRightArrowFunctionKey), - KEYCODE_ENTRY(VK_DOWN, NSDownArrowFunctionKey), - KEYCODE_ENTRY(VK_PRINTSCREEN, NSPrintScreenFunctionKey), - KEYCODE_ENTRY(VK_INSERT, NSInsertFunctionKey), - KEYCODE_ENTRY(VK_HELP, NSHelpFunctionKey), - KEYCODE_ENTRY(VK_0, '0'), - KEYCODE_ENTRY(VK_1, '1'), - KEYCODE_ENTRY(VK_2, '2'), - KEYCODE_ENTRY(VK_3, '3'), - KEYCODE_ENTRY(VK_4, '4'), - KEYCODE_ENTRY(VK_5, '5'), - KEYCODE_ENTRY(VK_6, '6'), - KEYCODE_ENTRY(VK_7, '7'), - KEYCODE_ENTRY(VK_8, '8'), - KEYCODE_ENTRY(VK_9, '9'), - KEYCODE_ENTRY(VK_SEMICOLON, ':'), - KEYCODE_ENTRY(VK_EQUALS, '='), - KEYCODE_ENTRY(VK_A, 'A'), - KEYCODE_ENTRY(VK_B, 'B'), - KEYCODE_ENTRY(VK_C, 'C'), - KEYCODE_ENTRY(VK_D, 'D'), - KEYCODE_ENTRY(VK_E, 'E'), - KEYCODE_ENTRY(VK_F, 'F'), - KEYCODE_ENTRY(VK_G, 'G'), - KEYCODE_ENTRY(VK_H, 'H'), - KEYCODE_ENTRY(VK_I, 'I'), - KEYCODE_ENTRY(VK_J, 'J'), - KEYCODE_ENTRY(VK_K, 'K'), - KEYCODE_ENTRY(VK_L, 'L'), - KEYCODE_ENTRY(VK_M, 'M'), - KEYCODE_ENTRY(VK_N, 'N'), - KEYCODE_ENTRY(VK_O, 'O'), - KEYCODE_ENTRY(VK_P, 'P'), - KEYCODE_ENTRY(VK_Q, 'Q'), - KEYCODE_ENTRY(VK_R, 'R'), - KEYCODE_ENTRY(VK_S, 'S'), - KEYCODE_ENTRY(VK_T, 'T'), - KEYCODE_ENTRY(VK_U, 'U'), - KEYCODE_ENTRY(VK_V, 'V'), - KEYCODE_ENTRY(VK_W, 'W'), - KEYCODE_ENTRY(VK_X, 'X'), - KEYCODE_ENTRY(VK_Y, 'Y'), - KEYCODE_ENTRY(VK_Z, 'Z'), - KEYCODE_ENTRY(VK_CONTEXT_MENU, NSMenuFunctionKey), - KEYCODE_ENTRY(VK_NUMPAD0, '0'), - KEYCODE_ENTRY(VK_NUMPAD1, '1'), - KEYCODE_ENTRY(VK_NUMPAD2, '2'), - KEYCODE_ENTRY(VK_NUMPAD3, '3'), - KEYCODE_ENTRY(VK_NUMPAD4, '4'), - KEYCODE_ENTRY(VK_NUMPAD5, '5'), - KEYCODE_ENTRY(VK_NUMPAD6, '6'), - KEYCODE_ENTRY(VK_NUMPAD7, '7'), - KEYCODE_ENTRY(VK_NUMPAD8, '8'), - KEYCODE_ENTRY(VK_NUMPAD9, '9'), - KEYCODE_ENTRY(VK_MULTIPLY, '*'), - KEYCODE_ENTRY(VK_ADD, '+'), - KEYCODE_ENTRY(VK_SEPARATOR, 0), - KEYCODE_ENTRY(VK_SUBTRACT, '-'), - KEYCODE_ENTRY(VK_DECIMAL, '.'), - KEYCODE_ENTRY(VK_DIVIDE, '/'), - KEYCODE_ENTRY(VK_F1, NSF1FunctionKey), - KEYCODE_ENTRY(VK_F2, NSF2FunctionKey), - KEYCODE_ENTRY(VK_F3, NSF3FunctionKey), - KEYCODE_ENTRY(VK_F4, NSF4FunctionKey), - KEYCODE_ENTRY(VK_F5, NSF5FunctionKey), - KEYCODE_ENTRY(VK_F6, NSF6FunctionKey), - KEYCODE_ENTRY(VK_F7, NSF7FunctionKey), - KEYCODE_ENTRY(VK_F8, NSF8FunctionKey), - KEYCODE_ENTRY(VK_F9, NSF9FunctionKey), - KEYCODE_ENTRY(VK_F10, NSF10FunctionKey), - KEYCODE_ENTRY(VK_F11, NSF11FunctionKey), - KEYCODE_ENTRY(VK_F12, NSF12FunctionKey), - KEYCODE_ENTRY(VK_F13, NSF13FunctionKey), - KEYCODE_ENTRY(VK_F14, NSF14FunctionKey), - KEYCODE_ENTRY(VK_F15, NSF15FunctionKey), - KEYCODE_ENTRY(VK_F16, NSF16FunctionKey), - KEYCODE_ENTRY(VK_F17, NSF17FunctionKey), - KEYCODE_ENTRY(VK_F18, NSF18FunctionKey), - KEYCODE_ENTRY(VK_F19, NSF19FunctionKey), - KEYCODE_ENTRY(VK_F20, NSF20FunctionKey), - KEYCODE_ENTRY(VK_F21, NSF21FunctionKey), - KEYCODE_ENTRY(VK_F22, NSF22FunctionKey), - KEYCODE_ENTRY(VK_F23, NSF23FunctionKey), - KEYCODE_ENTRY(VK_F24, NSF24FunctionKey), - KEYCODE_ENTRY(VK_NUM_LOCK, NSClearLineFunctionKey), - KEYCODE_ENTRY(VK_SCROLL_LOCK, NSScrollLockFunctionKey), - KEYCODE_ENTRY(VK_COMMA, ','), - KEYCODE_ENTRY(VK_PERIOD, '.'), - KEYCODE_ENTRY(VK_SLASH, '/'), - KEYCODE_ENTRY(VK_BACK_QUOTE, '`'), - KEYCODE_ENTRY(VK_OPEN_BRACKET, '['), - KEYCODE_ENTRY(VK_BACK_SLASH, '\\'), - KEYCODE_ENTRY(VK_CLOSE_BRACKET, ']'), - KEYCODE_ENTRY(VK_QUOTE, '\'') - -#undef KEYCODE_ENTRY - -}; - -uint32_t -nsCocoaUtils::ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName) -{ - if (aKeyCodeName.IsEmpty()) { - return 0; - } - - nsAutoCString keyCodeName; - keyCodeName.AssignWithConversion(aKeyCodeName); - // We want case-insensitive comparison with data stored as uppercase. - ToUpperCase(keyCodeName); - - uint32_t keyCodeNameLength = keyCodeName.Length(); - const char* keyCodeNameStr = keyCodeName.get(); - for (uint16_t i = 0; i < ArrayLength(gKeyConversions); ++i) { - if (keyCodeNameLength == gKeyConversions[i].strLength && - nsCRT::strcmp(gKeyConversions[i].str, keyCodeNameStr) == 0) { - return gKeyConversions[i].charCode; - } - } - - return 0; -} - -uint32_t -nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode) -{ - if (!aKeyCode) { - return 0; - } - - for (uint16_t i = 0; i < ArrayLength(gKeyConversions); ++i) { - if (gKeyConversions[i].geckoKeyCode == aKeyCode) { - return gKeyConversions[i].charCode; - } - } - - return 0; -} - -NSMutableAttributedString* -nsCocoaUtils::GetNSMutableAttributedString( - const nsAString& aText, - const nsTArray& aFontRanges, - const bool aIsVertical, - const CGFloat aBackingScaleFactor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL - - NSString* nsstr = nsCocoaUtils::ToNSString(aText); - NSMutableAttributedString* attrStr = - [[[NSMutableAttributedString alloc] initWithString:nsstr - attributes:nil] autorelease]; - - int32_t lastOffset = aText.Length(); - for (auto i = aFontRanges.Length(); i > 0; --i) { - const FontRange& fontRange = aFontRanges[i - 1]; - NSString* fontName = nsCocoaUtils::ToNSString(fontRange.mFontName); - CGFloat fontSize = fontRange.mFontSize / aBackingScaleFactor; - NSFont* font = [NSFont fontWithName:fontName size:fontSize]; - if (!font) { - font = [NSFont systemFontOfSize:fontSize]; - } - - NSDictionary* attrs = @{ NSFontAttributeName: font }; - NSRange range = NSMakeRange(fontRange.mStartOffset, - lastOffset - fontRange.mStartOffset); - [attrStr setAttributes:attrs range:range]; - lastOffset = fontRange.mStartOffset; - } - - if (aIsVertical) { - [attrStr addAttribute:NSVerticalGlyphFormAttributeName - value:[NSNumber numberWithInt: 1] - range:NSMakeRange(0, [attrStr length])]; - } - - return attrStr; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL -} diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h deleted file mode 100644 index 1913696b8c..0000000000 --- a/widget/cocoa/nsCocoaWindow.h +++ /dev/null @@ -1,426 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsCocoaWindow_h_ -#define nsCocoaWindow_h_ - -#undef DARWIN - -#import - -#include "mozilla/RefPtr.h" -#include "nsBaseWidget.h" -#include "nsPIWidgetCocoa.h" -#include "nsCocoaUtils.h" - -class nsCocoaWindow; -class nsChildView; -class nsMenuBarX; -@class ChildView; - -typedef struct _nsCocoaWindowList { - _nsCocoaWindowList() : prev(nullptr), window(nullptr) {} - struct _nsCocoaWindowList *prev; - nsCocoaWindow *window; // Weak -} nsCocoaWindowList; - -// NSWindow subclass that is the base class for all of our own window classes. -// Among other things, this class handles the storage of those settings that -// need to be persisted across window destruction and reconstruction, i.e. when -// switching to and from fullscreen mode. -// We don't save shadow, transparency mode or background color because it's not -// worth the hassle - Gecko will reset them anyway as soon as the window is -// resized. -@interface BaseWindow : NSWindow -{ - // Data Storage - NSMutableDictionary* mState; - BOOL mDrawsIntoWindowFrame; - NSColor* mActiveTitlebarColor; - NSColor* mInactiveTitlebarColor; - - // Shadow - BOOL mScheduledShadowInvalidation; - - // Invalidation disabling - BOOL mDisabledNeedsDisplay; - - // DPI cache. Getting the physical screen size (CGDisplayScreenSize) - // is ridiculously slow, so we cache it in the toplevel window for all - // descendants to use. - float mDPI; - - NSTrackingArea* mTrackingArea; - - NSRect mDirtyRect; - - BOOL mBeingShown; - BOOL mDrawTitle; - BOOL mBrightTitlebarForeground; - BOOL mUseMenuStyle; -} - -- (void)importState:(NSDictionary*)aState; -- (NSMutableDictionary*)exportState; -- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; -- (BOOL)drawsContentsIntoWindowFrame; -- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive; -- (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive; - -- (void)deferredInvalidateShadow; -- (void)invalidateShadow; -- (float)getDPI; - -- (void)mouseEntered:(NSEvent*)aEvent; -- (void)mouseExited:(NSEvent*)aEvent; -- (void)mouseMoved:(NSEvent*)aEvent; -- (void)updateTrackingArea; -- (NSView*)trackingAreaView; - -- (void)setBeingShown:(BOOL)aValue; -- (BOOL)isBeingShown; -- (BOOL)isVisibleOrBeingShown; - -- (ChildView*)mainChildView; - -- (NSArray*)titlebarControls; - -- (void)setWantsTitleDrawn:(BOOL)aDrawTitle; -- (BOOL)wantsTitleDrawn; - -- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground; -- (BOOL)useBrightTitlebarForeground; - -- (void)disableSetNeedsDisplay; -- (void)enableSetNeedsDisplay; - -- (NSRect)getAndResetNativeDirtyRect; - -- (void)setUseMenuStyle:(BOOL)aValue; - -@end - -@interface NSWindow (Undocumented) - -// If a window has been explicitly removed from the "window cache" (to -// deactivate it), it's sometimes necessary to "reset" it to reactivate it -// (and put it back in the "window cache"). One way to do this, which Apple -// often uses, is to set the "window number" to '-1' and then back to its -// original value. -- (void)_setWindowNumber:(NSInteger)aNumber; - -// If we set the window's stylemask to be textured, the corners on the bottom of -// the window are rounded by default. We use this private method to make -// the corners square again, a la Safari. Starting with 10.7, all windows have -// rounded bottom corners, so this call doesn't have any effect there. -- (void)setBottomCornerRounded:(BOOL)rounded; -- (BOOL)bottomCornerRounded; - -// Present in the same form on OS X since at least OS X 10.5. -- (NSRect)contentRectForFrameRect:(NSRect)windowFrame styleMask:(NSUInteger)windowStyle; -- (NSRect)frameRectForContentRect:(NSRect)windowContentRect styleMask:(NSUInteger)windowStyle; - -// Present since at least OS X 10.5. The OS calls this method on NSWindow -// (and its subclasses) to find out which NSFrameView subclass to instantiate -// to create its "frame view". -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; - -@end - -@interface PopupWindow : BaseWindow -{ -@private - BOOL mIsContextMenu; -} - -- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask - backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation; -- (BOOL)isContextMenu; -- (void)setIsContextMenu:(BOOL)flag; -- (BOOL)canBecomeMainWindow; - -@end - -@interface BorderlessWindow : BaseWindow -{ -} - -- (BOOL)canBecomeKeyWindow; -- (BOOL)canBecomeMainWindow; - -@end - -@interface WindowDelegate : NSObject -{ - nsCocoaWindow* mGeckoWindow; // [WEAK] (we are owned by the window) - // Used to avoid duplication when we send NS_ACTIVATE and - // NS_DEACTIVATE to Gecko for toplevel widgets. Starts out - // false. - bool mToplevelActiveState; - BOOL mHasEverBeenZoomed; -} -+ (void)paintMenubarForWindow:(NSWindow*)aWindow; -- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind; -- (void)windowDidResize:(NSNotification*)aNotification; -- (nsCocoaWindow*)geckoWidget; -- (bool)toplevelActiveState; -- (void)sendToplevelActivateEvents; -- (void)sendToplevelDeactivateEvents; -@end - -@class ToolbarWindow; - -// NSColor subclass that allows us to draw separate colors both in the titlebar -// and for background of the window. -@interface TitlebarAndBackgroundColor : NSColor -{ - ToolbarWindow *mWindow; // [WEAK] (we are owned by the window) -} - -- (id)initWithWindow:(ToolbarWindow*)aWindow; - -@end - -// NSWindow subclass for handling windows with toolbars. -@interface ToolbarWindow : BaseWindow -{ - TitlebarAndBackgroundColor *mColor; // strong - CGFloat mUnifiedToolbarHeight; - NSColor *mBackgroundColor; // strong - NSView *mTitlebarView; // strong - NSRect mWindowButtonsRect; - NSRect mFullScreenButtonRect; -} -// Pass nil here to get the default appearance. -- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive; -- (void)setUnifiedToolbarHeight:(CGFloat)aHeight; -- (CGFloat)unifiedToolbarHeight; -- (CGFloat)titlebarHeight; -- (NSRect)titlebarRect; -- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync; -- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect; -- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; -- (void)setSheetAttachmentPosition:(CGFloat)aY; -- (void)placeWindowButtons:(NSRect)aRect; -- (void)placeFullScreenButton:(NSRect)aRect; -- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition; -- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition; -- (void)setTemporaryBackgroundColor; -- (void)restoreBackgroundColor; -@end - -class nsCocoaWindow : public nsBaseWidget, public nsPIWidgetCocoa -{ -private: - typedef nsBaseWidget Inherited; - -public: - - nsCocoaWindow(); - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSPIWIDGETCOCOA - - virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const DesktopIntRect& aRect, - nsWidgetInitData* aInitData = nullptr) - override; - - virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData = nullptr) - override; - - virtual void Destroy() override; - - NS_IMETHOD Show(bool aState) override; - virtual nsIWidget* GetSheetWindowParent(void) override; - NS_IMETHOD Enable(bool aState) override; - virtual bool IsEnabled() const override; - virtual void SetModal(bool aState) override; - virtual void SetFakeModal(bool aState) override; - virtual bool IsRunningAppModal() override; - virtual bool IsVisible() const override; - NS_IMETHOD SetFocus(bool aState=false) override; - virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; - virtual LayoutDeviceIntPoint GetClientOffset() override; - virtual LayoutDeviceIntSize - ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override; - - virtual void* GetNativeData(uint32_t aDataType) override; - - virtual void ConstrainPosition(bool aAllowSlop, - int32_t *aX, int32_t *aY) override; - virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override; - NS_IMETHOD Move(double aX, double aY) override; - virtual void SetSizeMode(nsSizeMode aMode) override; - NS_IMETHOD HideWindowChrome(bool aShouldHide) override; - - void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true); - virtual bool PrepareForFullscreenTransition(nsISupports** aData) override; - virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, - uint16_t aDuration, - nsISupports* aData, - nsIRunnable* aCallback) override; - virtual nsresult MakeFullScreen( - bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final; - NS_IMETHOD MakeFullScreenWithNativeTransition( - bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override final; - NSAnimation* FullscreenTransitionAnimation() const { return mFullscreenTransitionAnimation; } - void ReleaseFullscreenTransitionAnimation() - { - MOZ_ASSERT(mFullscreenTransitionAnimation, - "Should only be called when there is animation"); - [mFullscreenTransitionAnimation release]; - mFullscreenTransitionAnimation = nil; - } - - NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override; - NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override; - virtual LayoutDeviceIntRect GetClientBounds() override; - virtual LayoutDeviceIntRect GetScreenBounds() override; - void ReportMoveEvent(); - void ReportSizeEvent(); - NS_IMETHOD SetCursor(nsCursor aCursor) override; - NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY) override; - - CGFloat BackingScaleFactor(); - void BackingScaleFactorChanged(); - virtual double GetDefaultScaleInternal() override; - virtual int32_t RoundsWidgetCoordinatesTo() override; - - mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale() final { - return mozilla::DesktopToLayoutDeviceScale(BackingScaleFactor()); - } - - NS_IMETHOD SetTitle(const nsAString& aTitle) override; - - NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override; - virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) override; - virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr, - LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE, - LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override; - NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) override; - virtual void CaptureRollupEvents(nsIRollupListener * aListener, - bool aDoCapture) override; - NS_IMETHOD GetAttention(int32_t aCycleCount) override; - virtual bool HasPendingInputEvent() override; - virtual nsTransparencyMode GetTransparencyMode() override; - virtual void SetTransparencyMode(nsTransparencyMode aMode) override; - virtual void SetWindowShadowStyle(int32_t aStyle) override; - virtual void SetShowsToolbarButton(bool aShow) override; - virtual void SetShowsFullScreenButton(bool aShow) override; - virtual void SetWindowAnimationType(WindowAnimationType aType) override; - virtual void SetDrawsTitle(bool aDrawTitle) override; - virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override; - NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override; - virtual void SetWindowTitlebarColor(nscolor aColor, bool aActive) override; - virtual void SetDrawsInTitlebar(bool aState) override; - virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) override; - virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - uint32_t aModifierFlags, - nsIObserver* aObserver) override; - - void DispatchSizeModeEvent(); - - // be notified that a some form of drag event needs to go into Gecko - virtual bool DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, UInt16 aKeyModifiers); - - bool HasModalDescendents() { return mNumModalDescendents > 0; } - NSWindow *GetCocoaWindow() { return mWindow; } - - void SetMenuBar(nsMenuBarX* aMenuBar); - nsMenuBarX *GetMenuBar(); - - NS_IMETHOD_(void) SetInputContext( - const InputContext& aContext, - const InputContextAction& aAction) override; - NS_IMETHOD_(InputContext) GetInputContext() override - { - return mInputContext; - } - NS_IMETHOD_(bool) ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; - - void SetPopupWindowLevel(); - -protected: - virtual ~nsCocoaWindow(); - - nsresult CreateNativeWindow(const NSRect &aRect, - nsBorderStyle aBorderStyle, - bool aRectIsFrameRect); - nsresult CreatePopupContentView(const LayoutDeviceIntRect &aRect, - nsWidgetInitData* aInitData); - void DestroyNativeWindow(); - void AdjustWindowShadow(); - void SetWindowBackgroundBlur(); - void UpdateBounds(); - - nsresult DoResize(double aX, double aY, double aWidth, double aHeight, - bool aRepaint, bool aConstrainToCurrentScreen); - - inline bool ShouldToggleNativeFullscreen(bool aFullScreen, - bool aUseSystemTransition); - nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition); - - virtual already_AddRefed - AllocateChildPopupWidget() override - { - static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID); - nsCOMPtr widget = do_CreateInstance(kCPopUpCID); - return widget.forget(); - } - - nsIWidget* mParent; // if we're a popup, this is our parent [WEAK] - nsIWidget* mAncestorLink; // link to traverse ancestors [WEAK] - BaseWindow* mWindow; // our cocoa window [STRONG] - WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG] - RefPtr mMenuBar; - NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to - nsChildView* mPopupContentView; // if this is a popup, this is its content widget - // if this is a toplevel window, and there is any ongoing fullscreen - // transition, it is the animation object. - NSAnimation* mFullscreenTransitionAnimation; - int32_t mShadowStyle; - - CGFloat mBackingScaleFactor; - - WindowAnimationType mAnimationType; - - bool mWindowMadeHere; // true if we created the window, false for embedding - bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown? - // this is used for sibling sheet contention only - bool mInFullScreenMode; - bool mInFullScreenTransition; // true from the request to enter/exit fullscreen - // (MakeFullScreen() call) to EnteredFullScreen() - bool mModal; - bool mFakeModal; - - // Only true on 10.7+ if SetShowsFullScreenButton(true) is called. - bool mSupportsNativeFullScreen; - // Whether we are currently using native fullscreen. It could be false because - // we are in the DOM fullscreen where we do not use the native fullscreen. - bool mInNativeFullScreenMode; - - bool mIsAnimationSuppressed; - - bool mInReportMoveEvent; // true if in a call to ReportMoveEvent(). - bool mInResize; // true if in a call to DoResize(). - - bool mAlwaysOnTop; - - int32_t mNumModalDescendents; - InputContext mInputContext; -}; - -#endif // nsCocoaWindow_h_ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm deleted file mode 100644 index a437504fd1..0000000000 --- a/widget/cocoa/nsCocoaWindow.mm +++ /dev/null @@ -1,3881 +0,0 @@ -/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsCocoaWindow.h" - -#include "NativeKeyBindings.h" -#include "TextInputHandler.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsWidgetsCID.h" -#include "nsIRollupListener.h" -#include "nsChildView.h" -#include "nsWindowMap.h" -#include "nsAppShell.h" -#include "nsIAppShellService.h" -#include "nsIBaseWindow.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIXULWindow.h" -#include "nsToolkit.h" -#include "nsIDOMWindow.h" -#include "nsPIDOMWindow.h" -#include "nsIDOMElement.h" -#include "nsThreadUtils.h" -#include "nsMenuBarX.h" -#include "nsMenuUtilsX.h" -#include "nsStyleConsts.h" -#include "nsNativeThemeColors.h" -#include "nsNativeThemeCocoa.h" -#include "nsChildView.h" -#include "nsCocoaFeatures.h" -#include "nsIScreenManager.h" -#include "nsIWidgetListener.h" -#include "nsIPresShell.h" -#include "nsScreenCocoa.h" -#include "VibrancyManager.h" - -#include "gfxPlatform.h" -#include "qcms.h" - -#include "mozilla/AutoRestore.h" -#include "mozilla/BasicEvents.h" -#include "mozilla/Preferences.h" -#include - -namespace mozilla { -namespace layers { -class LayerManager; -} // namespace layers -} // namespace mozilla -using namespace mozilla::layers; -using namespace mozilla::widget; -using namespace mozilla; - -int32_t gXULModalLevel = 0; - -// In principle there should be only one app-modal window at any given time. -// But sometimes, despite our best efforts, another window appears above the -// current app-modal window. So we need to keep a linked list of app-modal -// windows. (A non-sheet window that appears above an app-modal window is -// also made app-modal.) See nsCocoaWindow::SetModal(). -nsCocoaWindowList *gGeckoAppModalWindowList = NULL; - -// defined in nsMenuBarX.mm -extern NSMenu* sApplicationMenu; // Application menu shared by all menubars - -// defined in nsChildView.mm -extern BOOL gSomeMenuBarPainted; - -#if !defined(MAC_OS_X_VERSION_10_12) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 - -@interface NSWindow(AutomaticWindowTabbing) -+ (void)setAllowsAutomaticWindowTabbing:(BOOL)allow; -@end - -#endif - -extern "C" { - // CGSPrivate.h - typedef NSInteger CGSConnection; - typedef NSInteger CGSWindow; - typedef NSUInteger CGSWindowFilterRef; - extern CGSConnection _CGSDefaultConnection(void); - extern CGError CGSSetWindowShadowAndRimParameters(const CGSConnection cid, CGSWindow wid, float standardDeviation, float density, int offsetX, int offsetY, unsigned int flags); - extern CGError CGSSetWindowBackgroundBlurRadius(CGSConnection cid, CGSWindow wid, NSUInteger blur); -} - -#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" - -NS_IMPL_ISUPPORTS_INHERITED(nsCocoaWindow, Inherited, nsPIWidgetCocoa) - -// A note on testing to see if your object is a sheet... -// |mWindowType == eWindowType_sheet| is true if your gecko nsIWidget is a sheet -// widget - whether or not the sheet is showing. |[mWindow isSheet]| will return -// true *only when the sheet is actually showing*. Choose your test wisely. - -static void RollUpPopups() -{ - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE_VOID(rollupListener); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (!rollupWidget) - return; - rollupListener->Rollup(0, true, nullptr, nullptr); -} - -nsCocoaWindow::nsCocoaWindow() -: mParent(nullptr) -, mAncestorLink(nullptr) -, mWindow(nil) -, mDelegate(nil) -, mSheetWindowParent(nil) -, mPopupContentView(nil) -, mFullscreenTransitionAnimation(nil) -, mShadowStyle(NS_STYLE_WINDOW_SHADOW_DEFAULT) -, mBackingScaleFactor(0.0) -, mAnimationType(nsIWidget::eGenericWindowAnimation) -, mWindowMadeHere(false) -, mSheetNeedsShow(false) -, mInFullScreenMode(false) -, mInFullScreenTransition(false) -, mModal(false) -, mFakeModal(false) -, mSupportsNativeFullScreen(false) -, mInNativeFullScreenMode(false) -, mIsAnimationSuppressed(false) -, mInReportMoveEvent(false) -, mInResize(false) -, mAlwaysOnTop(false) -, mNumModalDescendents(0) -{ - if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)]) { - // Disable automatic tabbing on 10.12. We need to do this before we - // orderFront any of our windows. - [NSWindow setAllowsAutomaticWindowTabbing:NO]; - } -} - -void nsCocoaWindow::DestroyNativeWindow() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // We want to unhook the delegate here because we don't want events - // sent to it after this object has been destroyed. - [mWindow setDelegate:nil]; - [mWindow close]; - mWindow = nil; - [mDelegate autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsCocoaWindow::~nsCocoaWindow() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Notify the children that we're gone. Popup windows (e.g. tooltips) can - // have nsChildView children. 'kid' is an nsChildView object if and only if - // its 'type' is 'eWindowType_child'. - // childView->ResetParent() can change our list of children while it's - // being iterated, so the way we iterate the list must allow for this. - for (nsIWidget* kid = mLastChild; kid;) { - nsWindowType kidType = kid->WindowType(); - if (kidType == eWindowType_child) { - nsChildView* childView = static_cast(kid); - kid = kid->GetPrevSibling(); - childView->ResetParent(); - } else { - nsCocoaWindow* childWindow = static_cast(kid); - childWindow->mParent = nullptr; - childWindow->mAncestorLink = mAncestorLink; - kid = kid->GetPrevSibling(); - } - } - - if (mWindow && mWindowMadeHere) { - DestroyNativeWindow(); - } - - NS_IF_RELEASE(mPopupContentView); - - // Deal with the possiblity that we're being destroyed while running modal. - if (mModal) { - NS_WARNING("Widget destroyed while running modal!"); - --gXULModalLevel; - NS_ASSERTION(gXULModalLevel >= 0, "Weirdness setting modality!"); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Find the screen that overlaps aRect the most, -// if none are found default to the mainScreen. -static NSScreen* -FindTargetScreenForRect(const DesktopIntRect& aRect) -{ - NSScreen *targetScreen = [NSScreen mainScreen]; - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - int largestIntersectArea = 0; - while (NSScreen *screen = [screenEnum nextObject]) { - DesktopIntRect screenRect = - nsCocoaUtils::CocoaRectToGeckoRect([screen visibleFrame]); - screenRect = screenRect.Intersect(aRect); - int area = screenRect.width * screenRect.height; - if (area > largestIntersectArea) { - largestIntersectArea = area; - targetScreen = screen; - } - } - return targetScreen; -} - -// fits the rect to the screen that contains the largest area of it, -// or to aScreen if a screen is passed in -// NB: this operates with aRect in desktop pixels -static void -FitRectToVisibleAreaForScreen(DesktopIntRect& aRect, NSScreen* aScreen) -{ - if (!aScreen) { - aScreen = FindTargetScreenForRect(aRect); - } - - DesktopIntRect screenBounds = - nsCocoaUtils::CocoaRectToGeckoRect([aScreen visibleFrame]); - - if (aRect.width > screenBounds.width) { - aRect.width = screenBounds.width; - } - if (aRect.height > screenBounds.height) { - aRect.height = screenBounds.height; - } - - if (aRect.x - screenBounds.x + aRect.width > screenBounds.width) { - aRect.x += screenBounds.width - (aRect.x - screenBounds.x + aRect.width); - } - if (aRect.y - screenBounds.y + aRect.height > screenBounds.height) { - aRect.y += screenBounds.height - (aRect.y - screenBounds.y + aRect.height); - } - - // If the left/top edge of the window is off the screen in either direction, - // then set the window to start at the left/top edge of the screen. - if (aRect.x < screenBounds.x || aRect.x > (screenBounds.x + screenBounds.width)) { - aRect.x = screenBounds.x; - } - if (aRect.y < screenBounds.y || aRect.y > (screenBounds.y + screenBounds.height)) { - aRect.y = screenBounds.y; - } -} - -// Some applications use native popup windows -// (native context menus, native tooltips) -static bool UseNativePopupWindows() -{ -#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS - return true; -#else - return false; -#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */ -} - -// aRect here is specified in desktop pixels -nsresult -nsCocoaWindow::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const DesktopIntRect& aRect, - nsWidgetInitData* aInitData) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Because the hidden window is created outside of an event loop, - // we have to provide an autorelease pool (see bug 559075). - nsAutoreleasePool localPool; - - DesktopIntRect newBounds = aRect; - FitRectToVisibleAreaForScreen(newBounds, nullptr); - - // Set defaults which can be overriden from aInitData in BaseCreate - mWindowType = eWindowType_toplevel; - mBorderStyle = eBorderStyle_default; - - // Ensure that the toolkit is created. - nsToolkit::GetToolkit(); - - Inherited::BaseCreate(aParent, aInitData); - - mParent = aParent; - mAncestorLink = aParent; - - // Applications that use native popups don't want us to create popup windows. - if ((mWindowType == eWindowType_popup) && UseNativePopupWindows()) - return NS_OK; - - nsresult rv = - CreateNativeWindow(nsCocoaUtils::GeckoRectToCocoaRect(newBounds), - mBorderStyle, false); - NS_ENSURE_SUCCESS(rv, rv); - - if (mWindowType == eWindowType_popup) { - if (aInitData->mMouseTransparent) { - [mWindow setIgnoresMouseEvents:YES]; - } else { - [mWindow setIgnoresMouseEvents:NO]; - } - // now we can convert newBounds to device pixels for the window we created, - // as the child view expects a rect expressed in the dev pix of its parent - LayoutDeviceIntRect devRect = - RoundedToInt(newBounds * GetDesktopToDeviceScale()); - return CreatePopupContentView(devRect, aInitData); - } - - mIsAnimationSuppressed = aInitData->mIsAnimationSuppressed; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult -nsCocoaWindow::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - DesktopIntRect desktopRect = - RoundedToInt(aRect / GetDesktopToDeviceScale()); - return Create(aParent, aNativeParent, desktopRect, aInitData); -} - -static unsigned int WindowMaskForBorderStyle(nsBorderStyle aBorderStyle) -{ - bool allOrDefault = (aBorderStyle == eBorderStyle_all || - aBorderStyle == eBorderStyle_default); - - /* Apple's docs on NSWindow styles say that "a window's style mask should - * include NSTitledWindowMask if it includes any of the others [besides - * NSBorderlessWindowMask]". This implies that a borderless window - * shouldn't have any other styles than NSBorderlessWindowMask. - */ - if (!allOrDefault && !(aBorderStyle & eBorderStyle_title)) - return NSBorderlessWindowMask; - - unsigned int mask = NSTitledWindowMask; - if (allOrDefault || aBorderStyle & eBorderStyle_close) - mask |= NSClosableWindowMask; - if (allOrDefault || aBorderStyle & eBorderStyle_minimize) - mask |= NSMiniaturizableWindowMask; - if (allOrDefault || aBorderStyle & eBorderStyle_resizeh) - mask |= NSResizableWindowMask; - - return mask; -} - -// If aRectIsFrameRect, aRect specifies the frame rect of the new window. -// Otherwise, aRect.x/y specify the position of the window's frame relative to -// the bottom of the menubar and aRect.width/height specify the size of the -// content rect. -nsresult nsCocoaWindow::CreateNativeWindow(const NSRect &aRect, - nsBorderStyle aBorderStyle, - bool aRectIsFrameRect) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // We default to NSBorderlessWindowMask, add features if needed. - unsigned int features = NSBorderlessWindowMask; - - // Configure the window we will create based on the window type. - switch (mWindowType) - { - case eWindowType_invisible: - case eWindowType_child: - case eWindowType_plugin: - break; - case eWindowType_popup: - if (aBorderStyle != eBorderStyle_default && mBorderStyle & eBorderStyle_title) { - features |= NSTitledWindowMask; - if (aBorderStyle & eBorderStyle_close) { - features |= NSClosableWindowMask; - } - } - break; - case eWindowType_toplevel: - case eWindowType_dialog: - features = WindowMaskForBorderStyle(aBorderStyle); - break; - case eWindowType_sheet: - if (mParent->WindowType() != eWindowType_invisible && - aBorderStyle & eBorderStyle_resizeh) { - features = NSResizableWindowMask; - } - else { - features = NSMiniaturizableWindowMask; - } - features |= NSTitledWindowMask; - break; - default: - NS_ERROR("Unhandled window type!"); - return NS_ERROR_FAILURE; - } - - NSRect contentRect; - - if (aRectIsFrameRect) { - contentRect = [NSWindow contentRectForFrameRect:aRect styleMask:features]; - } else { - /* - * We pass a content area rect to initialize the native Cocoa window. The - * content rect we give is the same size as the size we're given by gecko. - * The origin we're given for non-popup windows is moved down by the height - * of the menu bar so that an origin of (0,100) from gecko puts the window - * 100 pixels below the top of the available desktop area. We also move the - * origin down by the height of a title bar if it exists. This is so the - * origin that gecko gives us for the top-left of the window turns out to - * be the top-left of the window we create. This is how it was done in - * Carbon. If it ought to be different we'll probably need to look at all - * the callers. - * - * Note: This means that if you put a secondary screen on top of your main - * screen and open a window in the top screen, it'll be incorrectly shifted - * down by the height of the menu bar. Same thing would happen in Carbon. - * - * Note: If you pass a rect with 0,0 for an origin, the window ends up in a - * weird place for some reason. This stops that without breaking popups. - */ - // Compensate for difference between frame and content area height (e.g. title bar). - NSRect newWindowFrame = [NSWindow frameRectForContentRect:aRect styleMask:features]; - - contentRect = aRect; - contentRect.origin.y -= (newWindowFrame.size.height - aRect.size.height); - - if (mWindowType != eWindowType_popup) - contentRect.origin.y -= [[NSApp mainMenu] menuBarHeight]; - } - - // NSLog(@"Top-level window being created at Cocoa rect: %f, %f, %f, %f\n", - // rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); - - Class windowClass = [BaseWindow class]; - // If we have a titlebar on a top-level window, we want to be able to control the - // titlebar color (for unified windows), so use the special ToolbarWindow class. - // Note that we need to check the window type because we mark sheets as - // having titlebars. - if ((mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) && - (features & NSTitledWindowMask)) - windowClass = [ToolbarWindow class]; - // If we're a popup window we need to use the PopupWindow class. - else if (mWindowType == eWindowType_popup) - windowClass = [PopupWindow class]; - // If we're a non-popup borderless window we need to use the - // BorderlessWindow class. - else if (features == NSBorderlessWindowMask) - windowClass = [BorderlessWindow class]; - - // Create the window - mWindow = [[windowClass alloc] initWithContentRect:contentRect styleMask:features - backing:NSBackingStoreBuffered defer:YES]; - - // Make sure that window titles don't leak to disk in private browsing mode - // due to macOS' resume feature. - [mWindow setRestorable:NO]; - [mWindow disableSnapshotRestoration]; - - // setup our notification delegate. Note that setDelegate: does NOT retain. - mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this]; - [mWindow setDelegate:mDelegate]; - - // Make sure that the content rect we gave has been honored. - NSRect wantedFrame = [mWindow frameRectForContentRect:contentRect]; - if (!NSEqualRects([mWindow frame], wantedFrame)) { - // This can happen when the window is not on the primary screen. - [mWindow setFrame:wantedFrame display:NO]; - } - UpdateBounds(); - - if (mWindowType == eWindowType_invisible) { - [mWindow setLevel:kCGDesktopWindowLevelKey]; - } - - if (mWindowType == eWindowType_popup) { - SetPopupWindowLevel(); - [mWindow setBackgroundColor:[NSColor clearColor]]; - [mWindow setOpaque:NO]; - } else { - // Make sure that regular windows are opaque from the start, so that - // nsChildView::WidgetTypeSupportsAcceleration returns true for them. - [mWindow setOpaque:YES]; - } - - NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior]; - if (mAlwaysOnTop) { - [mWindow setLevel:NSFloatingWindowLevel]; - newBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; - } - [mWindow setCollectionBehavior:newBehavior]; - - [mWindow setContentMinSize:NSMakeSize(60, 60)]; - [mWindow disableCursorRects]; - - // Make sure the window starts out not draggable by the background. - // We will turn it on as necessary. - [mWindow setMovableByWindowBackground:NO]; - - [[WindowDataMap sharedWindowDataMap] ensureDataForWindow:mWindow]; - mWindowMadeHere = true; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsCocoaWindow::CreatePopupContentView(const LayoutDeviceIntRect &aRect, - nsWidgetInitData* aInitData) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // We need to make our content view a ChildView. - mPopupContentView = new nsChildView(); - if (!mPopupContentView) - return NS_ERROR_FAILURE; - - NS_ADDREF(mPopupContentView); - - nsIWidget* thisAsWidget = static_cast(this); - nsresult rv = mPopupContentView->Create(thisAsWidget, nullptr, aRect, - aInitData); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - NSView* contentView = [mWindow contentView]; - ChildView* childView = (ChildView*)mPopupContentView->GetNativeData(NS_NATIVE_WIDGET); - [childView setFrame:NSZeroRect]; - [childView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [contentView addSubview:childView]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsCocoaWindow::Destroy() -{ - if (mOnDestroyCalled) - return; - mOnDestroyCalled = true; - - // SetFakeModal(true) is called for non-modal window opened by modal window. - // On Cocoa, it needs corresponding SetFakeModal(false) on destroy to restore - // ancestor windows' state. - if (mFakeModal) { - SetFakeModal(false); - } - - // If we don't hide here we run into problems with panels, this is not ideal. - // (Bug 891424) - Show(false); - - if (mPopupContentView) - mPopupContentView->Destroy(); - - if (mFullscreenTransitionAnimation) { - [mFullscreenTransitionAnimation stopAnimation]; - ReleaseFullscreenTransitionAnimation(); - } - - nsBaseWidget::Destroy(); - // nsBaseWidget::Destroy() calls GetParent()->RemoveChild(this). But we - // don't implement GetParent(), so we need to do the equivalent here. - if (mParent) { - mParent->RemoveChild(this); - } - nsBaseWidget::OnDestroy(); - - if (mInFullScreenMode) { - // On Lion we don't have to mess with the OS chrome when in Full Screen - // mode. But we do have to destroy the native window here (and not wait - // for that to happen in our destructor). We don't switch away from the - // native window's space until the window is destroyed, and otherwise this - // might not happen for several seconds (because at least one object - // holding a reference to ourselves is usually waiting to be garbage- - // collected). See bug 757618. - if (mInNativeFullScreenMode) { - DestroyNativeWindow(); - } else if (mWindow) { - nsCocoaUtils::HideOSChromeOnScreen(false); - } - } -} - -nsIWidget* nsCocoaWindow::GetSheetWindowParent(void) -{ - if (mWindowType != eWindowType_sheet) - return nullptr; - nsCocoaWindow *parent = static_cast(mParent); - while (parent && (parent->mWindowType == eWindowType_sheet)) - parent = static_cast(parent->mParent); - return parent; -} - -void* nsCocoaWindow::GetNativeData(uint32_t aDataType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL; - - void* retVal = nullptr; - - switch (aDataType) { - // to emulate how windows works, we always have to return a NSView - // for NS_NATIVE_WIDGET - case NS_NATIVE_WIDGET: - case NS_NATIVE_DISPLAY: - retVal = [mWindow contentView]; - break; - - case NS_NATIVE_WINDOW: - retVal = mWindow; - break; - - case NS_NATIVE_GRAPHIC: - // There isn't anything that makes sense to return here, - // and it doesn't matter so just return nullptr. - NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a top-level window!"); - break; - case NS_RAW_NATIVE_IME_CONTEXT: { - retVal = GetPseudoIMEContext(); - if (retVal) { - break; - } - NSView* view = mWindow ? [mWindow contentView] : nil; - if (view) { - retVal = [view inputContext]; - } - // If inputContext isn't available on this window, return this window's - // pointer instead of nullptr since if this returns nullptr, - // IMEStateManager cannot manage composition with TextComposition - // instance. Although, this case shouldn't occur. - if (NS_WARN_IF(!retVal)) { - retVal = this; - } - break; - } - } - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; -} - -bool nsCocoaWindow::IsVisible() const -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return (mWindow && ([mWindow isVisibleOrBeingShown] || mSheetNeedsShow)); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -void -nsCocoaWindow::SetModal(bool aState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // This is used during startup (outside the event loop) when creating - // the add-ons compatibility checking dialog and the profile manager UI; - // therefore, it needs to provide an autorelease pool to avoid cocoa - // objects leaking. - nsAutoreleasePool localPool; - - mModal = aState; - nsCocoaWindow *ancestor = static_cast(mAncestorLink); - if (aState) { - ++gXULModalLevel; - // When a non-sheet window gets "set modal", make the window(s) that it - // appears over behave as they should. We can't rely on native methods to - // do this, for the following reason: The OS runs modal non-sheet windows - // in an event loop (using [NSApplication runModalForWindow:] or similar - // methods) that's incompatible with the modal event loop in nsXULWindow:: - // ShowModal() (each of these event loops is "exclusive", and can't run at - // the same time as other (similar) event loops). - if (mWindowType != eWindowType_sheet) { - while (ancestor) { - if (ancestor->mNumModalDescendents++ == 0) { - NSWindow *aWindow = ancestor->GetCocoaWindow(); - if (ancestor->mWindowType != eWindowType_invisible) { - [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:NO]; - [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:NO]; - [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:NO]; - } - } - ancestor = static_cast(ancestor->mParent); - } - [mWindow setLevel:NSModalPanelWindowLevel]; - nsCocoaWindowList *windowList = new nsCocoaWindowList; - if (windowList) { - windowList->window = this; // Don't ADDREF - windowList->prev = gGeckoAppModalWindowList; - gGeckoAppModalWindowList = windowList; - } - } - } - else { - --gXULModalLevel; - NS_ASSERTION(gXULModalLevel >= 0, "Mismatched call to nsCocoaWindow::SetModal(false)!"); - if (mWindowType != eWindowType_sheet) { - while (ancestor) { - if (--ancestor->mNumModalDescendents == 0) { - NSWindow *aWindow = ancestor->GetCocoaWindow(); - if (ancestor->mWindowType != eWindowType_invisible) { - [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:YES]; - [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:YES]; - [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:YES]; - } - } - NS_ASSERTION(ancestor->mNumModalDescendents >= 0, "Widget hierarchy changed while modal!"); - ancestor = static_cast(ancestor->mParent); - } - if (gGeckoAppModalWindowList) { - NS_ASSERTION(gGeckoAppModalWindowList->window == this, "Widget hierarchy changed while modal!"); - nsCocoaWindowList *saved = gGeckoAppModalWindowList; - gGeckoAppModalWindowList = gGeckoAppModalWindowList->prev; - delete saved; // "window" not ADDREFed - } - if (mWindowType == eWindowType_popup) - SetPopupWindowLevel(); - else - [mWindow setLevel:NSNormalWindowLevel]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsCocoaWindow::SetFakeModal(bool aState) -{ - mFakeModal = aState; - SetModal(aState); -} - -bool -nsCocoaWindow::IsRunningAppModal() -{ - return [NSApp _isRunningAppModal]; -} - -// Hide or show this window -NS_IMETHODIMP nsCocoaWindow::Show(bool bState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow) - return NS_OK; - - // We need to re-execute sometimes in order to bring already-visible - // windows forward. - if (!mSheetNeedsShow && !bState && ![mWindow isVisible]) - return NS_OK; - - // Protect against re-entering. - if (bState && [mWindow isBeingShown]) - return NS_OK; - - [mWindow setBeingShown:bState]; - - nsIWidget* parentWidget = mParent; - nsCOMPtr piParentWidget(do_QueryInterface(parentWidget)); - NSWindow* nativeParentWindow = (parentWidget) ? - (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW) : nil; - - if (bState && !mBounds.IsEmpty()) { - // Don't try to show a popup when the parent isn't visible or is minimized. - if (mWindowType == eWindowType_popup && nativeParentWindow) { - if (![nativeParentWindow isVisible] || [nativeParentWindow isMiniaturized]) { - return NS_ERROR_FAILURE; - } - } - - if (mPopupContentView) { - // Ensure our content view is visible. We never need to hide it. - mPopupContentView->Show(true); - } - - if (mWindowType == eWindowType_sheet) { - // bail if no parent window (its basically what we do in Carbon) - if (!nativeParentWindow || !piParentWidget) - return NS_ERROR_FAILURE; - - NSWindow* topNonSheetWindow = nativeParentWindow; - - // If this sheet is the child of another sheet, hide the parent so that - // this sheet can be displayed. Leave the parent mSheetNeedsShow alone, - // that is only used to handle sibling sheet contention. The parent will - // return once there are no more child sheets. - bool parentIsSheet = false; - if (NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) && - parentIsSheet) { - piParentWidget->GetSheetWindowParent(&topNonSheetWindow); - [NSApp endSheet:nativeParentWindow]; - } - - nsCOMPtr sheetShown; - if (NS_SUCCEEDED(piParentWidget->GetChildSheet( - true, getter_AddRefs(sheetShown))) && - (!sheetShown || sheetShown == this)) { - // If this sheet is already the sheet actually being shown, don't - // tell it to show again. Otherwise the number of calls to - // [NSApp beginSheet...] won't match up with [NSApp endSheet...]. - if (![mWindow isVisible]) { - mSheetNeedsShow = false; - mSheetWindowParent = topNonSheetWindow; - // Only set contextInfo if our parent isn't a sheet. - NSWindow* contextInfo = parentIsSheet ? nil : mSheetWindowParent; - [TopLevelWindowData deactivateInWindow:mSheetWindowParent]; - [NSApp beginSheet:mWindow - modalForWindow:mSheetWindowParent - modalDelegate:mDelegate - didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) - contextInfo:contextInfo]; - [TopLevelWindowData activateInWindow:mWindow]; - SendSetZLevelEvent(); - } - } - else { - // A sibling of this sheet is active, don't show this sheet yet. - // When the active sheet hides, its brothers and sisters that have - // mSheetNeedsShow set will have their opportunities to display. - mSheetNeedsShow = true; - } - } - else if (mWindowType == eWindowType_popup) { - if (!nsCocoaFeatures::OnMojaveOrLater()) { - // If a popup window is shown after being hidden, it needs to be "reset" - // for it to receive any mouse events aside from mouse-moved events - // (because it was removed from the "window cache" when it was hidden - // -- see below). Setting the window number to -1 and then back to its - // original value seems to accomplish this. The idea was "borrowed" - // from the Java Embedding Plugin. This is fixed on macOS 10.14+. - NSInteger windowNumber = [mWindow windowNumber]; - [mWindow _setWindowNumber:-1]; - [mWindow _setWindowNumber:windowNumber]; - } - // For reasons that aren't yet clear, calls to [NSWindow orderFront:] or - // [NSWindow makeKeyAndOrderFront:] can sometimes trigger "Error (1000) - // creating CGSWindow", which in turn triggers an internal inconsistency - // NSException. These errors shouldn't be fatal. So we need to wrap - // calls to ...orderFront: in TRY blocks. See bmo bug 470864. - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - [[mWindow contentView] setNeedsDisplay:YES]; - [mWindow orderFront:nil]; - NS_OBJC_END_TRY_ABORT_BLOCK; - SendSetZLevelEvent(); - AdjustWindowShadow(); - SetWindowBackgroundBlur(); - // If our popup window is a non-native context menu, tell the OS (and - // other programs) that a menu has opened. This is how the OS knows to - // close other programs' context menus when ours open. - if ([mWindow isKindOfClass:[PopupWindow class]] && - [(PopupWindow*) mWindow isContextMenu]) { - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification" - object:@"org.mozilla.gecko.PopupWindow"]; - } - - // If a parent window was supplied and this is a popup at the parent - // level, set its child window. This will cause the child window to - // appear above the parent and move when the parent does. Setting this - // needs to happen after the _setWindowNumber calls above, otherwise the - // window doesn't focus properly. - if (nativeParentWindow && mPopupLevel == ePopupLevelParent) - [nativeParentWindow addChildWindow:mWindow - ordered:NSWindowAbove]; - } - else { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - if (mWindowType == eWindowType_toplevel && - [mWindow respondsToSelector:@selector(setAnimationBehavior:)]) { - NSWindowAnimationBehavior behavior; - if (mIsAnimationSuppressed) { - behavior = NSWindowAnimationBehaviorNone; - } else { - switch (mAnimationType) { - case nsIWidget::eDocumentWindowAnimation: - behavior = NSWindowAnimationBehaviorDocumentWindow; - break; - default: - NS_NOTREACHED("unexpected mAnimationType value"); - // fall through - case nsIWidget::eGenericWindowAnimation: - behavior = NSWindowAnimationBehaviorDefault; - break; - } - } - [mWindow setAnimationBehavior:behavior]; - } - [mWindow makeKeyAndOrderFront:nil]; - NS_OBJC_END_TRY_ABORT_BLOCK; - SendSetZLevelEvent(); - } - } - else { - // roll up any popups if a top-level window is going away - if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) - RollUpPopups(); - - // now get rid of the window/sheet - if (mWindowType == eWindowType_sheet) { - if (mSheetNeedsShow) { - // This is an attempt to hide a sheet that never had a chance to - // be shown. There's nothing to do other than make sure that it - // won't show. - mSheetNeedsShow = false; - } - else { - // get sheet's parent *before* hiding the sheet (which breaks the linkage) - NSWindow* sheetParent = mSheetWindowParent; - - // hide the sheet - [NSApp endSheet:mWindow]; - - [TopLevelWindowData deactivateInWindow:mWindow]; - - nsCOMPtr siblingSheetToShow; - bool parentIsSheet = false; - - if (nativeParentWindow && piParentWidget && - NS_SUCCEEDED(piParentWidget->GetChildSheet( - false, getter_AddRefs(siblingSheetToShow))) && - siblingSheetToShow) { - // First, give sibling sheets an opportunity to show. - siblingSheetToShow->Show(true); - } - else if (nativeParentWindow && piParentWidget && - NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) && - parentIsSheet) { - // Only set contextInfo if the parent of the parent sheet we're about - // to restore isn't itself a sheet. - NSWindow* contextInfo = sheetParent; - nsIWidget* grandparentWidget = nil; - if (NS_SUCCEEDED(piParentWidget->GetRealParent(&grandparentWidget)) && grandparentWidget) { - nsCOMPtr piGrandparentWidget(do_QueryInterface(grandparentWidget)); - bool grandparentIsSheet = false; - if (piGrandparentWidget && NS_SUCCEEDED(piGrandparentWidget->GetIsSheet(&grandparentIsSheet)) && - grandparentIsSheet) { - contextInfo = nil; - } - } - // If there are no sibling sheets, but the parent is a sheet, restore - // it. It wasn't sent any deactivate events when it was hidden, so - // don't call through Show, just let the OS put it back up. - [NSApp beginSheet:nativeParentWindow - modalForWindow:sheetParent - modalDelegate:[nativeParentWindow delegate] - didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) - contextInfo:contextInfo]; - } - else { - // Sheet, that was hard. No more siblings or parents, going back - // to a real window. - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - [sheetParent makeKeyAndOrderFront:nil]; - NS_OBJC_END_TRY_ABORT_BLOCK; - } - SendSetZLevelEvent(); - } - } - else { - // If the window is a popup window with a parent window we need to - // unhook it here before ordering it out. When you order out the child - // of a window it hides the parent window. - if (mWindowType == eWindowType_popup && nativeParentWindow) - [nativeParentWindow removeChildWindow:mWindow]; - - [mWindow orderOut:nil]; - - if (!nsCocoaFeatures::OnMojaveOrLater()) { - // Unless it's explicitly removed from NSApp's "window cache", a popup - // window will keep receiving mouse-moved events even after it's been - // "ordered out" (instead of the browser window that was underneath it, - // until you click on that window). This is bmo bug 378645, but it's - // surely an Apple bug. The "window cache" is an undocumented - // subsystem, all of whose methods are included in the NSWindowCache - // category of the NSApplication class (in header files generated using - // class-dump). This workaround was "borrowed" from the Java Embedding - // Plugin (which uses it for a different purpose). This is fixed on - // macOS 10.14+. - if (mWindowType == eWindowType_popup) { - [NSApp _removeWindowFromCache:mWindow]; - } - } - - // If our popup window is a non-native context menu, tell the OS (and - // other programs) that a menu has closed. - if ([mWindow isKindOfClass:[PopupWindow class]] && - [(PopupWindow*) mWindow isContextMenu]) { - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:@"com.apple.HIToolbox.endMenuTrackingNotification" - object:@"org.mozilla.gecko.PopupWindow"]; - } - } - } - - [mWindow setBeingShown:NO]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -struct ShadowParams { - float standardDeviation; - float density; - int offsetX; - int offsetY; - unsigned int flags; -}; - -// These numbers have been determined by looking at the results of -// CGSGetWindowShadowAndRimParameters for native window types. -static const ShadowParams kWindowShadowParametersPreYosemite[] = { - { 0.0f, 0.0f, 0, 0, 0 }, // none - { 8.0f, 0.5f, 0, 6, 1 }, // default - { 10.0f, 0.44f, 0, 10, 512 }, // menu - { 8.0f, 0.5f, 0, 6, 1 }, // tooltip - { 4.0f, 0.6f, 0, 4, 512 } // sheet -}; - -static const ShadowParams kWindowShadowParametersPostYosemite[] = { - { 0.0f, 0.0f, 0, 0, 0 }, // none - { 8.0f, 0.5f, 0, 6, 1 }, // default - { 9.882353f, 0.3f, 0, 4, 0 }, // menu - { 3.294118f, 0.2f, 0, 1, 0 }, // tooltip - { 9.882353f, 0.3f, 0, 4, 0 } // sheet -}; - -// This method will adjust the window shadow style for popup windows after -// they have been made visible. Before they're visible, their window number -// might be -1, which is not useful. -// We won't attempt to change the shadow for windows that can acquire key state -// since OS X will reset the shadow whenever that happens. -void -nsCocoaWindow::AdjustWindowShadow() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow isVisible] || ![mWindow hasShadow] || - [mWindow canBecomeKeyWindow] || [mWindow windowNumber] == -1) - return; - - const ShadowParams& params = nsCocoaFeatures::OnYosemiteOrLater() - ? kWindowShadowParametersPostYosemite[mShadowStyle] - : kWindowShadowParametersPreYosemite[mShadowStyle]; - CGSConnection cid = _CGSDefaultConnection(); - CGSSetWindowShadowAndRimParameters(cid, [mWindow windowNumber], - params.standardDeviation, params.density, - params.offsetX, params.offsetY, - params.flags); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const NSUInteger kWindowBackgroundBlurRadius = 4; - -void -nsCocoaWindow::SetWindowBackgroundBlur() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow isVisible] || [mWindow windowNumber] == -1) - return; - - // Only blur the background of menus and fake sheets. - if (mShadowStyle != NS_STYLE_WINDOW_SHADOW_MENU && - mShadowStyle != NS_STYLE_WINDOW_SHADOW_SHEET) - return; - - CGSConnection cid = _CGSDefaultConnection(); - CGSSetWindowBackgroundBlurRadius(cid, [mWindow windowNumber], kWindowBackgroundBlurRadius); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult -nsCocoaWindow::ConfigureChildren(const nsTArray& aConfigurations) -{ - if (mPopupContentView) { - mPopupContentView->ConfigureChildren(aConfigurations); - } - return NS_OK; -} - -LayerManager* -nsCocoaWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, - LayersBackend aBackendHint, - LayerManagerPersistence aPersistence) -{ - if (mPopupContentView) { - return mPopupContentView->GetLayerManager(aShadowManager, - aBackendHint, - aPersistence); - } - return nullptr; -} - -nsTransparencyMode nsCocoaWindow::GetTransparencyMode() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return (!mWindow || [mWindow isOpaque]) ? eTransparencyOpaque : eTransparencyTransparent; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque); -} - -// This is called from nsMenuPopupFrame when making a popup transparent, or -// from nsChildView::SetTransparencyMode for other window types. -void nsCocoaWindow::SetTransparencyMode(nsTransparencyMode aMode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // Transparent windows are only supported on popups. - BOOL isTransparent = aMode == eTransparencyTransparent && - mWindowType == eWindowType_popup; - BOOL currentTransparency = ![mWindow isOpaque]; - if (isTransparent != currentTransparency) { - [mWindow setOpaque:!isTransparent]; - [mWindow setBackgroundColor:(isTransparent ? [NSColor clearColor] : [NSColor whiteColor])]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::Enable(bool aState) -{ - return NS_OK; -} - -bool nsCocoaWindow::IsEnabled() const -{ - return true; -} - -#define kWindowPositionSlop 20 - -void -nsCocoaWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow screen]) { - return; - } - - nsIntRect screenBounds; - - int32_t width, height; - - NSRect frame = [mWindow frame]; - - // zero size rects confuse the screen manager - width = std::max(frame.size.width, 1); - height = std::max(frame.size.height, 1); - - nsCOMPtr screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1"); - if (screenMgr) { - nsCOMPtr screen; - screenMgr->ScreenForRect(*aX, *aY, width, height, getter_AddRefs(screen)); - - if (screen) { - screen->GetRectDisplayPix(&(screenBounds.x), &(screenBounds.y), - &(screenBounds.width), &(screenBounds.height)); - } - } - - if (aAllowSlop) { - if (*aX < screenBounds.x - width + kWindowPositionSlop) { - *aX = screenBounds.x - width + kWindowPositionSlop; - } else if (*aX >= screenBounds.x + screenBounds.width - kWindowPositionSlop) { - *aX = screenBounds.x + screenBounds.width - kWindowPositionSlop; - } - - if (*aY < screenBounds.y - height + kWindowPositionSlop) { - *aY = screenBounds.y - height + kWindowPositionSlop; - } else if (*aY >= screenBounds.y + screenBounds.height - kWindowPositionSlop) { - *aY = screenBounds.y + screenBounds.height - kWindowPositionSlop; - } - } else { - if (*aX < screenBounds.x) { - *aX = screenBounds.x; - } else if (*aX >= screenBounds.x + screenBounds.width - width) { - *aX = screenBounds.x + screenBounds.width - width; - } - - if (*aY < screenBounds.y) { - *aY = screenBounds.y; - } else if (*aY >= screenBounds.y + screenBounds.height - height) { - *aY = screenBounds.y + screenBounds.height - height; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Popups can be smaller than (60, 60) - NSRect rect = - (mWindowType == eWindowType_popup) ? NSZeroRect : NSMakeRect(0.0, 0.0, 60, 60); - rect = [mWindow frameRectForContentRect:rect]; - - CGFloat scaleFactor = BackingScaleFactor(); - - SizeConstraints c = aConstraints; - c.mMinSize.width = - std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.width, scaleFactor), - c.mMinSize.width); - c.mMinSize.height = - std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.height, scaleFactor), - c.mMinSize.height); - - NSSize minSize = { - nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.width, scaleFactor), - nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.height, scaleFactor) - }; - [mWindow setMinSize:minSize]; - - NSSize maxSize = { - c.mMaxSize.width == NS_MAXSIZE ? - FLT_MAX : nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.width, scaleFactor), - c.mMaxSize.height == NS_MAXSIZE ? - FLT_MAX : nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.height, scaleFactor) - }; - [mWindow setMaxSize:maxSize]; - - nsBaseWidget::SetSizeConstraints(c); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Coordinates are desktop pixels -NS_IMETHODIMP nsCocoaWindow::Move(double aX, double aY) -{ - if (!mWindow) { - return NS_OK; - } - - // The point we have is in Gecko coordinates (origin top-left). Convert - // it to Cocoa ones (origin bottom-left). - NSPoint coord = { - static_cast(aX), - static_cast(nsCocoaUtils::FlippedScreenY(NSToIntRound(aY))) - }; - - NSRect frame = [mWindow frame]; - if (frame.origin.x != coord.x || - frame.origin.y + frame.size.height != coord.y) { - [mWindow setFrameTopLeftPoint:coord]; - } - - return NS_OK; -} - -void -nsCocoaWindow::SetSizeMode(nsSizeMode aMode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // mSizeMode will be updated in DispatchSizeModeEvent, which will be called - // from a delegate method that handles the state change during one of the - // calls below. - nsSizeMode previousMode = mSizeMode; - - if (aMode == nsSizeMode_Normal) { - if ([mWindow isMiniaturized]) - [mWindow deminiaturize:nil]; - else if (previousMode == nsSizeMode_Maximized && [mWindow isZoomed]) - [mWindow zoom:nil]; - } - else if (aMode == nsSizeMode_Minimized) { - if (![mWindow isMiniaturized]) - [mWindow miniaturize:nil]; - } - else if (aMode == nsSizeMode_Maximized) { - if ([mWindow isMiniaturized]) - [mWindow deminiaturize:nil]; - if (![mWindow isZoomed]) - [mWindow zoom:nil]; - } - else if (aMode == nsSizeMode_Fullscreen) { - if (!mInFullScreenMode) - MakeFullScreen(true); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// This has to preserve the window's frame bounds. -// This method requires (as does the Windows impl.) that you call Resize shortly -// after calling HideWindowChrome. See bug 498835 for fixing this. -NS_IMETHODIMP nsCocoaWindow::HideWindowChrome(bool aShouldHide) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow || !mWindowMadeHere || - (mWindowType != eWindowType_toplevel && mWindowType != eWindowType_dialog)) - return NS_ERROR_FAILURE; - - BOOL isVisible = [mWindow isVisible]; - - // Remove child windows. - NSArray* childWindows = [mWindow childWindows]; - NSEnumerator* enumerator = [childWindows objectEnumerator]; - NSWindow* child = nil; - while ((child = [enumerator nextObject])) { - [mWindow removeChildWindow:child]; - } - - // Remove the content view. - NSView* contentView = [mWindow contentView]; - [contentView retain]; - [contentView removeFromSuperviewWithoutNeedingDisplay]; - - // Save state (like window title). - NSMutableDictionary* state = [mWindow exportState]; - - // Recreate the window with the right border style. - NSRect frameRect = [mWindow frame]; - DestroyNativeWindow(); - nsresult rv = CreateNativeWindow(frameRect, aShouldHide ? eBorderStyle_none : mBorderStyle, true); - NS_ENSURE_SUCCESS(rv, rv); - - // Re-import state. - [mWindow importState:state]; - - // Reparent the content view. - [mWindow setContentView:contentView]; - [contentView release]; - - // Reparent child windows. - enumerator = [childWindows objectEnumerator]; - while ((child = [enumerator nextObject])) { - [mWindow addChildWindow:child ordered:NSWindowAbove]; - } - - // Show the new window. - if (isVisible) { - bool wasAnimationSuppressed = mIsAnimationSuppressed; - mIsAnimationSuppressed = true; - rv = Show(true); - mIsAnimationSuppressed = wasAnimationSuppressed; - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -class FullscreenTransitionData : public nsISupports -{ -public: - NS_DECL_ISUPPORTS - - explicit FullscreenTransitionData(NSWindow* aWindow) - : mTransitionWindow(aWindow) { } - - NSWindow* mTransitionWindow; - -private: - virtual ~FullscreenTransitionData() - { - [mTransitionWindow close]; - } -}; - -NS_IMPL_ISUPPORTS0(FullscreenTransitionData) - -@interface FullscreenTransitionDelegate : NSObject -{ -@public - nsCocoaWindow* mWindow; - nsIRunnable* mCallback; -} -@end - -@implementation FullscreenTransitionDelegate -- (void)cleanupAndDispatch:(NSAnimation* )animation -{ - [animation setDelegate:nil]; - [self autorelease]; - // The caller should have added ref for us. - NS_DispatchToMainThread(already_AddRefed(mCallback)); -} - -- (void)animationDidEnd:(NSAnimation *)animation -{ - MOZ_ASSERT(animation == mWindow->FullscreenTransitionAnimation(), - "Should be handling the only animation on the window"); - mWindow->ReleaseFullscreenTransitionAnimation(); - [self cleanupAndDispatch:animation]; -} - -- (void)animationDidStop:(NSAnimation *)animation -{ - [self cleanupAndDispatch:animation]; -} -@end - -/* virtual */ bool -nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData) -{ - nsCOMPtr widgetScreen = GetWidgetScreen(); - nsScreenCocoa* screen = static_cast(widgetScreen.get()); - NSScreen* cocoaScreen = screen->CocoaScreen(); - - NSWindow* win = - [[NSWindow alloc] initWithContentRect:[cocoaScreen frame] - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:YES]; - [win setBackgroundColor:[NSColor blackColor]]; - [win setAlphaValue:0]; - [win setIgnoresMouseEvents:YES]; - [win setLevel:NSScreenSaverWindowLevel]; - [win makeKeyAndOrderFront:nil]; - - auto data = new FullscreenTransitionData(win); - *aData = data; - NS_ADDREF(data); - return true; -} - -/* virtual */ void -nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage, - uint16_t aDuration, - nsISupports* aData, - nsIRunnable* aCallback) -{ - auto data = static_cast(aData); - FullscreenTransitionDelegate* delegate = - [[FullscreenTransitionDelegate alloc] init]; - delegate->mWindow = this; - // Storing already_AddRefed directly could cause static checking fail. - delegate->mCallback = nsCOMPtr(aCallback).forget().take(); - - if (mFullscreenTransitionAnimation) { - [mFullscreenTransitionAnimation stopAnimation]; - ReleaseFullscreenTransitionAnimation(); - } - - NSDictionary* dict = @{ - NSViewAnimationTargetKey: data->mTransitionWindow, - NSViewAnimationEffectKey: aStage == eBeforeFullscreenToggle ? - NSViewAnimationFadeInEffect : NSViewAnimationFadeOutEffect - }; - mFullscreenTransitionAnimation = - [[NSViewAnimation alloc] initWithViewAnimations:@[dict]]; - [mFullscreenTransitionAnimation setDelegate:delegate]; - [mFullscreenTransitionAnimation setDuration:aDuration / 1000.0]; - [mFullscreenTransitionAnimation startAnimation]; -} - -void nsCocoaWindow::EnteredFullScreen(bool aFullScreen, bool aNativeMode) -{ - mInFullScreenTransition = false; - bool wasInFullscreen = mInFullScreenMode; - mInFullScreenMode = aFullScreen; - if (aNativeMode || mInNativeFullScreenMode) { - mInNativeFullScreenMode = aFullScreen; - } - DispatchSizeModeEvent(); - if (mWidgetListener && wasInFullscreen != aFullScreen) { - mWidgetListener->FullscreenChanged(aFullScreen); - } -} - -inline bool -nsCocoaWindow::ShouldToggleNativeFullscreen(bool aFullScreen, - bool aUseSystemTransition) -{ - if (!mSupportsNativeFullScreen) { - // If we cannot use native fullscreen, don't touch it. - return false; - } - if (mInNativeFullScreenMode) { - // If we are using native fullscreen, go ahead to exit it. - return true; - } - if (!aUseSystemTransition) { - // If we do not want the system fullscreen transition, - // don't use the native fullscreen. - return false; - } - // If we are using native fullscreen, we should have returned earlier. - return aFullScreen; -} - -nsresult -nsCocoaWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) -{ - return DoMakeFullScreen(aFullScreen, false); -} - -NS_IMETHODIMP -nsCocoaWindow::MakeFullScreenWithNativeTransition(bool aFullScreen, - nsIScreen* aTargetScreen) -{ - return DoMakeFullScreen(aFullScreen, true); -} - -nsresult -nsCocoaWindow::DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow) { - return NS_OK; - } - - // We will call into MakeFullScreen redundantly when entering/exiting - // fullscreen mode via OS X controls. When that happens we should just handle - // it gracefully - no need to ASSERT. - if (mInFullScreenMode == aFullScreen) { - return NS_OK; - } - - mInFullScreenTransition = true; - - if (ShouldToggleNativeFullscreen(aFullScreen, aUseSystemTransition)) { - // If we're using native fullscreen mode and our native window is invisible, - // our attempt to go into fullscreen mode will fail with an assertion in - // system code, without [WindowDelegate windowDidFailToEnterFullScreen:] - // ever getting called. To pre-empt this we bail here. See bug 752294. - if (aFullScreen && ![mWindow isVisible]) { - EnteredFullScreen(false); - return NS_OK; - } - MOZ_ASSERT(mInNativeFullScreenMode != aFullScreen, - "We shouldn't have been in native fullscreen."); - // Calling toggleFullScreen will result in windowDid(FailTo)?(Enter|Exit)FullScreen - // to be called from the OS. We will call EnteredFullScreen from those methods, - // where mInFullScreenMode will be set and a sizemode event will be dispatched. - [mWindow toggleFullScreen:nil]; - } else { - NSDisableScreenUpdates(); - // The order here matters. When we exit full screen mode, we need to show the - // Dock first, otherwise the newly-created window won't have its minimize - // button enabled. See bug 526282. - nsCocoaUtils::HideOSChromeOnScreen(aFullScreen); - nsBaseWidget::InfallibleMakeFullScreen(aFullScreen); - NSEnableScreenUpdates(); - EnteredFullScreen(aFullScreen, /* aNativeMode */ false); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Coordinates are desktop pixels -nsresult nsCocoaWindow::DoResize(double aX, double aY, - double aWidth, double aHeight, - bool aRepaint, - bool aConstrainToCurrentScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow || mInResize) { - return NS_OK; - } - - AutoRestore reentrantResizeGuard(mInResize); - mInResize = true; - - // ConstrainSize operates in device pixels, so we need to convert using - // the backing scale factor here - CGFloat scale = BackingScaleFactor(); - int32_t width = NSToIntRound(aWidth * scale); - int32_t height = NSToIntRound(aHeight * scale); - ConstrainSize(&width, &height); - - DesktopIntRect newBounds(NSToIntRound(aX), NSToIntRound(aY), - NSToIntRound(width / scale), - NSToIntRound(height / scale)); - - // constrain to the screen that contains the largest area of the new rect - FitRectToVisibleAreaForScreen(newBounds, aConstrainToCurrentScreen ? - [mWindow screen] : nullptr); - - // convert requested bounds into Cocoa coordinate system - NSRect newFrame = nsCocoaUtils::GeckoRectToCocoaRect(newBounds); - - NSRect frame = [mWindow frame]; - BOOL isMoving = newFrame.origin.x != frame.origin.x || - newFrame.origin.y != frame.origin.y; - BOOL isResizing = newFrame.size.width != frame.size.width || - newFrame.size.height != frame.size.height; - - if (!isMoving && !isResizing) { - return NS_OK; - } - - // We ignore aRepaint -- we have to call display:YES, otherwise the - // title bar doesn't immediately get repainted and is displayed in - // the wrong place, leading to a visual jump. - [mWindow setFrame:newFrame display:YES]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Coordinates are desktop pixels -NS_IMETHODIMP nsCocoaWindow::Resize(double aX, double aY, - double aWidth, double aHeight, - bool aRepaint) -{ - return DoResize(aX, aY, aWidth, aHeight, aRepaint, false); -} - -// Coordinates are desktop pixels -NS_IMETHODIMP nsCocoaWindow::Resize(double aWidth, double aHeight, bool aRepaint) -{ - double invScale = 1.0 / BackingScaleFactor(); - return DoResize(mBounds.x * invScale, mBounds.y * invScale, - aWidth, aHeight, aRepaint, true); -} - -LayoutDeviceIntRect -nsCocoaWindow::GetClientBounds() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - CGFloat scaleFactor = BackingScaleFactor(); - if (!mWindow) { - return nsCocoaUtils::CocoaRectToGeckoRectDevPix(NSZeroRect, scaleFactor); - } - - NSRect r; - if ([mWindow isKindOfClass:[ToolbarWindow class]] && - [(ToolbarWindow*)mWindow drawsContentsIntoWindowFrame]) { - r = [mWindow frame]; - } else { - r = [mWindow contentRectForFrameRect:[mWindow frame]]; - } - - return nsCocoaUtils::CocoaRectToGeckoRectDevPix(r, scaleFactor); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntRect(0, 0, 0, 0)); -} - -void -nsCocoaWindow::UpdateBounds() -{ - NSRect frame = NSZeroRect; - if (mWindow) { - frame = [mWindow frame]; - } - mBounds = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); -} - -LayoutDeviceIntRect -nsCocoaWindow::GetScreenBounds() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - -#ifdef DEBUG - LayoutDeviceIntRect r = nsCocoaUtils::CocoaRectToGeckoRectDevPix([mWindow frame], BackingScaleFactor()); - NS_ASSERTION(mWindow && mBounds == r, "mBounds out of sync!"); -#endif - - return mBounds; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntRect(0, 0, 0, 0)); -} - -double -nsCocoaWindow::GetDefaultScaleInternal() -{ - return BackingScaleFactor(); -} - -static CGFloat -GetBackingScaleFactor(NSWindow* aWindow) -{ - NSRect frame = [aWindow frame]; - if (frame.size.width > 0 && frame.size.height > 0) { - return nsCocoaUtils::GetBackingScaleFactor(aWindow); - } - - // For windows with zero width or height, the backingScaleFactor method - // is broken - it will always return 2 on a retina macbook, even when - // the window position implies it's on a non-hidpi external display - // (to the extent that a zero-area window can be said to be "on" a - // display at all!) - // And to make matters worse, Cocoa even fires a - // windowDidChangeBackingProperties notification with the - // NSBackingPropertyOldScaleFactorKey key when a window on an - // external display is resized to/from zero height, even though it hasn't - // really changed screens. - - // This causes us to handle popup window sizing incorrectly when the - // popup is resized to zero height (bug 820327) - nsXULPopupManager - // becomes (incorrectly) convinced the popup has been explicitly forced - // to a non-default size and needs to have size attributes attached. - - // Workaround: instead of asking the window, we'll find the screen it is on - // and ask that for *its* backing scale factor. - - // (See bug 853252 and additional comments in windowDidChangeScreen: below - // for further complications this causes.) - - // First, expand the rect so that it actually has a measurable area, - // for FindTargetScreenForRect to use. - if (frame.size.width == 0) { - frame.size.width = 1; - } - if (frame.size.height == 0) { - frame.size.height = 1; - } - - // Then identify the screen it belongs to, and return its scale factor. - NSScreen *screen = - FindTargetScreenForRect(nsCocoaUtils::CocoaRectToGeckoRect(frame)); - return nsCocoaUtils::GetBackingScaleFactor(screen); -} - -CGFloat -nsCocoaWindow::BackingScaleFactor() -{ - if (mBackingScaleFactor > 0.0) { - return mBackingScaleFactor; - } - if (!mWindow) { - return 1.0; - } - mBackingScaleFactor = GetBackingScaleFactor(mWindow); - return mBackingScaleFactor; -} - -void -nsCocoaWindow::BackingScaleFactorChanged() -{ - CGFloat newScale = GetBackingScaleFactor(mWindow); - - // ignore notification if it hasn't really changed (or maybe we have - // disabled HiDPI mode via prefs) - if (mBackingScaleFactor == newScale) { - return; - } - - if (mBackingScaleFactor > 0.0) { - // convert size constraints to the new device pixel coordinate space - double scaleFactor = newScale / mBackingScaleFactor; - mSizeConstraints.mMinSize.width = - NSToIntRound(mSizeConstraints.mMinSize.width * scaleFactor); - mSizeConstraints.mMinSize.height = - NSToIntRound(mSizeConstraints.mMinSize.height * scaleFactor); - if (mSizeConstraints.mMaxSize.width < NS_MAXSIZE) { - mSizeConstraints.mMaxSize.width = - std::min(NS_MAXSIZE, - NSToIntRound(mSizeConstraints.mMaxSize.width * scaleFactor)); - } - if (mSizeConstraints.mMaxSize.height < NS_MAXSIZE) { - mSizeConstraints.mMaxSize.height = - std::min(NS_MAXSIZE, - NSToIntRound(mSizeConstraints.mMaxSize.height * scaleFactor)); - } - } - - mBackingScaleFactor = newScale; - - if (!mWidgetListener || mWidgetListener->GetXULWindow()) { - return; - } - - nsIPresShell* presShell = mWidgetListener->GetPresShell(); - if (presShell) { - presShell->BackingScaleFactorChanged(); - } -} - -int32_t -nsCocoaWindow::RoundsWidgetCoordinatesTo() -{ - if (BackingScaleFactor() == 2.0) { - return 2; - } - return 1; -} - -NS_IMETHODIMP nsCocoaWindow::SetCursor(nsCursor aCursor) -{ - if (mPopupContentView) - return mPopupContentView->SetCursor(aCursor); - - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::SetCursor(imgIContainer* aCursor, - uint32_t aHotspotX, uint32_t aHotspotY) -{ - if (mPopupContentView) - return mPopupContentView->SetCursor(aCursor, aHotspotX, aHotspotY); - - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::SetTitle(const nsAString& aTitle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mWindow) - return NS_OK; - - const nsString& strTitle = PromiseFlatString(aTitle); - NSString* title = [NSString stringWithCharacters:reinterpret_cast(strTitle.get()) - length:strTitle.Length()]; - - if ([mWindow drawsContentsIntoWindowFrame] && ![mWindow wantsTitleDrawn]) { - // Don't cause invalidations. - [mWindow disableSetNeedsDisplay]; - [mWindow setTitle:title]; - [mWindow enableSetNeedsDisplay]; - } else { - [mWindow setTitle:title]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsCocoaWindow::Invalidate(const LayoutDeviceIntRect& aRect) -{ - if (mPopupContentView) { - return mPopupContentView->Invalidate(aRect); - } - - return NS_OK; -} - -// Pass notification of some drag event to Gecko -// -// The drag manager has let us know that something related to a drag has -// occurred in this window. It could be any number of things, ranging from -// a drop, to a drag enter/leave, or a drag over event. The actual event -// is passed in |aMessage| and is passed along to our event hanlder so Gecko -// knows about it. -bool nsCocoaWindow::DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, UInt16 aKeyModifiers) -{ - return false; -} - -NS_IMETHODIMP nsCocoaWindow::SendSetZLevelEvent() -{ - nsWindowZ placement = nsWindowZTop; - nsCOMPtr actualBelow; - if (mWidgetListener) - mWidgetListener->ZLevelChanged(true, &placement, nullptr, getter_AddRefs(actualBelow)); - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetChildSheet(bool aShown, nsIWidget** _retval) -{ - nsIWidget* child = GetFirstChild(); - - while (child) { - if (child->WindowType() == eWindowType_sheet) { - // if it's a sheet, it must be an nsCocoaWindow - nsCocoaWindow* cocoaWindow = static_cast(child); - if (cocoaWindow->mWindow && - ((aShown && [cocoaWindow->mWindow isVisible]) || - (!aShown && cocoaWindow->mSheetNeedsShow))) { - nsCOMPtr widget = cocoaWindow; - widget.forget(_retval); - return NS_OK; - } - } - child = child->GetNextSibling(); - } - - *_retval = nullptr; - - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetRealParent(nsIWidget** parent) -{ - *parent = mParent; - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetIsSheet(bool* isSheet) -{ - mWindowType == eWindowType_sheet ? *isSheet = true : *isSheet = false; - return NS_OK; -} - -NS_IMETHODIMP nsCocoaWindow::GetSheetWindowParent(NSWindow** sheetWindowParent) -{ - *sheetWindowParent = mSheetWindowParent; - return NS_OK; -} - -// Invokes callback and ProcessEvent methods on Event Listener object -NS_IMETHODIMP -nsCocoaWindow::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus) -{ - aStatus = nsEventStatus_eIgnore; - - nsCOMPtr kungFuDeathGrip(event->mWidget); - mozilla::Unused << kungFuDeathGrip; // Not used within this function - - if (mWidgetListener) - aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents); - - return NS_OK; -} - -// aFullScreen should be the window's mInFullScreenMode. We don't have access to that -// from here, so we need to pass it in. mInFullScreenMode should be the canonical -// indicator that a window is currently full screen and it makes sense to keep -// all sizemode logic here. -static nsSizeMode -GetWindowSizeMode(NSWindow* aWindow, bool aFullScreen) { - if (aFullScreen) - return nsSizeMode_Fullscreen; - if ([aWindow isMiniaturized]) - return nsSizeMode_Minimized; - if (([aWindow styleMask] & NSResizableWindowMask) && [aWindow isZoomed]) - return nsSizeMode_Maximized; - return nsSizeMode_Normal; -} - -void -nsCocoaWindow::ReportMoveEvent() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Prevent recursion, which can become infinite (see bug 708278). This - // can happen when the call to [NSWindow setFrameTopLeftPoint:] in - // nsCocoaWindow::Move() triggers an immediate NSWindowDidMove notification - // (and a call to [WindowDelegate windowDidMove:]). - if (mInReportMoveEvent) { - return; - } - mInReportMoveEvent = true; - - UpdateBounds(); - - // Dispatch the move event to Gecko - NotifyWindowMoved(mBounds.x, mBounds.y); - - mInReportMoveEvent = false; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsCocoaWindow::DispatchSizeModeEvent() -{ - if (!mWindow) { - return; - } - - nsSizeMode newMode = GetWindowSizeMode(mWindow, mInFullScreenMode); - - // Don't dispatch a sizemode event if: - // 1. the window is transitioning to fullscreen - // 2. the new sizemode is the same as the current sizemode - if (mInFullScreenTransition || mSizeMode == newMode) { - return; - } - - mSizeMode = newMode; - if (mWidgetListener) { - mWidgetListener->SizeModeChanged(newMode); - } -} - -void -nsCocoaWindow::ReportSizeEvent() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - UpdateBounds(); - - if (mWidgetListener) { - LayoutDeviceIntRect innerBounds = GetClientBounds(); - mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetMenuBar(nsMenuBarX *aMenuBar) -{ - if (mMenuBar) - mMenuBar->SetParent(nullptr); - if (!mWindow) { - mMenuBar = nullptr; - return; - } - mMenuBar = aMenuBar; - - // Only paint for active windows, or paint the hidden window menu bar if no - // other menu bar has been painted yet so that some reasonable menu bar is - // displayed when the app starts up. - id windowDelegate = [mWindow delegate]; - if (mMenuBar && - ((!gSomeMenuBarPainted && nsMenuUtilsX::GetHiddenWindowMenuBar() == mMenuBar) || - (windowDelegate && [windowDelegate toplevelActiveState]))) - mMenuBar->Paint(); -} - -NS_IMETHODIMP nsCocoaWindow::SetFocus(bool aState) -{ - if (!mWindow) - return NS_OK; - - if (mPopupContentView) { - mPopupContentView->SetFocus(aState); - } - else if (aState && ([mWindow isVisible] || [mWindow isMiniaturized])) { - if ([mWindow isMiniaturized]) { - [mWindow deminiaturize:nil]; - } - - [mWindow makeKeyAndOrderFront:nil]; - SendSetZLevelEvent(); - } - - return NS_OK; -} - -LayoutDeviceIntPoint nsCocoaWindow::WidgetToScreenOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSRect rect = NSZeroRect; - LayoutDeviceIntRect r; - if (mWindow) { - rect = [mWindow contentRectForFrameRect:[mWindow frame]]; - } - r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(rect, BackingScaleFactor()); - - return r.TopLeft(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0,0)); -} - -LayoutDeviceIntPoint nsCocoaWindow::GetClientOffset() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - LayoutDeviceIntRect clientRect = GetClientBounds(); - - return clientRect.TopLeft() - mBounds.TopLeft(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0)); -} - -LayoutDeviceIntSize -nsCocoaWindow::ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!mWindow) - return LayoutDeviceIntSize(0, 0); - - CGFloat backingScale = BackingScaleFactor(); - LayoutDeviceIntRect r(0, 0, aClientSize.width, aClientSize.height); - NSRect rect = nsCocoaUtils::DevPixelsToCocoaPoints(r, backingScale); - - NSRect inflatedRect = [mWindow frameRectForContentRect:rect]; - r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(inflatedRect, backingScale); - return r.Size(); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntSize(0,0)); -} - -nsMenuBarX* nsCocoaWindow::GetMenuBar() -{ - return mMenuBar; -} - -void -nsCocoaWindow::CaptureRollupEvents(nsIRollupListener* aListener, - bool aDoCapture) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - gRollupListener = nullptr; - - if (aDoCapture) { - if (![NSApp isActive]) { - // We need to capture mouse event if we aren't - // the active application. We only set this up when needed - // because they cause spurious mouse event after crash - // and gdb sessions. See bug 699538. - nsToolkit::GetToolkit()->RegisterForAllProcessMouseEvents(); - } - gRollupListener = aListener; - - // Sometimes more than one popup window can be visible at the same time - // (e.g. nested non-native context menus, or the test case (attachment - // 276885) for bmo bug 392389, which displays a non-native combo-box in a - // non-native popup window). In these cases the "active" popup window should - // be the topmost -- the (nested) context menu the mouse is currently over, - // or the combo-box's drop-down list (when it's displayed). But (among - // windows that have the same "level") OS X makes topmost the window that - // last received a mouse-down event, which may be incorrect (in the combo- - // box case, it makes topmost the window containing the combo-box). So - // here we fiddle with a non-native popup window's level to make sure the - // "active" one is always above any other non-native popup windows that - // may be visible. - if (mWindow && (mWindowType == eWindowType_popup)) - SetPopupWindowLevel(); - } else { - nsToolkit::GetToolkit()->UnregisterAllProcessMouseEventHandlers(); - - // XXXndeakin this doesn't make sense. - // Why is the new window assumed to be a modal panel? - if (mWindow && (mWindowType == eWindowType_popup)) - [mWindow setLevel:NSModalPanelWindowLevel]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::GetAttention(int32_t aCycleCount) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - [NSApp requestUserAttention:NSInformationalRequest]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -bool -nsCocoaWindow::HasPendingInputEvent() -{ - return nsChildView::DoHasPendingInputEvent(); -} - -void -nsCocoaWindow::SetWindowShadowStyle(int32_t aStyle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - mShadowStyle = aStyle; - - // Shadowless windows are only supported on popups. - if (mWindowType == eWindowType_popup) - [mWindow setHasShadow:(aStyle != NS_STYLE_WINDOW_SHADOW_NONE)]; - - [mWindow setUseMenuStyle:(aStyle == NS_STYLE_WINDOW_SHADOW_MENU)]; - AdjustWindowShadow(); - SetWindowBackgroundBlur(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetShowsToolbarButton(bool aShow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mWindow) - [mWindow setShowsToolbarButton:aShow]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetShowsFullScreenButton(bool aShow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow || ![mWindow respondsToSelector:@selector(toggleFullScreen:)] || - mSupportsNativeFullScreen == aShow) { - return; - } - - // If the window is currently in fullscreen mode, then we're going to - // transition out first, then set the collection behavior & toggle - // mSupportsNativeFullScreen, then transtion back into fullscreen mode. This - // prevents us from getting into a conflicting state with MakeFullScreen - // where mSupportsNativeFullScreen would lead us down the wrong path. - bool wasFullScreen = mInFullScreenMode; - - if (wasFullScreen) { - MakeFullScreen(false); - } - - NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior]; - if (aShow) { - newBehavior |= NSWindowCollectionBehaviorFullScreenPrimary; - } else { - newBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; - } - [mWindow setCollectionBehavior:newBehavior]; - mSupportsNativeFullScreen = aShow; - - if (wasFullScreen) { - MakeFullScreen(true); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetWindowAnimationType(nsIWidget::WindowAnimationType aType) -{ - mAnimationType = aType; -} - -void -nsCocoaWindow::SetDrawsTitle(bool aDrawTitle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindow setWantsTitleDrawn:aDrawTitle]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsCocoaWindow::SetUseBrightTitlebarForeground(bool aBrightForeground) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindow setUseBrightTitlebarForeground:aBrightForeground]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::SetNonClientMargins(LayoutDeviceIntMargin &margins) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - SetDrawsInTitlebar(margins.top == 0); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor, bool aActive) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mWindow) - return; - - // If they pass a color with a complete transparent alpha component, use the - // native titlebar appearance. - if (NS_GET_A(aColor) == 0) { - [mWindow setTitlebarColor:nil forActiveWindow:(BOOL)aActive]; - } else { - // Transform from sRGBA to monitor RGBA. This seems like it would make trying - // to match the system appearance lame, so probably we just shouldn't color - // correct chrome. - if (gfxPlatform::GetCMSMode() == eCMSMode_All) { - qcms_transform *transform = gfxPlatform::GetCMSRGBATransform(); - if (transform) { - uint8_t color[3]; - color[0] = NS_GET_R(aColor); - color[1] = NS_GET_G(aColor); - color[2] = NS_GET_B(aColor); - qcms_transform_data(transform, color, color, 1); - aColor = NS_RGB(color[0], color[1], color[2]); - } - } - - [mWindow setTitlebarColor:[NSColor colorWithDeviceRed:NS_GET_R(aColor)/255.0 - green:NS_GET_G(aColor)/255.0 - blue:NS_GET_B(aColor)/255.0 - alpha:NS_GET_A(aColor)/255.0] - forActiveWindow:(BOOL)aActive]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetDrawsInTitlebar(bool aState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mWindow) - [mWindow setDrawsContentsIntoWindowFrame:aState]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP nsCocoaWindow::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint, - uint32_t aNativeMessage, - uint32_t aModifierFlags, - nsIObserver* aObserver) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - AutoObserverNotifier notifier(aObserver, "mouseevent"); - if (mPopupContentView) - return mPopupContentView->SynthesizeNativeMouseEvent(aPoint, aNativeMessage, - aModifierFlags, nullptr); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsCocoaWindow::UpdateThemeGeometries(const nsTArray& aThemeGeometries) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mPopupContentView) { - return mPopupContentView->UpdateThemeGeometries(aThemeGeometries); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsCocoaWindow::SetPopupWindowLevel() -{ - if (!mWindow) - return; - - // Floating popups are at the floating level and hide when the window is - // deactivated. - if (mPopupLevel == ePopupLevelFloating) { - [mWindow setLevel:NSFloatingWindowLevel]; - [mWindow setHidesOnDeactivate:YES]; - } - else { - // Otherwise, this is a top-level or parent popup. Parent popups always - // appear just above their parent and essentially ignore the level. - [mWindow setLevel:NSPopUpMenuWindowLevel]; - [mWindow setHidesOnDeactivate:NO]; - } -} - -NS_IMETHODIMP_(void) -nsCocoaWindow::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mInputContext = aContext; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP_(bool) -nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, - const WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) -{ - NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType); - return keyBindings->Execute(aEvent, aCallback, aCallbackData); -} - -@implementation WindowDelegate - -// We try to find a gecko menu bar to paint. If one does not exist, just paint -// the application menu by itself so that a window doesn't have some other -// window's menu bar. -+ (void)paintMenubarForWindow:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // make sure we only act on windows that have this kind of - // object as a delegate - id windowDelegate = [aWindow delegate]; - if ([windowDelegate class] != [self class]) - return; - - nsCocoaWindow* geckoWidget = [windowDelegate geckoWidget]; - NS_ASSERTION(geckoWidget, "Window delegate not returning a gecko widget!"); - - nsMenuBarX* geckoMenuBar = geckoWidget->GetMenuBar(); - if (geckoMenuBar) { - geckoMenuBar->Paint(); - } - else { - // sometimes we don't have a native application menu early in launching - if (!sApplicationMenu) - return; - - NSMenu* mainMenu = [NSApp mainMenu]; - NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - - // Create a new menu bar. - // We create a GeckoNSMenu because all menu bar NSMenu objects should use that subclass for - // key handling reasons. - GeckoNSMenu* newMenuBar = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; - - // move the application menu from the existing menu bar to the new one - NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain]; - [mainMenu removeItemAtIndex:0]; - [newMenuBar insertItem:firstMenuItem atIndex:0]; - [firstMenuItem release]; - - // set our new menu bar as the main menu - [NSApp setMainMenu:newMenuBar]; - [newMenuBar release]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - [super init]; - mGeckoWindow = geckoWind; - mToplevelActiveState = false; - mHasEverBeenZoomed = false; - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize -{ - RollUpPopups(); - - return proposedFrameSize; -} - -- (void)windowDidResize:(NSNotification *)aNotification -{ - BaseWindow* window = [aNotification object]; - [window updateTrackingArea]; - - if (!mGeckoWindow) - return; - - // Resizing might have changed our zoom state. - mGeckoWindow->DispatchSizeModeEvent(); - mGeckoWindow->ReportSizeEvent(); -} - -- (void)windowDidChangeScreen:(NSNotification *)aNotification -{ - if (!mGeckoWindow) - return; - - // Because of Cocoa's peculiar treatment of zero-size windows (see comments - // at GetBackingScaleFactor() above), we sometimes have a situation where - // our concept of backing scale (based on the screen where the zero-sized - // window is positioned) differs from Cocoa's idea (always based on the - // Retina screen, AFAICT, even when an external non-Retina screen is the - // primary display). - // - // As a result, if the window was created with zero size on an external - // display, but then made visible on the (secondary) Retina screen, we - // will *not* get a windowDidChangeBackingProperties notification for it. - // This leads to an incorrect GetDefaultScale(), and widget coordinate - // confusion, as per bug 853252. - // - // To work around this, we check for a backing scale mismatch when we - // receive a windowDidChangeScreen notification, as we will receive this - // even if Cocoa was already treating the zero-size window as having - // Retina backing scale. - NSWindow *window = (NSWindow *)[aNotification object]; - if ([window respondsToSelector:@selector(backingScaleFactor)]) { - if (GetBackingScaleFactor(window) != mGeckoWindow->BackingScaleFactor()) { - mGeckoWindow->BackingScaleFactorChanged(); - } - } - - mGeckoWindow->ReportMoveEvent(); -} - -// Lion's full screen mode will bypass our internal fullscreen tracking, so -// we need to catch it when we transition and call our own methods, which in -// turn will fire "fullscreen" events. -- (void)windowDidEnterFullScreen:(NSNotification *)notification -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(true); - - // On Yosemite, the NSThemeFrame class has two new properties -- - // titlebarView (an NSTitlebarView object) and titlebarContainerView (an - // NSTitlebarContainerView object). These are used to display the titlebar - // in fullscreen mode. In Safari they're not transparent. But in Firefox - // for some reason they are, which causes bug 1069658. The following code - // works around this Apple bug or design flaw. - NSWindow *window = (NSWindow *) [notification object]; - NSView *frameView = [[window contentView] superview]; - NSView *titlebarView = nil; - NSView *titlebarContainerView = nil; - if ([frameView respondsToSelector:@selector(titlebarView)]) { - titlebarView = [frameView titlebarView]; - } - if ([frameView respondsToSelector:@selector(titlebarContainerView)]) { - titlebarContainerView = [frameView titlebarContainerView]; - } - if ([titlebarView respondsToSelector:@selector(setTransparent:)]) { - [titlebarView setTransparent:NO]; - } - if ([titlebarContainerView respondsToSelector:@selector(setTransparent:)]) { - [titlebarContainerView setTransparent:NO]; - } -} - -- (void)windowDidExitFullScreen:(NSNotification *)notification -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(false); -} - -- (void)windowDidFailToEnterFullScreen:(NSWindow *)window -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(false); -} - -- (void)windowDidFailToExitFullScreen:(NSWindow *)window -{ - if (!mGeckoWindow) { - return; - } - - mGeckoWindow->EnteredFullScreen(true); -} - -- (void)windowDidBecomeMain:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - // [NSApp _isRunningAppModal] will return true if we're running an OS dialog - // app modally. If one of those is up then we want it to retain its menu bar. - if ([NSApp _isRunningAppModal]) - return; - NSWindow* window = [aNotification object]; - if (window) - [WindowDelegate paintMenubarForWindow:window]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowDidResignMain:(NSNotification *)aNotification -{ - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - // [NSApp _isRunningAppModal] will return true if we're running an OS dialog - // app modally. If one of those is up then we want it to retain its menu bar. - if ([NSApp _isRunningAppModal]) - return; - RefPtr hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar(); - if (hiddenWindowMenuBar) { - // printf("painting hidden window menu bar due to window losing main status\n"); - hiddenWindowMenuBar->Paint(); - } -} - -- (void)windowDidBecomeKey:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - NSWindow* window = [aNotification object]; - if ([window isSheet]) - [WindowDelegate paintMenubarForWindow:window]; - - nsChildView* mainChildView = - static_cast([[(BaseWindow*)window mainChildView] widget]); - if (mainChildView) { - if (mainChildView->GetInputContext().IsPasswordEditor()) { - TextInputHandler::EnableSecureEventInput(); - } else { - TextInputHandler::EnsureSecureEventInputDisabled(); - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowDidResignKey:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - ChildViewMouseTracker::ReEvaluateMouseEnterState(); - - // If a sheet just resigned key then we should paint the menu bar - // for whatever window is now main. - NSWindow* window = [aNotification object]; - if ([window isSheet]) - [WindowDelegate paintMenubarForWindow:[NSApp mainWindow]]; - - TextInputHandler::EnsureSecureEventInputDisabled(); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowWillMove:(NSNotification *)aNotification -{ - RollUpPopups(); -} - -- (void)windowDidMove:(NSNotification *)aNotification -{ - if (mGeckoWindow) - mGeckoWindow->ReportMoveEvent(); -} - -- (BOOL)windowShouldClose:(id)sender -{ - nsIWidgetListener* listener = mGeckoWindow ? mGeckoWindow->GetWidgetListener() : nullptr; - if (listener) - listener->RequestWindowClose(mGeckoWindow); - return NO; // gecko will do it -} - -- (void)windowWillClose:(NSNotification *)aNotification -{ - RollUpPopups(); -} - -- (void)windowWillMiniaturize:(NSNotification *)aNotification -{ - RollUpPopups(); -} - -- (void)windowDidMiniaturize:(NSNotification *)aNotification -{ - if (mGeckoWindow) - mGeckoWindow->DispatchSizeModeEvent(); -} - -- (void)windowDidDeminiaturize:(NSNotification *)aNotification -{ - if (mGeckoWindow) - mGeckoWindow->DispatchSizeModeEvent(); -} - -- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)proposedFrame -{ - if (!mHasEverBeenZoomed && [window isZoomed]) - return NO; // See bug 429954. - - mHasEverBeenZoomed = YES; - return YES; -} - -- (void)didEndSheet:(NSWindow*)sheet returnCode:(int)returnCode contextInfo:(void*)contextInfo -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Note: 'contextInfo' (if it is set) is the window that is the parent of - // the sheet. The value of contextInfo is determined in - // nsCocoaWindow::Show(). If it's set, 'contextInfo' is always the top- - // level window, not another sheet itself. But 'contextInfo' is nil if - // our parent window is also a sheet -- in that case we shouldn't send - // the top-level window any activate events (because it's our parent - // window that needs to get these events, not the top-level window). - [TopLevelWindowData deactivateInWindow:sheet]; - [sheet orderOut:self]; - if (contextInfo) - [TopLevelWindowData activateInWindow:(NSWindow*)contextInfo]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowDidChangeBackingProperties:(NSNotification *)aNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSWindow *window = (NSWindow *)[aNotification object]; - - if ([window respondsToSelector:@selector(backingScaleFactor)]) { - CGFloat oldFactor = - [[[aNotification userInfo] - objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - if ([window backingScaleFactor] != oldFactor) { - mGeckoWindow->BackingScaleFactorChanged(); - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (nsCocoaWindow*)geckoWidget -{ - return mGeckoWindow; -} - -- (bool)toplevelActiveState -{ - return mToplevelActiveState; -} - -- (void)sendToplevelActivateEvents -{ - if (!mToplevelActiveState && mGeckoWindow) { - nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener(); - if (listener) { - listener->WindowActivated(); - } - mToplevelActiveState = true; - } -} - -- (void)sendToplevelDeactivateEvents -{ - if (mToplevelActiveState && mGeckoWindow) { - nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener(); - if (listener) { - listener->WindowDeactivated(); - } - mToplevelActiveState = false; - } -} - -@end - -static float -GetDPI(NSWindow* aWindow) -{ - NSScreen* screen = [aWindow screen]; - if (!screen) - return 96.0f; - - CGDirectDisplayID displayID = - [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue]; - CGFloat heightMM = ::CGDisplayScreenSize(displayID).height; - size_t heightPx = ::CGDisplayPixelsHigh(displayID); - if (heightMM < 1 || heightPx < 1) { - // Something extremely bogus is going on - return 96.0f; - } - - float dpi = heightPx / (heightMM / MM_PER_INCH_FLOAT); - - // Account for HiDPI mode where Cocoa's "points" do not correspond to real - // device pixels - CGFloat backingScale = GetBackingScaleFactor(aWindow); - - return dpi * backingScale; -} - -@interface NSView(FrameViewMethodSwizzling) -- (NSPoint)FrameView__closeButtonOrigin; -- (NSPoint)FrameView__fullScreenButtonOrigin; -@end - -@implementation NSView(FrameViewMethodSwizzling) - -- (NSPoint)FrameView__closeButtonOrigin -{ - NSPoint defaultPosition = [self FrameView__closeButtonOrigin]; - if ([[self window] isKindOfClass:[ToolbarWindow class]]) { - return [(ToolbarWindow*)[self window] windowButtonsPositionWithDefaultPosition:defaultPosition]; - } - return defaultPosition; -} - -- (NSPoint)FrameView__fullScreenButtonOrigin -{ - NSPoint defaultPosition = [self FrameView__fullScreenButtonOrigin]; - if ([[self window] isKindOfClass:[ToolbarWindow class]]) { - return [(ToolbarWindow*)[self window] fullScreenButtonPositionWithDefaultPosition:defaultPosition]; - } - return defaultPosition; -} - -@end - -static NSMutableSet *gSwizzledFrameViewClasses = nil; - -@interface NSWindow(PrivateSetNeedsDisplayInRectMethod) - - (void)_setNeedsDisplayInRect:(NSRect)aRect; -@end - -// This method is on NSThemeFrame starting with 10.10, but since NSThemeFrame -// is not a public class, we declare the method on NSView instead. We only have -// this declaration in order to avoid compiler warnings. -@interface NSView(PrivateAddKnownSubviewMethod) - - (void)_addKnownSubview:(NSView*)aView positioned:(NSWindowOrderingMode)place relativeTo:(NSView*)otherView; -@end - -#if !defined(MAC_OS_X_VERSION_10_10) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10 - -@interface NSImage(CapInsets) -- (void)setCapInsets:(NSEdgeInsets)capInsets; -@end - -#endif - -#if !defined(MAC_OS_X_VERSION_10_8) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 - -@interface NSImage(ImageCreationWithDrawingHandler) -+ (NSImage *)imageWithSize:(NSSize)size - flipped:(BOOL)drawingHandlerShouldBeCalledWithFlippedContext - drawingHandler:(BOOL (^)(NSRect dstRect))drawingHandler; -@end - -#endif - -@interface NSView(NSVisualEffectViewSetMaskImage) -- (void)setMaskImage:(NSImage*)image; -@end - -@interface BaseWindow(Private) -- (void)removeTrackingArea; -- (void)cursorUpdated:(NSEvent*)aEvent; -- (void)updateContentViewSize; -- (void)reflowTitlebarElements; -@end - -@implementation BaseWindow - -// The frame of a window is implemented using undocumented NSView subclasses. -// We offset the window buttons by overriding the methods _closeButtonOrigin -// and _fullScreenButtonOrigin on these frame view classes. The class which is -// used for a window is determined in the window's frameViewClassForStyleMask: -// method, so this is where we make sure that we have swizzled the method on -// all encountered classes. -+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask -{ - Class frameViewClass = [super frameViewClassForStyleMask:styleMask]; - - if (!gSwizzledFrameViewClasses) { - gSwizzledFrameViewClasses = [[NSMutableSet setWithCapacity:3] retain]; - if (!gSwizzledFrameViewClasses) { - return frameViewClass; - } - } - - static IMP our_closeButtonOrigin = - class_getMethodImplementation([NSView class], - @selector(FrameView__closeButtonOrigin)); - static IMP our_fullScreenButtonOrigin = - class_getMethodImplementation([NSView class], - @selector(FrameView__fullScreenButtonOrigin)); - - if (![gSwizzledFrameViewClasses containsObject:frameViewClass]) { - // Either of these methods might be implemented in both a subclass of - // NSFrameView and one of its own subclasses. Which means that if we - // aren't careful we might end up swizzling the same method twice. - // Since method swizzling involves swapping pointers, this would break - // things. - IMP _closeButtonOrigin = - class_getMethodImplementation(frameViewClass, - @selector(_closeButtonOrigin)); - if (_closeButtonOrigin && _closeButtonOrigin != our_closeButtonOrigin) { - nsToolkit::SwizzleMethods(frameViewClass, @selector(_closeButtonOrigin), - @selector(FrameView__closeButtonOrigin)); - } - IMP _fullScreenButtonOrigin = - class_getMethodImplementation(frameViewClass, - @selector(_fullScreenButtonOrigin)); - if (_fullScreenButtonOrigin && - _fullScreenButtonOrigin != our_fullScreenButtonOrigin) { - nsToolkit::SwizzleMethods(frameViewClass, @selector(_fullScreenButtonOrigin), - @selector(FrameView__fullScreenButtonOrigin)); - } - [gSwizzledFrameViewClasses addObject:frameViewClass]; - } - - return frameViewClass; -} - -- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag -{ - mDrawsIntoWindowFrame = NO; - [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag]; - mState = nil; - mActiveTitlebarColor = nil; - mInactiveTitlebarColor = nil; - mScheduledShadowInvalidation = NO; - mDisabledNeedsDisplay = NO; - mDPI = GetDPI(self); - mTrackingArea = nil; - mDirtyRect = NSZeroRect; - mBeingShown = NO; - mDrawTitle = NO; - mBrightTitlebarForeground = NO; - mUseMenuStyle = NO; - [self updateTrackingArea]; - - return self; -} - -// Returns an autoreleased NSImage. -static NSImage* -GetMenuMaskImage() -{ - CGFloat radius = 4.0f; - NSEdgeInsets insets = { 5, 5, 5, 5 }; - NSSize maskSize = { 12, 12 }; - NSImage* maskImage = [NSImage imageWithSize:maskSize flipped:YES drawingHandler:^BOOL(NSRect dstRect) { - NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:dstRect xRadius:radius yRadius:radius]; - [[NSColor colorWithDeviceWhite:1.0 alpha:1.0] set]; - [path fill]; - return YES; - }]; - [maskImage setCapInsets:insets]; - return maskImage; -} - -- (void)swapOutChildViewWrapper:(NSView*)aNewWrapper -{ - [aNewWrapper setFrame:[[self contentView] frame]]; - NSView* childView = [[self mainChildView] retain]; - [childView removeFromSuperview]; - [aNewWrapper addSubview:childView]; - [childView release]; - [super setContentView:aNewWrapper]; -} - -- (void)setUseMenuStyle:(BOOL)aValue -{ - if (!VibrancyManager::SystemSupportsVibrancy()) { - return; - } - - if (aValue && !mUseMenuStyle) { - // Turn on rounded corner masking. - NSView* effectView = VibrancyManager::CreateEffectView(VibrancyType::MENU, YES); - if ([effectView respondsToSelector:@selector(setMaskImage:)]) { - [effectView setMaskImage:GetMenuMaskImage()]; - } - [self swapOutChildViewWrapper:effectView]; - [effectView release]; - } else if (mUseMenuStyle && !aValue) { - // Turn off rounded corner masking. - NSView* wrapper = [[NSView alloc] initWithFrame:NSZeroRect]; - [self swapOutChildViewWrapper:wrapper]; - [wrapper release]; - } - mUseMenuStyle = aValue; -} - -- (void)setBeingShown:(BOOL)aValue -{ - mBeingShown = aValue; -} - -- (BOOL)isBeingShown -{ - return mBeingShown; -} - -- (BOOL)isVisibleOrBeingShown -{ - return [super isVisible] || mBeingShown; -} - -- (void)disableSetNeedsDisplay -{ - mDisabledNeedsDisplay = YES; -} - -- (void)enableSetNeedsDisplay -{ - mDisabledNeedsDisplay = NO; -} - -- (void)dealloc -{ - [mActiveTitlebarColor release]; - [mInactiveTitlebarColor release]; - [self removeTrackingArea]; - ChildViewMouseTracker::OnDestroyWindow(self); - [super dealloc]; -} - -static const NSString* kStateTitleKey = @"title"; -static const NSString* kStateDrawsContentsIntoWindowFrameKey = @"drawsContentsIntoWindowFrame"; -static const NSString* kStateActiveTitlebarColorKey = @"activeTitlebarColor"; -static const NSString* kStateInactiveTitlebarColorKey = @"inactiveTitlebarColor"; -static const NSString* kStateShowsToolbarButton = @"showsToolbarButton"; -static const NSString* kStateCollectionBehavior = @"collectionBehavior"; - -- (void)importState:(NSDictionary*)aState -{ - [self setTitle:[aState objectForKey:kStateTitleKey]]; - [self setDrawsContentsIntoWindowFrame:[[aState objectForKey:kStateDrawsContentsIntoWindowFrameKey] boolValue]]; - [self setTitlebarColor:[aState objectForKey:kStateActiveTitlebarColorKey] forActiveWindow:YES]; - [self setTitlebarColor:[aState objectForKey:kStateInactiveTitlebarColorKey] forActiveWindow:NO]; - [self setShowsToolbarButton:[[aState objectForKey:kStateShowsToolbarButton] boolValue]]; - [self setCollectionBehavior:[[aState objectForKey:kStateCollectionBehavior] unsignedIntValue]]; -} - -- (NSMutableDictionary*)exportState -{ - NSMutableDictionary* state = [NSMutableDictionary dictionaryWithCapacity:10]; - [state setObject:[self title] forKey:kStateTitleKey]; - [state setObject:[NSNumber numberWithBool:[self drawsContentsIntoWindowFrame]] - forKey:kStateDrawsContentsIntoWindowFrameKey]; - NSColor* activeTitlebarColor = [self titlebarColorForActiveWindow:YES]; - if (activeTitlebarColor) { - [state setObject:activeTitlebarColor forKey:kStateActiveTitlebarColorKey]; - } - NSColor* inactiveTitlebarColor = [self titlebarColorForActiveWindow:NO]; - if (inactiveTitlebarColor) { - [state setObject:inactiveTitlebarColor forKey:kStateInactiveTitlebarColorKey]; - } - [state setObject:[NSNumber numberWithBool:[self showsToolbarButton]] - forKey:kStateShowsToolbarButton]; - [state setObject:[NSNumber numberWithUnsignedInt: [self collectionBehavior]] - forKey:kStateCollectionBehavior]; - return state; -} - -- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState -{ - bool changed = (aState != mDrawsIntoWindowFrame); - mDrawsIntoWindowFrame = aState; - if (changed) { - [self updateContentViewSize]; - [self reflowTitlebarElements]; - } -} - -- (BOOL)drawsContentsIntoWindowFrame -{ - return mDrawsIntoWindowFrame; -} - -- (void)setWantsTitleDrawn:(BOOL)aDrawTitle -{ - mDrawTitle = aDrawTitle; -} - -- (BOOL)wantsTitleDrawn -{ - return mDrawTitle; -} - -- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground -{ - mBrightTitlebarForeground = aBrightForeground; - [[self standardWindowButton:NSWindowFullScreenButton] setNeedsDisplay:YES]; -} - -- (BOOL)useBrightTitlebarForeground -{ - return mBrightTitlebarForeground; -} - -// Pass nil here to get the default appearance. -- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive -{ - [aColor retain]; - if (aActive) { - [mActiveTitlebarColor release]; - mActiveTitlebarColor = aColor; - } else { - [mInactiveTitlebarColor release]; - mInactiveTitlebarColor = aColor; - } -} - -- (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive -{ - return aActive ? mActiveTitlebarColor : mInactiveTitlebarColor; -} - -- (void)deferredInvalidateShadow -{ - if (mScheduledShadowInvalidation || [self isOpaque] || ![self hasShadow]) - return; - - [self performSelector:@selector(invalidateShadow) withObject:nil afterDelay:0]; - mScheduledShadowInvalidation = YES; -} - -- (void)invalidateShadow -{ - [super invalidateShadow]; - mScheduledShadowInvalidation = NO; -} - -- (float)getDPI -{ - return mDPI; -} - -- (NSView*)trackingAreaView -{ - NSView* contentView = [self contentView]; - return [contentView superview] ? [contentView superview] : contentView; -} - -- (ChildView*)mainChildView -{ - NSView *contentView = [self contentView]; - NSView* lastView = [[contentView subviews] lastObject]; - if ([lastView isKindOfClass:[ChildView class]]) { - return (ChildView*)lastView; - } - return nil; -} - -- (void)removeTrackingArea -{ - if (mTrackingArea) { - [[self trackingAreaView] removeTrackingArea:mTrackingArea]; - [mTrackingArea release]; - mTrackingArea = nil; - } -} - -- (void)updateTrackingArea -{ - [self removeTrackingArea]; - - NSView* view = [self trackingAreaView]; - const NSTrackingAreaOptions options = - NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways; - mTrackingArea = [[NSTrackingArea alloc] initWithRect:[view bounds] - options:options - owner:self - userInfo:nil]; - [view addTrackingArea:mTrackingArea]; -} - -- (void)mouseEntered:(NSEvent*)aEvent -{ - ChildViewMouseTracker::MouseEnteredWindow(aEvent); -} - -- (void)mouseExited:(NSEvent*)aEvent -{ - ChildViewMouseTracker::MouseExitedWindow(aEvent); -} - -- (void)mouseMoved:(NSEvent*)aEvent -{ - ChildViewMouseTracker::MouseMoved(aEvent); -} - -- (void)cursorUpdated:(NSEvent*)aEvent -{ - // Nothing to do here, but NSTrackingArea wants us to implement this method. -} - -- (void)_setNeedsDisplayInRect:(NSRect)aRect -{ - // Prevent unnecessary invalidations due to moving NSViews (e.g. for plugins) - if (!mDisabledNeedsDisplay) { - // This method is only called by Cocoa, so when we're here, we know that - // it's available and don't need to check whether our superclass responds - // to the selector. - [super _setNeedsDisplayInRect:aRect]; - mDirtyRect = NSUnionRect(mDirtyRect, aRect); - } -} - -- (NSRect)getAndResetNativeDirtyRect -{ - NSRect dirtyRect = mDirtyRect; - mDirtyRect = NSZeroRect; - return dirtyRect; -} - -- (void)updateContentViewSize -{ - NSRect rect = [self contentRectForFrameRect:[self frame]]; - [[self contentView] setFrameSize:rect.size]; -} - -// Possibly move the titlebar buttons. -- (void)reflowTitlebarElements -{ - NSView *frameView = [[self contentView] superview]; - if ([frameView respondsToSelector:@selector(_tileTitlebarAndRedisplay:)]) { - [frameView _tileTitlebarAndRedisplay:NO]; - } -} - -// Override methods that translate between content rect and frame rect. -- (NSRect)contentRectForFrameRect:(NSRect)aRect -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - return [super contentRectForFrameRect:aRect]; -} - -- (NSRect)contentRectForFrameRect:(NSRect)aRect styleMask:(NSUInteger)aMask -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - if ([super respondsToSelector:@selector(contentRectForFrameRect:styleMask:)]) { - return [super contentRectForFrameRect:aRect styleMask:aMask]; - } else { - return [NSWindow contentRectForFrameRect:aRect styleMask:aMask]; - } -} - -- (NSRect)frameRectForContentRect:(NSRect)aRect -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - return [super frameRectForContentRect:aRect]; -} - -- (NSRect)frameRectForContentRect:(NSRect)aRect styleMask:(NSUInteger)aMask -{ - if ([self drawsContentsIntoWindowFrame]) { - return aRect; - } - if ([super respondsToSelector:@selector(frameRectForContentRect:styleMask:)]) { - return [super frameRectForContentRect:aRect styleMask:aMask]; - } else { - return [NSWindow frameRectForContentRect:aRect styleMask:aMask]; - } -} - -- (void)setContentView:(NSView*)aView -{ - [super setContentView:aView]; - - // Now move the contentView to the bottommost layer so that it's guaranteed - // to be under the window buttons. - NSView* frameView = [aView superview]; - [aView removeFromSuperview]; - if ([frameView respondsToSelector:@selector(_addKnownSubview:positioned:relativeTo:)]) { - // 10.10 prints a warning when we call addSubview on the frame view, so we - // silence the warning by calling a private method instead. - [frameView _addKnownSubview:aView positioned:NSWindowBelow relativeTo:nil]; - } else { - [frameView addSubview:aView positioned:NSWindowBelow relativeTo:nil]; - } -} - -- (NSArray*)titlebarControls -{ - // Return all subviews of the frameView which are not the content view. - NSView* frameView = [[self contentView] superview]; - NSMutableArray* array = [[[frameView subviews] mutableCopy] autorelease]; - [array removeObject:[self contentView]]; - return array; -} - -- (BOOL)respondsToSelector:(SEL)aSelector -{ - // Claim the window doesn't respond to this so that the system - // doesn't steal keyboard equivalents for it. Bug 613710. - if (aSelector == @selector(cancelOperation:)) { - return NO; - } - - return [super respondsToSelector:aSelector]; -} - -- (void) doCommandBySelector:(SEL)aSelector -{ - // We override this so that it won't beep if it can't act. - // We want to control the beeping for missing or disabled - // commands ourselves. - [self tryToPerform:aSelector with:nil]; -} - -- (id)accessibilityAttributeValue:(NSString *)attribute -{ - id retval = [super accessibilityAttributeValue:attribute]; - - // The following works around a problem with Text-to-Speech on OS X 10.7. - // See bug 674612 for more info. - // - // When accessibility is off, AXUIElementCopyAttributeValue(), when called - // on an AXApplication object to get its AXFocusedUIElement attribute, - // always returns an AXWindow object (the actual browser window -- never a - // mozAccessible object). This also happens with accessibility turned on, - // if no other object in the browser window has yet been focused. But if - // the browser window has a title bar (as it currently always does), the - // AXWindow object will always have four "accessible" children, one of which - // is an AXStaticText object (the title bar's "title"; the other three are - // the close, minimize and zoom buttons). This means that (for complicated - // reasons, for which see bug 674612) Text-to-Speech on OS X 10.7 will often - // "speak" the window title, no matter what text is selected, or even if no - // text at all is selected. (This always happens when accessibility is off. - // It doesn't happen in Firefox releases because Apple has (on OS X 10.7) - // special-cased the handling of apps whose CFBundleIdentifier is - // org.mozilla.firefox.) - // - // We work around this problem by only returning AXChildren that are - // mozAccessible object or are one of the titlebar's buttons (which - // instantiate subclasses of NSButtonCell). - if ([retval isKindOfClass:[NSArray class]] && - [attribute isEqualToString:@"AXChildren"]) { - NSMutableArray *holder = [NSMutableArray arrayWithCapacity:10]; - [holder addObjectsFromArray:(NSArray *)retval]; - NSUInteger count = [holder count]; - for (NSInteger i = count - 1; i >= 0; --i) { - id item = [holder objectAtIndex:i]; - // Remove anything from holder that isn't one of the titlebar's buttons - // (which instantiate subclasses of NSButtonCell) or a mozAccessible - // object (or one of its subclasses). - if (![item isKindOfClass:[NSButtonCell class]] && - ![item respondsToSelector:@selector(hasRepresentedView)]) { - [holder removeObjectAtIndex:i]; - } - } - retval = [NSArray arrayWithArray:holder]; - } - - return retval; -} - -@end - -// This class allows us to exercise control over the window's title bar. This -// allows for a "unified toolbar" look without having to extend the content -// area into the title bar. It works like this: -// 1) We set the window's style to textured. -// 2) Because of this, the background color applies to the entire window, including -// the titlebar area. For normal textured windows, the default pattern is a -// "brushed metal" image on Tiger and a unified gradient on Leopard. -// 3) We set the background color to a custom NSColor subclass that knows how tall the window is. -// When -set is called on it, it sets a pattern (with a draw callback) as the fill. In that callback, -// it paints the the titlebar and background colors in the correct areas of the context it's given, -// which will fill the entire window (CG will tile it horizontally for us). -// 4) Whenever the window's main state changes and when [window display] is called, -// Cocoa redraws the titlebar using the patternDraw callback function. -// -// This class also provides us with a pill button to show/hide the toolbar up to 10.6. -// -// Drawing the unified gradient in the titlebar and the toolbar works like this: -// 1) In the style sheet we set the toolbar's -moz-appearance to toolbar. -// 2) When the toolbar is visible and we paint the application chrome -// window, the array that Gecko passes nsChildView::UpdateThemeGeometries -// will contain an entry for the widget type NS_THEME_TOOLBAR. -// 3) nsChildView::UpdateThemeGeometries finds the toolbar frame's ToolbarWindow -// and passes the toolbar frame's height to setUnifiedToolbarHeight. -// 4) If the toolbar height has changed, a titlebar redraw is triggered and the -// upper part of the unified gradient is drawn in the titlebar. -// 5) The lower part of the unified gradient in the toolbar is drawn during -// normal window content painting in nsNativeThemeCocoa::DrawUnifiedToolbar. -// -// Whenever the unified gradient is drawn in the titlebar or the toolbar, both -// titlebar height and toolbar height must be known in order to construct the -// correct gradient. But you can only get from the toolbar frame -// to the containing window - the other direction doesn't work. That's why the -// toolbar height is cached in the ToolbarWindow but nsNativeThemeCocoa can simply -// query the window for its titlebar height when drawing the toolbar. -// -// Note that in drawsContentsIntoWindowFrame mode, titlebar drawing works in a -// completely different way: In that mode, the window's mainChildView will -// cover the titlebar completely and nothing that happens in the window -// background will reach the screen. -@implementation ToolbarWindow - -- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - aStyle = aStyle | NSTexturedBackgroundWindowMask; - if ((self = [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) { - mColor = [[TitlebarAndBackgroundColor alloc] initWithWindow:self]; - // Bypass our guard method below. - [super setBackgroundColor:mColor]; - mBackgroundColor = [[NSColor whiteColor] retain]; - - mUnifiedToolbarHeight = 22.0f; - mWindowButtonsRect = NSZeroRect; - mFullScreenButtonRect = NSZeroRect; - - // setBottomCornerRounded: is a private API call, so we check to make sure - // we respond to it just in case. - if ([self respondsToSelector:@selector(setBottomCornerRounded:)]) - [self setBottomCornerRounded:YES]; - - [self setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; - [self setContentBorderThickness:0.0f forEdge:NSMaxYEdge]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [super setBackgroundColor:[NSColor whiteColor]]; - [mColor release]; - [mBackgroundColor release]; - [mTitlebarView release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive -{ - [super setTitlebarColor:aColor forActiveWindow:aActive]; - [self setTitlebarNeedsDisplayInRect:[self titlebarRect]]; -} - -- (void)setBackgroundColor:(NSColor*)aColor -{ - [aColor retain]; - [mBackgroundColor release]; - mBackgroundColor = aColor; -} - -- (NSColor*)windowBackgroundColor -{ - return mBackgroundColor; -} - -- (void)setTemporaryBackgroundColor -{ - [super setBackgroundColor:[NSColor whiteColor]]; -} - -- (void)restoreBackgroundColor -{ - [super setBackgroundColor:mBackgroundColor]; -} - -- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect -{ - [self setTitlebarNeedsDisplayInRect:aRect sync:NO]; -} - -- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync -{ - NSRect titlebarRect = [self titlebarRect]; - NSRect rect = NSIntersectionRect(titlebarRect, aRect); - if (NSIsEmptyRect(rect)) - return; - - NSView* borderView = [[self contentView] superview]; - if (!borderView) - return; - - if (aSync) { - [borderView displayRect:rect]; - } else { - [borderView setNeedsDisplayInRect:rect]; - } -} - -- (NSRect)titlebarRect -{ - CGFloat titlebarHeight = [self titlebarHeight]; - return NSMakeRect(0, [self frame].size.height - titlebarHeight, - [self frame].size.width, titlebarHeight); -} - -// Returns the unified height of titlebar + toolbar. -- (CGFloat)unifiedToolbarHeight -{ - return mUnifiedToolbarHeight; -} - -- (CGFloat)titlebarHeight -{ - // We use the original content rect here, not what we return from - // [self contentRectForFrameRect:], because that would give us a - // titlebarHeight of zero in drawsContentsIntoWindowFrame mode. - NSRect frameRect = [self frame]; - NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:[self styleMask]]; - return NSMaxY(frameRect) - NSMaxY(originalContentRect); -} - -// Stores the complete height of titlebar + toolbar. -- (void)setUnifiedToolbarHeight:(CGFloat)aHeight -{ - if (aHeight == mUnifiedToolbarHeight) - return; - - mUnifiedToolbarHeight = aHeight; - - if (![self drawsContentsIntoWindowFrame]) { - // Redraw the title bar. If we're inside painting, we'll do it right now, - // otherwise we'll just invalidate it. - BOOL needSyncRedraw = ([NSView focusView] != nil); - [self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:needSyncRedraw]; - } -} - -// Extending the content area into the title bar works by resizing the -// mainChildView so that it covers the titlebar. -- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState -{ - BOOL stateChanged = ([self drawsContentsIntoWindowFrame] != aState); - [super setDrawsContentsIntoWindowFrame:aState]; - if (stateChanged && [[self delegate] isKindOfClass:[WindowDelegate class]]) { - // Here we extend / shrink our mainChildView. We do that by firing a resize - // event which will cause the ChildView to be resized to the rect returned - // by nsCocoaWindow::GetClientBounds. GetClientBounds bases its return - // value on what we return from drawsContentsIntoWindowFrame. - WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate]; - nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget]; - if (geckoWindow) { - // Re-layout our contents. - geckoWindow->ReportSizeEvent(); - } - - // Resizing the content area causes a reflow which would send a synthesized - // mousemove event to the old mouse position relative to the top left - // corner of the content area. But the mouse has shifted relative to the - // content area, so that event would have wrong position information. So - // we'll send a mouse move event with the correct new position. - ChildViewMouseTracker::ResendLastMouseMoveEvent(); - } -} - -- (void)setWantsTitleDrawn:(BOOL)aDrawTitle -{ - [super setWantsTitleDrawn:aDrawTitle]; - [self setTitlebarNeedsDisplayInRect:[self titlebarRect]]; -} - -- (void)setSheetAttachmentPosition:(CGFloat)aY -{ - CGFloat topMargin = aY - [self titlebarHeight]; - [self setContentBorderThickness:topMargin forEdge:NSMaxYEdge]; -} - -- (void)placeWindowButtons:(NSRect)aRect -{ - if (!NSEqualRects(mWindowButtonsRect, aRect)) { - mWindowButtonsRect = aRect; - [self reflowTitlebarElements]; - } -} - -- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition -{ - NSInteger styleMask = [self styleMask]; - if ([self drawsContentsIntoWindowFrame] && - !(styleMask & NSFullScreenWindowMask) && (styleMask & NSTitledWindowMask)) { - if (NSIsEmptyRect(mWindowButtonsRect)) { - // Empty rect. Let's hide the buttons. - // Position is in non-flipped window coordinates. Using frame's height - // for the vertical coordinate will move the buttons above the window, - // making them invisible. - return NSMakePoint(0, [self frame].size.height); - } - return NSMakePoint(mWindowButtonsRect.origin.x, mWindowButtonsRect.origin.y); - } - return aDefaultPosition; -} - -- (void)placeFullScreenButton:(NSRect)aRect -{ - if (!NSEqualRects(mFullScreenButtonRect, aRect)) { - mFullScreenButtonRect = aRect; - [self reflowTitlebarElements]; - } -} - -- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition -{ - if ([self drawsContentsIntoWindowFrame] && !NSIsEmptyRect(mFullScreenButtonRect)) { - return NSMakePoint(std::min(mFullScreenButtonRect.origin.x, aDefaultPosition.x), - std::min(mFullScreenButtonRect.origin.y, aDefaultPosition.y)); - } - return aDefaultPosition; -} - -// Returning YES here makes the setShowsToolbarButton method work even though -// the window doesn't contain an NSToolbar. -- (BOOL)_hasToolbar -{ - return YES; -} - -// Dispatch a toolbar pill button clicked message to Gecko. -- (void)_toolbarPillButtonClicked:(id)sender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - RollUpPopups(); - - if ([[self delegate] isKindOfClass:[WindowDelegate class]]) { - WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate]; - nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget]; - if (!geckoWindow) - return; - - nsIWidgetListener* listener = geckoWindow->GetWidgetListener(); - if (listener) - listener->OSToolbarButtonPressed(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Retain and release "self" to avoid crashes when our widget (and its native -// window) is closed as a result of processing a key equivalent (e.g. -// Command+w or Command+q). This workaround is only needed for a window -// that can become key. -- (BOOL)performKeyEquivalent:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSWindow *nativeWindow = [self retain]; - BOOL retval = [super performKeyEquivalent:theEvent]; - [nativeWindow release]; - return retval; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -- (void)sendEvent:(NSEvent *)anEvent -{ - NSEventType type = [anEvent type]; - - switch (type) { - case NSScrollWheel: - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - { - // Drop all mouse events if a modal window has appeared above us. - // This helps make us behave as if the OS were running a "real" modal - // event loop. - id delegate = [self delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) { - nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget]; - if (widget) { - if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window)) - return; - if (widget->HasModalDescendents()) - return; - } - } - break; - } - default: - break; - } - - [super sendEvent:anEvent]; -} - -@end - -// Custom NSColor subclass where most of the work takes place for drawing in -// the titlebar area. Not used in drawsContentsIntoWindowFrame mode. -@implementation TitlebarAndBackgroundColor - -- (id)initWithWindow:(ToolbarWindow*)aWindow -{ - if ((self = [super init])) { - mWindow = aWindow; // weak ref to avoid a cycle - } - return self; -} - -static void -DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect, - CGFloat aUnifiedToolbarHeight, BOOL aIsMain) -{ - nsNativeThemeCocoa::DrawNativeTitlebar(aContext, aTitlebarRect, aUnifiedToolbarHeight, aIsMain, NO); - - // The call to CUIDraw doesn't draw the top pixel strip at some window widths. - // We don't want to have a flickering transparent line, so we overdraw it. - CGContextSetRGBFillColor(aContext, 0.95, 0.95, 0.95, 1); - CGContextFillRect(aContext, CGRectMake(0, CGRectGetMaxY(aTitlebarRect) - 1, - aTitlebarRect.size.width, 1)); -} - -// Pattern draw callback for standard titlebar gradients and solid titlebar colors -static void -TitlebarDrawCallback(void* aInfo, CGContextRef aContext) -{ - ToolbarWindow *window = (ToolbarWindow*)aInfo; - if (![window drawsContentsIntoWindowFrame]) { - NSRect titlebarRect = [window titlebarRect]; - BOOL isMain = [window isMainWindow]; - NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain]; - if (!titlebarColor) { - // If the titlebar color is nil, draw the default titlebar shading. - DrawNativeTitlebar(aContext, NSRectToCGRect(titlebarRect), - [window unifiedToolbarHeight], isMain); - } else { - // If the titlebar color is not nil, just set and draw it normally. - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:aContext flipped:NO]]; - [titlebarColor set]; - NSRectFill(titlebarRect); - [NSGraphicsContext restoreGraphicsState]; - } - } -} - -- (void)setFill -{ - float patternWidth = [mWindow frame].size.width; - - CGPatternCallbacks callbacks = {0, &TitlebarDrawCallback, NULL}; - CGPatternRef pattern = CGPatternCreate(mWindow, CGRectMake(0.0f, 0.0f, patternWidth, [mWindow frame].size.height), - CGAffineTransformIdentity, patternWidth, [mWindow frame].size.height, - kCGPatternTilingConstantSpacing, true, &callbacks); - - // Set the pattern as the fill, which is what we were asked to do. All our - // drawing will take place in the patternDraw callback. - CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); - CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextSetFillColorSpace(context, patternSpace); - CGColorSpaceRelease(patternSpace); - CGFloat component = 1.0f; - CGContextSetFillPattern(context, pattern, &component); - CGPatternRelease(pattern); -} - -- (void)set -{ - [self setFill]; -} - -- (NSString*)colorSpaceName -{ - return NSDeviceRGBColorSpace; -} - -@end - -@implementation PopupWindow - -- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask - backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - mIsContextMenu = false; - return [super initWithContentRect:contentRect styleMask:styleMask - backing:bufferingType defer:deferCreation]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL)isContextMenu -{ - return mIsContextMenu; -} - -- (void)setIsContextMenu:(BOOL)flag -{ - mIsContextMenu = flag; -} - -- (BOOL)canBecomeMainWindow -{ - // This is overriden because the default is 'yes' when a titlebar is present. - return NO; -} - -@end - -// According to Apple's docs on [NSWindow canBecomeKeyWindow] and [NSWindow -// canBecomeMainWindow], windows without a title bar or resize bar can't (by -// default) become key or main. But if a window can't become key, it can't -// accept keyboard input (bmo bug 393250). And it should also be possible for -// an otherwise "ordinary" window to become main. We need to override these -// two methods to make this happen. -@implementation BorderlessWindow - -- (BOOL)canBecomeKeyWindow -{ - return YES; -} - -- (void)sendEvent:(NSEvent *)anEvent -{ - NSEventType type = [anEvent type]; - - switch (type) { - case NSScrollWheel: - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - { - // Drop all mouse events if a modal window has appeared above us. - // This helps make us behave as if the OS were running a "real" modal - // event loop. - id delegate = [self delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) { - nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget]; - if (widget) { - if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window)) - return; - if (widget->HasModalDescendents()) - return; - } - } - break; - } - default: - break; - } - - [super sendEvent:anEvent]; -} - -// Apple's doc on this method says that the NSWindow class's default is not to -// become main if the window isn't "visible" -- so we should replicate that -// behavior here. As best I can tell, the [NSWindow isVisible] method is an -// accurate test of what Apple means by "visibility". -- (BOOL)canBecomeMainWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (![self isVisible]) - return NO; - return YES; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -// Retain and release "self" to avoid crashes when our widget (and its native -// window) is closed as a result of processing a key equivalent (e.g. -// Command+w or Command+q). This workaround is only needed for a window -// that can become key. -- (BOOL)performKeyEquivalent:(NSEvent*)theEvent -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - NSWindow *nativeWindow = [self retain]; - BOOL retval = [super performKeyEquivalent:theEvent]; - [nativeWindow release]; - return retval; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -@end diff --git a/widget/cocoa/nsColorPicker.h b/widget/cocoa/nsColorPicker.h deleted file mode 100644 index 4b3e262188..0000000000 --- a/widget/cocoa/nsColorPicker.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 nsColorPicker_h_ -#define nsColorPicker_h_ - -#include "nsIColorPicker.h" -#include "nsString.h" -#include "nsCOMPtr.h" - -class nsIColorPickerShownCallback; -class mozIDOMWindowProxy; -@class NSColorPanelWrapper; -@class NSColor; - -class nsColorPicker final : public nsIColorPicker -{ -public: - NS_DECL_ISUPPORTS - - NS_IMETHOD Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle, - const nsAString& aInitialColor) override; - NS_IMETHOD Open(nsIColorPickerShownCallback* aCallback) override; - - // For NSColorPanelWrapper. - void Update(NSColor* aColor); - // Call this method if you are done with this input, but the color picker needs to - // stay open as it will be associated to another input - void DoneWithRetarget(); - // Same as DoneWithRetarget + clean the static instance of sColorPanelWrapper, - // as it is not needed anymore for now - void Done(); - -private: - ~nsColorPicker(); - - static NSColor* GetNSColorFromHexString(const nsAString& aColor); - static void GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult); - - static NSColorPanelWrapper* sColorPanelWrapper; - - nsString mTitle; - nsString mColor; - nsCOMPtr mCallback; -}; - -#endif // nsColorPicker_h_ diff --git a/widget/cocoa/nsColorPicker.mm b/widget/cocoa/nsColorPicker.mm deleted file mode 100644 index 263ea349b0..0000000000 --- a/widget/cocoa/nsColorPicker.mm +++ /dev/null @@ -1,188 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#import - -#include "nsColorPicker.h" -#include "nsCocoaUtils.h" -#include "nsThreadUtils.h" - -using namespace mozilla; - -static unsigned int -HexStrToInt(NSString* str) -{ - unsigned int result = 0; - - for (unsigned int i = 0; i < [str length]; ++i) { - char c = [str characterAtIndex:i]; - result *= 16; - if (c >= '0' && c <= '9') { - result += c - '0'; - } else if (c >= 'A' && c <= 'F') { - result += 10 + (c - 'A'); - } else { - result += 10 + (c - 'a'); - } - } - - return result; -} - -@interface NSColorPanelWrapper : NSObject -{ - NSColorPanel* mColorPanel; - nsColorPicker* mColorPicker; -} -- (id)initWithPicker:(nsColorPicker*)aPicker; -- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle; -- (void)retarget:(nsColorPicker*)aPicker; -- (void)colorChanged:(NSColorPanel*)aPanel; -@end - -@implementation NSColorPanelWrapper -- (id)initWithPicker:(nsColorPicker*)aPicker -{ - mColorPicker = aPicker; - mColorPanel = [NSColorPanel sharedColorPanel]; - - self = [super init]; - return self; -} - -- (void)open:(NSColor*)aInitialColor title:(NSString*)aTitle -{ - [mColorPanel setTarget:self]; - [mColorPanel setAction:@selector(colorChanged:)]; - [mColorPanel setDelegate:self]; - [mColorPanel setTitle:aTitle]; - [mColorPanel setColor:aInitialColor]; - [mColorPanel makeKeyAndOrderFront:nil]; -} - -- (void)colorChanged:(NSColorPanel*)aPanel -{ - mColorPicker->Update([mColorPanel color]); -} - -- (void)windowWillClose:(NSNotification*)aNotification -{ - mColorPicker->Done(); -} - -- (void)retarget:(nsColorPicker*)aPicker -{ - mColorPicker->DoneWithRetarget(); - mColorPicker = aPicker; -} - -- (void)dealloc -{ - [mColorPanel setTarget:nil]; - [mColorPanel setAction:nil]; - [mColorPanel setDelegate:nil]; - - mColorPanel = nil; - mColorPicker = nullptr; - - [super dealloc]; -} -@end - -NS_IMPL_ISUPPORTS(nsColorPicker, nsIColorPicker) - -NSColorPanelWrapper* nsColorPicker::sColorPanelWrapper = nullptr; - -nsColorPicker::~nsColorPicker() -{ -} - -NS_IMETHODIMP -nsColorPicker::Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle, - const nsAString& aInitialColor) -{ - MOZ_ASSERT(NS_IsMainThread(), - "Color pickers can only be opened from main thread currently"); - mTitle = aTitle; - mColor = aInitialColor; - - if (sColorPanelWrapper) { - // Update current wrapper to target the new input instead - [sColorPanelWrapper retarget:this]; - } else { - // Create a brand new color panel wrapper - sColorPanelWrapper = [[NSColorPanelWrapper alloc] initWithPicker:this]; - } - return NS_OK; -} - -/* static */ NSColor* -nsColorPicker::GetNSColorFromHexString(const nsAString& aColor) -{ - NSString* str = nsCocoaUtils::ToNSString(aColor); - - double red = HexStrToInt([str substringWithRange:NSMakeRange(1, 2)]) / 255.0; - double green = HexStrToInt([str substringWithRange:NSMakeRange(3, 2)]) / 255.0; - double blue = HexStrToInt([str substringWithRange:NSMakeRange(5, 2)]) / 255.0; - - return [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1.0]; -} - -/* static */ void -nsColorPicker::GetHexStringFromNSColor(NSColor* aColor, nsAString& aResult) -{ - CGFloat redFloat, greenFloat, blueFloat; - - NSColor* color = aColor; - @try { - [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha: nil]; - } @catch (NSException* e) { - color = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; - [color getRed:&redFloat green:&greenFloat blue:&blueFloat alpha: nil]; - } - - nsCocoaUtils::GetStringForNSString([NSString stringWithFormat:@"#%02x%02x%02x", - (int)(redFloat * 255), - (int)(greenFloat * 255), - (int)(blueFloat * 255)], - aResult); -} - -NS_IMETHODIMP -nsColorPicker::Open(nsIColorPickerShownCallback* aCallback) -{ - MOZ_ASSERT(aCallback); - mCallback = aCallback; - - [sColorPanelWrapper open:GetNSColorFromHexString(mColor) - title:nsCocoaUtils::ToNSString(mTitle)]; - - NS_ADDREF_THIS(); - - return NS_OK; -} - -void -nsColorPicker::Update(NSColor* aColor) -{ - GetHexStringFromNSColor(aColor, mColor); - mCallback->Update(mColor); -} - -void -nsColorPicker::DoneWithRetarget() -{ - mCallback->Done(EmptyString()); - mCallback = nullptr; - NS_RELEASE_THIS(); -} - -void -nsColorPicker::Done() -{ - [sColorPanelWrapper release]; - sColorPanelWrapper = nullptr; - DoneWithRetarget(); -} diff --git a/widget/cocoa/nsCursorManager.h b/widget/cocoa/nsCursorManager.h deleted file mode 100644 index 6dba8f9034..0000000000 --- a/widget/cocoa/nsCursorManager.h +++ /dev/null @@ -1,65 +0,0 @@ -/* 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 nsCursorManager_h_ -#define nsCursorManager_h_ - -#import -#include "nsIWidget.h" -#include "nsMacCursor.h" - -/*! @class nsCursorManager - @abstract Singleton service provides access to all cursors available in the application. - @discussion Use nsCusorManager to set the current cursor using an XP nsCusor enum value. - nsCursorManager encapsulates the details of setting different types of cursors, animating - cursors and cleaning up cursors when they are no longer in use. - */ -@interface nsCursorManager : NSObject -{ - @private - NSMutableDictionary *mCursors; - nsMacCursor *mCurrentMacCursor; -} - -/*! @method setCursor: - @abstract Sets the current cursor. - @discussion Sets the current cursor to the cursor indicated by the XP cursor constant given as an argument. - Resources associated with the previous cursor are cleaned up. - @param aCursor the cursor to use -*/ -- (nsresult) setCursor: (nsCursor) aCursor; - -/*! @method setCursorWithImage:hotSpotX:hotSpotY: - @abstract Sets the current cursor to a custom image - @discussion Sets the current cursor to the cursor given by the aCursorImage argument. - Resources associated with the previous cursor are cleaned up. - @param aCursorImage the cursor image to use - @param aHotSpotX the x coordinate of the cursor's hotspot - @param aHotSpotY the y coordinate of the cursor's hotspot - @param scaleFactor the scale factor of the target display (2 for a retina display) - */ -- (nsresult) setCursorWithImage: (imgIContainer*) aCursorImage hotSpotX: (uint32_t) aHotspotX hotSpotY: (uint32_t) aHotspotY scaleFactor: (CGFloat) scaleFactor; - - -/*! @method sharedInstance - @abstract Get the Singleton instance of the cursor manager. - @discussion Use this method to obtain a reference to the cursor manager. - @result a reference to the cursor manager -*/ -+ (nsCursorManager *) sharedInstance; - -/*! @method dispose - @abstract Releases the shared instance of the cursor manager. - @discussion Use dispose to clean up the cursor manager and associated cursors. -*/ -+ (void) dispose; -@end - -@interface NSCursor (Undocumented) -// busyButClickableCursor is an undocumented NSCursor API, but has been in use since -// at least OS X 10.4 and through 10.9. -+ (NSCursor*)busyButClickableCursor; -@end - -#endif // nsCursorManager_h_ diff --git a/widget/cocoa/nsCursorManager.mm b/widget/cocoa/nsCursorManager.mm deleted file mode 100644 index c4281a438a..0000000000 --- a/widget/cocoa/nsCursorManager.mm +++ /dev/null @@ -1,308 +0,0 @@ -/* 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 "imgIContainer.h" -#include "nsCocoaUtils.h" -#include "nsCursorManager.h" -#include "nsObjCExceptions.h" -#include - -static nsCursorManager *gInstance; -static CGFloat sCursorScaleFactor = 0.0f; -static imgIContainer *sCursorImgContainer = nullptr; -static const nsCursor sCustomCursor = eCursorCount; - -/*! @category nsCursorManager(PrivateMethods) - Private methods for the cursor manager class. -*/ -@interface nsCursorManager(PrivateMethods) -/*! @method getCursor: - @abstract Get a reference to the native Mac representation of a cursor. - @discussion Gets a reference to the Mac native implementation of a cursor. - If the cursor has been requested before, it is retreived from the cursor cache, - otherwise it is created and cached. - @param aCursor the cursor to get - @result the Mac native implementation of the cursor -*/ -- (nsMacCursor *) getCursor: (nsCursor) aCursor; - -/*! @method setMacCursor: - @abstract Set the current Mac native cursor - @discussion Sets the current cursor - this routine is what actually causes the cursor to change. - The argument is retained and the old cursor is released. - @param aMacCursor the cursor to set - @result NS_OK - */ -- (nsresult) setMacCursor: (nsMacCursor*) aMacCursor; - -/*! @method createCursor: - @abstract Create a Mac native representation of a cursor. - @discussion Creates a version of the Mac native representation of this cursor - @param aCursor the cursor to create - @result the Mac native implementation of the cursor -*/ -+ (nsMacCursor *) createCursor: (enum nsCursor) aCursor; - -@end - -@implementation nsCursorManager - -+ (nsCursorManager *) sharedInstance -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!gInstance) { - gInstance = [[nsCursorManager alloc] init]; - } - return gInstance; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (void) dispose -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [gInstance release]; - gInstance = nil; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -+ (nsMacCursor *) createCursor: (enum nsCursor) aCursor -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - switch(aCursor) - { - SEL cursorSelector; - case eCursor_standard: - return [nsMacCursor cursorWithCursor:[NSCursor arrowCursor] type:aCursor]; - case eCursor_wait: - case eCursor_spinning: - { - return [nsMacCursor cursorWithCursor:[NSCursor busyButClickableCursor] type:aCursor]; - } - case eCursor_select: - return [nsMacCursor cursorWithCursor:[NSCursor IBeamCursor] type:aCursor]; - case eCursor_hyperlink: - return [nsMacCursor cursorWithCursor:[NSCursor pointingHandCursor] type:aCursor]; - case eCursor_crosshair: - return [nsMacCursor cursorWithCursor:[NSCursor crosshairCursor] type:aCursor]; - case eCursor_move: - return [nsMacCursor cursorWithImageNamed:@"move" hotSpot:NSMakePoint(12,12) type:aCursor]; - case eCursor_help: - return [nsMacCursor cursorWithImageNamed:@"help" hotSpot:NSMakePoint(12,12) type:aCursor]; - case eCursor_copy: - cursorSelector = @selector(dragCopyCursor); - return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ? - [NSCursor performSelector:cursorSelector] : - [NSCursor arrowCursor] type:aCursor]; - case eCursor_alias: - cursorSelector = @selector(dragLinkCursor); - return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ? - [NSCursor performSelector:cursorSelector] : - [NSCursor arrowCursor] type:aCursor]; - case eCursor_context_menu: - cursorSelector = @selector(contextualMenuCursor); - return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ? - [NSCursor performSelector:cursorSelector] : - [NSCursor arrowCursor] type:aCursor]; - case eCursor_cell: - return [nsMacCursor cursorWithImageNamed:@"cell" hotSpot:NSMakePoint(12,12) type:aCursor]; - case eCursor_grab: - return [nsMacCursor cursorWithCursor:[NSCursor openHandCursor] type:aCursor]; - case eCursor_grabbing: - return [nsMacCursor cursorWithCursor:[NSCursor closedHandCursor] type:aCursor]; - case eCursor_zoom_in: - return [nsMacCursor cursorWithImageNamed:@"zoomIn" hotSpot:NSMakePoint(10,10) type:aCursor]; - case eCursor_zoom_out: - return [nsMacCursor cursorWithImageNamed:@"zoomOut" hotSpot:NSMakePoint(10,10) type:aCursor]; - case eCursor_vertical_text: - return [nsMacCursor cursorWithImageNamed:@"vtIBeam" hotSpot:NSMakePoint(12,11) type:aCursor]; - case eCursor_all_scroll: - return [nsMacCursor cursorWithCursor:[NSCursor openHandCursor] type:aCursor]; - case eCursor_not_allowed: - case eCursor_no_drop: - cursorSelector = @selector(operationNotAllowedCursor); - return [nsMacCursor cursorWithCursor:[NSCursor respondsToSelector:cursorSelector] ? - [NSCursor performSelector:cursorSelector] : - [NSCursor arrowCursor] type:aCursor]; - // Resize Cursors: - // North - case eCursor_n_resize: - return [nsMacCursor cursorWithCursor:[NSCursor resizeUpCursor] type:aCursor]; - // North East - case eCursor_ne_resize: - return [nsMacCursor cursorWithImageNamed:@"sizeNE" hotSpot:NSMakePoint(12,11) type:aCursor]; - // East - case eCursor_e_resize: - return [nsMacCursor cursorWithCursor:[NSCursor resizeRightCursor] type:aCursor]; - // South East - case eCursor_se_resize: - return [nsMacCursor cursorWithImageNamed:@"sizeSE" hotSpot:NSMakePoint(12,12) type:aCursor]; - // South - case eCursor_s_resize: - return [nsMacCursor cursorWithCursor:[NSCursor resizeDownCursor] type:aCursor]; - // South West - case eCursor_sw_resize: - return [nsMacCursor cursorWithImageNamed:@"sizeSW" hotSpot:NSMakePoint(10,12) type:aCursor]; - // West - case eCursor_w_resize: - return [nsMacCursor cursorWithCursor:[NSCursor resizeLeftCursor] type:aCursor]; - // North West - case eCursor_nw_resize: - return [nsMacCursor cursorWithImageNamed:@"sizeNW" hotSpot:NSMakePoint(11,11) type:aCursor]; - // North & South - case eCursor_ns_resize: - return [nsMacCursor cursorWithCursor:[NSCursor resizeUpDownCursor] type:aCursor]; - // East & West - case eCursor_ew_resize: - return [nsMacCursor cursorWithCursor:[NSCursor resizeLeftRightCursor] type:aCursor]; - // North East & South West - case eCursor_nesw_resize: - return [nsMacCursor cursorWithImageNamed:@"sizeNESW" hotSpot:NSMakePoint(12,12) type:aCursor]; - // North West & South East - case eCursor_nwse_resize: - return [nsMacCursor cursorWithImageNamed:@"sizeNWSE" hotSpot:NSMakePoint(12,12) type:aCursor]; - // Column Resize - case eCursor_col_resize: - return [nsMacCursor cursorWithImageNamed:@"colResize" hotSpot:NSMakePoint(12,12) type:aCursor]; - // Row Resize - case eCursor_row_resize: - return [nsMacCursor cursorWithImageNamed:@"rowResize" hotSpot:NSMakePoint(12,12) type:aCursor]; - default: - return [nsMacCursor cursorWithCursor:[NSCursor arrowCursor] type:aCursor]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id) init -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - mCursors = [[NSMutableDictionary alloc] initWithCapacity:25]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (nsresult) setCursor: (enum nsCursor) aCursor -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Some plugins mess with our cursors and set a cursor that even - // [NSCursor currentCursor] doesn't know about. In case that happens, just - // reset the state. - [[NSCursor currentCursor] set]; - - nsCursor oldType = [mCurrentMacCursor type]; - if (oldType != aCursor) { - if (aCursor == eCursor_none) { - [NSCursor hide]; - } else if (oldType == eCursor_none) { - [NSCursor unhide]; - } - } - [self setMacCursor:[self getCursor:aCursor]]; - - // if a custom cursor was previously set, release sCursorImgContainer - if (oldType == sCustomCursor) { - NS_IF_RELEASE(sCursorImgContainer); - } - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -- (nsresult) setMacCursor: (nsMacCursor*) aMacCursor -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mCurrentMacCursor != aMacCursor || ![mCurrentMacCursor isSet]) { - [aMacCursor retain]; - [mCurrentMacCursor unset]; - [aMacCursor set]; - [mCurrentMacCursor release]; - mCurrentMacCursor = aMacCursor; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -- (nsresult) setCursorWithImage: (imgIContainer*) aCursorImage hotSpotX: (uint32_t) aHotspotX hotSpotY: (uint32_t) aHotspotY scaleFactor: (CGFloat) scaleFactor -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - // As the user moves the mouse, this gets called repeatedly with the same aCursorImage - if (sCursorImgContainer == aCursorImage && sCursorScaleFactor == scaleFactor && mCurrentMacCursor) { - [self setMacCursor:mCurrentMacCursor]; - return NS_OK; - } - - [[NSCursor currentCursor] set]; - int32_t width = 0, height = 0; - aCursorImage->GetWidth(&width); - aCursorImage->GetHeight(&height); - // prevent DoS attacks - if (width > 128 || height > 128) { - return NS_OK; - } - - NSImage *cursorImage; - nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer(aCursorImage, imgIContainer::FRAME_FIRST, &cursorImage, scaleFactor); - if (NS_FAILED(rv) || !cursorImage) { - return NS_ERROR_FAILURE; - } - - // if the hotspot is nonsensical, make it 0,0 - aHotspotX = (aHotspotX > (uint32_t)width - 1) ? 0 : aHotspotX; - aHotspotY = (aHotspotY > (uint32_t)height - 1) ? 0 : aHotspotY; - - NSPoint hotSpot = ::NSMakePoint(aHotspotX, aHotspotY); - [self setMacCursor:[nsMacCursor cursorWithCursor:[[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpot] type:sCustomCursor]]; - [cursorImage release]; - - NS_IF_RELEASE(sCursorImgContainer); - sCursorImgContainer = aCursorImage; - sCursorScaleFactor = scaleFactor; - NS_ADDREF(sCursorImgContainer); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -- (nsMacCursor *) getCursor: (enum nsCursor) aCursor -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsMacCursor * result = [mCursors objectForKey:[NSNumber numberWithInt:aCursor]]; - if (!result) { - result = [nsCursorManager createCursor:aCursor]; - [mCursors setObject:result forKey:[NSNumber numberWithInt:aCursor]]; - } - return result; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void) dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mCurrentMacCursor unset]; - [mCurrentMacCursor release]; - [mCursors release]; - NS_IF_RELEASE(sCursorImgContainer); - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end diff --git a/widget/cocoa/nsDeviceContextSpecX.h b/widget/cocoa/nsDeviceContextSpecX.h deleted file mode 100644 index 2df52418a7..0000000000 --- a/widget/cocoa/nsDeviceContextSpecX.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 nsDeviceContextSpecX_h_ -#define nsDeviceContextSpecX_h_ - -#include "nsIDeviceContextSpec.h" - -#include - -class nsDeviceContextSpecX : public nsIDeviceContextSpec -{ -public: - NS_DECL_ISUPPORTS - - nsDeviceContextSpecX(); - - NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override; - virtual already_AddRefed MakePrintTarget() final; - NS_IMETHOD BeginDocument(const nsAString& aTitle, - const nsAString& aPrintToFileName, - int32_t aStartPage, - int32_t aEndPage) override; - NS_IMETHOD EndDocument() override; - NS_IMETHOD BeginPage() override; - NS_IMETHOD EndPage() override; - - void GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight); - -protected: - virtual ~nsDeviceContextSpecX(); - -protected: - PMPrintSession mPrintSession; // printing context. - PMPageFormat mPageFormat; // page format. - PMPrintSettings mPrintSettings; // print settings. -}; - -#endif //nsDeviceContextSpecX_h_ diff --git a/widget/cocoa/nsDeviceContextSpecX.mm b/widget/cocoa/nsDeviceContextSpecX.mm deleted file mode 100644 index d252adef69..0000000000 --- a/widget/cocoa/nsDeviceContextSpecX.mm +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 "nsDeviceContextSpecX.h" - -#include "mozilla/gfx/PrintTargetCG.h" -#include "mozilla/RefPtr.h" -#include "nsCRT.h" -#include - -#include "nsQueryObject.h" -#include "nsIServiceManager.h" -#include "nsPrintSettingsX.h" - -// This must be the last include: -#include "nsObjCExceptions.h" - -using namespace mozilla; -using namespace mozilla::gfx; - -nsDeviceContextSpecX::nsDeviceContextSpecX() -: mPrintSession(NULL) -, mPageFormat(kPMNoPageFormat) -, mPrintSettings(kPMNoPrintSettings) -{ -} - -nsDeviceContextSpecX::~nsDeviceContextSpecX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mPrintSession) - ::PMRelease(mPrintSession); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMPL_ISUPPORTS(nsDeviceContextSpecX, nsIDeviceContextSpec) - -NS_IMETHODIMP nsDeviceContextSpecX::Init(nsIWidget *aWidget, - nsIPrintSettings* aPS, - bool aIsPrintPreview) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - RefPtr settings(do_QueryObject(aPS)); - if (!settings) - return NS_ERROR_NO_INTERFACE; - - mPrintSession = settings->GetPMPrintSession(); - ::PMRetain(mPrintSession); - mPageFormat = settings->GetPMPageFormat(); - mPrintSettings = settings->GetPMPrintSettings(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(const nsAString& aTitle, - const nsAString& aPrintToFileName, - int32_t aStartPage, - int32_t aEndPage) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!aTitle.IsEmpty()) { - CFStringRef cfString = - ::CFStringCreateWithCharacters(NULL, reinterpret_cast(aTitle.BeginReading()), - aTitle.Length()); - if (cfString) { - ::PMPrintSettingsSetJobName(mPrintSettings, cfString); - ::CFRelease(cfString); - } - } - - OSStatus status; - status = ::PMSetFirstPage(mPrintSettings, aStartPage, false); - NS_ASSERTION(status == noErr, "PMSetFirstPage failed"); - status = ::PMSetLastPage(mPrintSettings, aEndPage, false); - NS_ASSERTION(status == noErr, "PMSetLastPage failed"); - - status = ::PMSessionBeginCGDocumentNoDialog(mPrintSession, mPrintSettings, mPageFormat); - if (status != noErr) - return NS_ERROR_ABORT; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsDeviceContextSpecX::EndDocument() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - ::PMSessionEndDocumentNoDialog(mPrintSession); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsDeviceContextSpecX::BeginPage() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMSessionError(mPrintSession); - OSStatus status = ::PMSessionBeginPageNoDialog(mPrintSession, mPageFormat, NULL); - if (status != noErr) return NS_ERROR_ABORT; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsDeviceContextSpecX::EndPage() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - OSStatus status = ::PMSessionEndPageNoDialog(mPrintSession); - if (status != noErr) return NS_ERROR_ABORT; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsDeviceContextSpecX::GetPaperRect(double* aTop, double* aLeft, double* aBottom, double* aRight) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - PMRect paperRect; - ::PMGetAdjustedPaperRect(mPageFormat, &paperRect); - - *aTop = paperRect.top, *aLeft = paperRect.left; - *aBottom = paperRect.bottom, *aRight = paperRect.right; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -already_AddRefed nsDeviceContextSpecX::MakePrintTarget() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - double top, left, bottom, right; - GetPaperRect(&top, &left, &bottom, &right); - const double width = right - left; - const double height = bottom - top; - IntSize size = IntSize::Floor(width, height); - - CGContextRef context; - ::PMSessionGetCGGraphicsContext(mPrintSession, &context); - - if (context) { - // Initially, origin is at bottom-left corner of the paper. - // Here, we translate it to top-left corner of the paper. - CGContextTranslateCTM(context, 0, height); - CGContextScaleCTM(context, 1.0, -1.0); - return PrintTargetCG::CreateOrNull(context, size); - } - - // Apparently we do need this branch - bug 368933. - return PrintTargetCG::CreateOrNull(size, SurfaceFormat::A8R8G8B8_UINT32); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL; -} diff --git a/widget/cocoa/nsDragService.h b/widget/cocoa/nsDragService.h deleted file mode 100644 index ea6702812a..0000000000 --- a/widget/cocoa/nsDragService.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsDragService_h_ -#define nsDragService_h_ - -#include "nsBaseDragService.h" - -#include - -extern NSString* const kWildcardPboardType; -extern NSString* const kCorePboardType_url; -extern NSString* const kCorePboardType_urld; -extern NSString* const kCorePboardType_urln; -extern NSString* const kCustomTypesPboardType; - -class nsDragService : public nsBaseDragService -{ -public: - nsDragService(); - - // nsBaseDragService - virtual nsresult InvokeDragSessionImpl(nsIArray* anArrayTransferables, - nsIScriptableRegion* aRegion, - uint32_t aActionType); - // nsIDragService - NS_IMETHOD EndDragSession(bool aDoneDrag); - - // nsIDragSession - NS_IMETHOD GetData(nsITransferable * aTransferable, uint32_t aItemIndex); - NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, bool *_retval); - NS_IMETHOD GetNumDropItems(uint32_t * aNumItems); - -protected: - virtual ~nsDragService(); - -private: - - NSImage* ConstructDragImage(nsIDOMNode* aDOMNode, - mozilla::LayoutDeviceIntRect* aDragRect, - nsIScriptableRegion* aRegion); - bool IsValidType(NSString* availableType, bool allowFileURL); - NSString* GetStringForType(NSPasteboardItem* item, const NSString* type, - bool allowFileURL = false); - NSString* GetTitleForURL(NSPasteboardItem* item); - NSString* GetFilePath(NSPasteboardItem* item); - - nsCOMPtr mDataItems; // only valid for a drag started within gecko - NSView* mNativeDragView; - NSEvent* mNativeDragEvent; -}; - -#endif // nsDragService_h_ diff --git a/widget/cocoa/nsDragService.mm b/widget/cocoa/nsDragService.mm deleted file mode 100644 index c4d8e6ff06..0000000000 --- a/widget/cocoa/nsDragService.mm +++ /dev/null @@ -1,669 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsArrayUtils.h" -#include "nsDragService.h" -#include "nsArrayUtils.h" -#include "nsObjCExceptions.h" -#include "nsITransferable.h" -#include "nsString.h" -#include "nsClipboard.h" -#include "nsXPCOM.h" -#include "nsISupportsPrimitives.h" -#include "nsCOMPtr.h" -#include "nsPrimitiveHelpers.h" -#include "nsLinebreakConverter.h" -#include "nsIMacUtils.h" -#include "nsIDOMNode.h" -#include "nsRect.h" -#include "nsPoint.h" -#include "nsIIOService.h" -#include "nsIDocument.h" -#include "nsIContent.h" -#include "nsView.h" -#include "gfxContext.h" -#include "nsCocoaUtils.h" -#include "mozilla/gfx/2D.h" -#include "gfxPlatform.h" - -using namespace mozilla; -using namespace mozilla::gfx; - -extern PRLogModuleInfo* sCocoaLog; - -extern void EnsureLogInitialized(); - -extern NSPasteboard* globalDragPboard; -extern NSView* gLastDragView; -extern NSEvent* gLastDragMouseDownEvent; -extern bool gUserCancelledDrag; - -// This global makes the transferable array available to Cocoa's promised -// file destination callback. -nsIArray *gDraggedTransferables = nullptr; - -NSString* const kWildcardPboardType = @"MozillaWildcard"; -NSString* const kCorePboardType_url = @"CorePasteboardFlavorType 0x75726C20"; // 'url ' url -NSString* const kCorePboardType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld' desc -NSString* const kCorePboardType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln' title -NSString* const kUTTypeURLName = @"public.url-name"; -NSString* const kCustomTypesPboardType = @"org.mozilla.custom-clipdata"; - -nsDragService::nsDragService() -{ - mNativeDragView = nil; - mNativeDragEvent = nil; - - EnsureLogInitialized(); -} - -nsDragService::~nsDragService() -{ -} - -static nsresult SetUpDragClipboard(nsIArray* aTransferableArray) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!aTransferableArray) - return NS_ERROR_FAILURE; - - uint32_t count = 0; - aTransferableArray->GetLength(&count); - - NSPasteboard* dragPBoard = [NSPasteboard pasteboardWithName:NSDragPboard]; - - for (uint32_t j = 0; j < count; j++) { - nsCOMPtr currentTransferable = do_QueryElementAt(aTransferableArray, j); - if (!currentTransferable) - return NS_ERROR_FAILURE; - - // Transform the transferable to an NSDictionary - NSDictionary* pasteboardOutputDict = nsClipboard::PasteboardDictFromTransferable(currentTransferable); - if (!pasteboardOutputDict) - return NS_ERROR_FAILURE; - - // write everything out to the general pasteboard - unsigned int typeCount = [pasteboardOutputDict count]; - NSMutableArray* types = [NSMutableArray arrayWithCapacity:typeCount + 1]; - [types addObjectsFromArray:[pasteboardOutputDict allKeys]]; - // Gecko is initiating this drag so we always want its own views to consider - // it. Add our wildcard type to the pasteboard to accomplish this. - [types addObject:kWildcardPboardType]; // we don't increase the count for the loop below on purpose - [dragPBoard declareTypes:types owner:nil]; - for (unsigned int k = 0; k < typeCount; k++) { - NSString* currentKey = [types objectAtIndex:k]; - id currentValue = [pasteboardOutputDict valueForKey:currentKey]; - if (currentKey == NSStringPboardType || - currentKey == kCorePboardType_url || - currentKey == kCorePboardType_urld || - currentKey == kCorePboardType_urln) { - [dragPBoard setString:currentValue forType:currentKey]; - } - else if (currentKey == NSHTMLPboardType) { - [dragPBoard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue)) - forType:currentKey]; - } - else if (currentKey == NSTIFFPboardType || - currentKey == kCustomTypesPboardType) { - [dragPBoard setData:currentValue forType:currentKey]; - } - else if (currentKey == NSFilesPromisePboardType || - currentKey == NSFilenamesPboardType) { - [dragPBoard setPropertyList:currentValue forType:currentKey]; - } - } - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NSImage* -nsDragService::ConstructDragImage(nsIDOMNode* aDOMNode, - LayoutDeviceIntRect* aDragRect, - nsIScriptableRegion* aRegion) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView); - - RefPtr surface; - nsPresContext* pc; - nsresult rv = DrawDrag(aDOMNode, aRegion, mScreenPosition, - aDragRect, &surface, &pc); - if (pc && (!aDragRect->width || !aDragRect->height)) { - // just use some suitable defaults - int32_t size = nsCocoaUtils::CocoaPointsToDevPixels(20, scaleFactor); - aDragRect->SetRect(pc->CSSPixelsToDevPixels(mScreenPosition.x), - pc->CSSPixelsToDevPixels(mScreenPosition.y), size, size); - } - - if (NS_FAILED(rv) || !surface) - return nil; - - uint32_t width = aDragRect->width; - uint32_t height = aDragRect->height; - - RefPtr dataSurface = - Factory::CreateDataSourceSurface(IntSize(width, height), - SurfaceFormat::B8G8R8A8); - DataSourceSurface::MappedSurface map; - if (!dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map)) { - return nil; - } - - RefPtr dt = - Factory::CreateDrawTargetForData(BackendType::CAIRO, - map.mData, - dataSurface->GetSize(), - map.mStride, - dataSurface->GetFormat()); - if (!dt) { - dataSurface->Unmap(); - return nil; - } - - dt->FillRect(gfx::Rect(0, 0, width, height), - SurfacePattern(surface, ExtendMode::CLAMP), - DrawOptions(1.0f, CompositionOp::OP_SOURCE)); - - NSBitmapImageRep* imageRep = - [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:width * 4 - bitsPerPixel:32]; - - uint8_t* dest = [imageRep bitmapData]; - for (uint32_t i = 0; i < height; ++i) { - uint8_t* src = map.mData + i * map.mStride; - for (uint32_t j = 0; j < width; ++j) { - // Reduce transparency overall by multipying by a factor. Remember, Alpha - // is premultipled here. Also, Quartz likes RGBA, so do that translation as well. -#ifdef IS_BIG_ENDIAN - dest[0] = uint8_t(src[1] * DRAG_TRANSLUCENCY); - dest[1] = uint8_t(src[2] * DRAG_TRANSLUCENCY); - dest[2] = uint8_t(src[3] * DRAG_TRANSLUCENCY); - dest[3] = uint8_t(src[0] * DRAG_TRANSLUCENCY); -#else - dest[0] = uint8_t(src[2] * DRAG_TRANSLUCENCY); - dest[1] = uint8_t(src[1] * DRAG_TRANSLUCENCY); - dest[2] = uint8_t(src[0] * DRAG_TRANSLUCENCY); - dest[3] = uint8_t(src[3] * DRAG_TRANSLUCENCY); -#endif - src += 4; - dest += 4; - } - } - dataSurface->Unmap(); - - NSImage* image = - [[NSImage alloc] initWithSize:NSMakeSize(width / scaleFactor, - height / scaleFactor)]; - [image addRepresentation:imageRep]; - [imageRep release]; - - return [image autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -bool -nsDragService::IsValidType(NSString* availableType, bool allowFileURL) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - // Prevent exposing fileURL for non-fileURL type. - // We need URL provided by dropped webloc file, but don't need file's URL. - // kUTTypeFileURL is returned by [NSPasteboard availableTypeFromArray:] for - // kUTTypeURL, since it conforms to kUTTypeURL. - if (!allowFileURL && [availableType isEqualToString:(id)kUTTypeFileURL]) { - return false; - } - - return true; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -NSString* -nsDragService::GetStringForType(NSPasteboardItem* item, const NSString* type, - bool allowFileURL) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSString* availableType = [item availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]]; - if (availableType && IsValidType(availableType, allowFileURL)) { - return [item stringForType:(id)availableType]; - } - - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -NSString* -nsDragService::GetTitleForURL(NSPasteboardItem* item) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSString* name = GetStringForType(item, (const NSString*)kUTTypeURLName); - if (name) { - return name; - } - - NSString* filePath = GetFilePath(item); - if (filePath) { - return [filePath lastPathComponent]; - } - - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -NSString* -nsDragService::GetFilePath(NSPasteboardItem* item) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSString* urlString = GetStringForType(item, (const NSString*)kUTTypeFileURL, true); - if (urlString) { - NSURL* url = [NSURL URLWithString:urlString]; - if (url) { - return [url path]; - } - } - - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// We can only invoke NSView's 'dragImage:at:offset:event:pasteboard:source:slideBack:' from -// within NSView's 'mouseDown:' or 'mouseDragged:'. Luckily 'mouseDragged' is always on the -// stack when InvokeDragSession gets called. -nsresult -nsDragService::InvokeDragSessionImpl(nsIArray* aTransferableArray, - nsIScriptableRegion* aDragRgn, - uint32_t aActionType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mDataItems = aTransferableArray; - - // put data on the clipboard - if (NS_FAILED(SetUpDragClipboard(aTransferableArray))) - return NS_ERROR_FAILURE; - - CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(gLastDragView); - - LayoutDeviceIntRect dragRect(0, 0, 20, 20); - NSImage* image = ConstructDragImage(mSourceNode, &dragRect, aDragRgn); - if (!image) { - // if no image was returned, just draw a rectangle - NSSize size; - size.width = nsCocoaUtils::DevPixelsToCocoaPoints(dragRect.width, scaleFactor); - size.height = nsCocoaUtils::DevPixelsToCocoaPoints(dragRect.height, scaleFactor); - image = [[NSImage alloc] initWithSize:size]; - [image lockFocus]; - [[NSColor grayColor] set]; - NSBezierPath* path = [NSBezierPath bezierPath]; - [path setLineWidth:2.0]; - [path moveToPoint:NSMakePoint(0, 0)]; - [path lineToPoint:NSMakePoint(0, size.height)]; - [path lineToPoint:NSMakePoint(size.width, size.height)]; - [path lineToPoint:NSMakePoint(size.width, 0)]; - [path lineToPoint:NSMakePoint(0, 0)]; - [path stroke]; - [image unlockFocus]; - } - - LayoutDeviceIntPoint pt(dragRect.x, dragRect.YMost()); - NSPoint point = nsCocoaUtils::DevPixelsToCocoaPoints(pt, scaleFactor); - point.y = nsCocoaUtils::FlippedScreenY(point.y); - - point = nsCocoaUtils::ConvertPointFromScreen([gLastDragView window], point); - NSPoint localPoint = [gLastDragView convertPoint:point fromView:nil]; - - // Save the transferables away in case a promised file callback is invoked. - gDraggedTransferables = aTransferableArray; - - nsBaseDragService::StartDragSession(); - nsBaseDragService::OpenDragPopup(); - - // We need to retain the view and the event during the drag in case either gets destroyed. - mNativeDragView = [gLastDragView retain]; - mNativeDragEvent = [gLastDragMouseDownEvent retain]; - - gUserCancelledDrag = false; - [mNativeDragView dragImage:image - at:localPoint - offset:NSZeroSize - event:mNativeDragEvent - pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard] - source:mNativeDragView - slideBack:YES]; - gUserCancelledDrag = false; - - if (mDoingDrag) - nsBaseDragService::EndDragSession(false); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsDragService::GetData(nsITransferable* aTransferable, uint32_t aItemIndex) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!aTransferable) - return NS_ERROR_FAILURE; - - // get flavor list that includes all acceptable flavors (including ones obtained through conversion) - nsCOMPtr flavorList; - nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; - - uint32_t acceptableFlavorCount; - flavorList->GetLength(&acceptableFlavorCount); - - // if this drag originated within Mozilla we should just use the cached data from - // when the drag started if possible - if (mDataItems) { - nsCOMPtr currentTransferable = do_QueryElementAt(mDataItems, aItemIndex); - if (currentTransferable) { - for (uint32_t i = 0; i < acceptableFlavorCount; i++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - - nsCOMPtr dataSupports; - uint32_t dataSize = 0; - rv = currentTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize); - if (NS_SUCCEEDED(rv)) { - aTransferable->SetTransferData(flavorStr, dataSupports, dataSize); - return NS_OK; // maybe try to fill in more types? Is there a point? - } - } - } - } - - // now check the actual clipboard for data - for (uint32_t i = 0; i < acceptableFlavorCount; i++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, i); - if (!currentFlavor) - continue; - - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - - MOZ_LOG(sCocoaLog, LogLevel::Info, ("nsDragService::GetData: looking for clipboard data of type %s\n", flavorStr.get())); - - NSArray* droppedItems = [globalDragPboard pasteboardItems]; - if (!droppedItems) { - continue; - } - - uint32_t itemCount = [droppedItems count]; - if (aItemIndex >= itemCount) { - continue; - } - - NSPasteboardItem* item = [droppedItems objectAtIndex:aItemIndex]; - if (!item) { - continue; - } - - if (flavorStr.EqualsLiteral(kFileMime)) { - NSString* filePath = GetFilePath(item); - if (!filePath) - continue; - - unsigned int stringLength = [filePath length]; - unsigned int dataLength = (stringLength + 1) * sizeof(char16_t); // in bytes - char16_t* clipboardDataPtr = (char16_t*)malloc(dataLength); - if (!clipboardDataPtr) - return NS_ERROR_OUT_OF_MEMORY; - [filePath getCharacters:reinterpret_cast(clipboardDataPtr)]; - clipboardDataPtr[stringLength] = 0; // null terminate - - nsCOMPtr file; - rv = NS_NewLocalFile(nsDependentString(clipboardDataPtr), true, getter_AddRefs(file)); - free(clipboardDataPtr); - if (NS_FAILED(rv)) - continue; - - aTransferable->SetTransferData(flavorStr, file, dataLength); - - break; - } - else if (flavorStr.EqualsLiteral(kCustomTypesMime)) { - NSString* availableType = [item availableTypeFromArray:[NSArray arrayWithObject:kCustomTypesPboardType]]; - if (!availableType || !IsValidType(availableType, false)) { - continue; - } - NSData *pasteboardData = [item dataForType:availableType]; - if (!pasteboardData) { - continue; - } - - unsigned int dataLength = [pasteboardData length]; - void* clipboardDataPtr = malloc(dataLength); - if (!clipboardDataPtr) { - return NS_ERROR_OUT_OF_MEMORY; - } - [pasteboardData getBytes:clipboardDataPtr]; - - nsCOMPtr genericDataWrapper; - nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtr, dataLength, - getter_AddRefs(genericDataWrapper)); - - aTransferable->SetTransferData(flavorStr, genericDataWrapper, sizeof(nsIInputStream*)); - free(clipboardDataPtr); - break; - } - - NSString* pString = nil; - if (flavorStr.EqualsLiteral(kUnicodeMime)) { - pString = GetStringForType(item, (const NSString*)kUTTypeUTF8PlainText); - } else if (flavorStr.EqualsLiteral(kHTMLMime)) { - pString = GetStringForType(item, (const NSString*)kUTTypeHTML); - } else if (flavorStr.EqualsLiteral(kURLMime)) { - pString = GetStringForType(item, (const NSString*)kUTTypeURL); - if (pString) { - NSString* title = GetTitleForURL(item); - if (!title) { - title = pString; - } - pString = [NSString stringWithFormat:@"%@\n%@", pString, title]; - } - } else if (flavorStr.EqualsLiteral(kURLDataMime)) { - pString = GetStringForType(item, (const NSString*)kUTTypeURL); - } else if (flavorStr.EqualsLiteral(kURLDescriptionMime)) { - pString = GetTitleForURL(item); - } else if (flavorStr.EqualsLiteral(kRTFMime)) { - pString = GetStringForType(item, (const NSString*)kUTTypeRTF); - } - if (pString) { - NSData* stringData; - if (flavorStr.EqualsLiteral(kRTFMime)) { - stringData = [pString dataUsingEncoding:NSASCIIStringEncoding]; - } else { - stringData = [pString dataUsingEncoding:NSUnicodeStringEncoding]; - } - unsigned int dataLength = [stringData length]; - void* clipboardDataPtr = malloc(dataLength); - if (!clipboardDataPtr) - return NS_ERROR_OUT_OF_MEMORY; - [stringData getBytes:clipboardDataPtr]; - - // The DOM only wants LF, so convert from MacOS line endings to DOM line endings. - int32_t signedDataLength = dataLength; - nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(flavorStr, &clipboardDataPtr, &signedDataLength); - dataLength = signedDataLength; - - // skip BOM (Byte Order Mark to distinguish little or big endian) - char16_t* clipboardDataPtrNoBOM = (char16_t*)clipboardDataPtr; - if ((dataLength > 2) && - ((clipboardDataPtrNoBOM[0] == 0xFEFF) || - (clipboardDataPtrNoBOM[0] == 0xFFFE))) { - dataLength -= sizeof(char16_t); - clipboardDataPtrNoBOM += 1; - } - - nsCOMPtr genericDataWrapper; - nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, clipboardDataPtrNoBOM, dataLength, - getter_AddRefs(genericDataWrapper)); - aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLength); - free(clipboardDataPtr); - break; - } - - // We have never supported this on Mac OS X, we should someday. Normally dragging images - // in is accomplished with a file path drag instead of the image data itself. - /* - if (flavorStr.EqualsLiteral(kPNGImageMime) || flavorStr.EqualsLiteral(kJPEGImageMime) || - flavorStr.EqualsLiteral(kJPGImageMime) || flavorStr.EqualsLiteral(kGIFImageMime)) { - - } - */ - } - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsDragService::IsDataFlavorSupported(const char *aDataFlavor, bool *_retval) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *_retval = false; - - if (!globalDragPboard) - return NS_ERROR_FAILURE; - - nsDependentCString dataFlavor(aDataFlavor); - - // first see if we have data for this in our cached transferable - if (mDataItems) { - uint32_t dataItemsCount; - mDataItems->GetLength(&dataItemsCount); - for (unsigned int i = 0; i < dataItemsCount; i++) { - nsCOMPtr currentTransferable = do_QueryElementAt(mDataItems, i); - if (!currentTransferable) - continue; - - nsCOMPtr flavorList; - nsresult rv = currentTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); - if (NS_FAILED(rv)) - continue; - - uint32_t flavorCount; - flavorList->GetLength(&flavorCount); - for (uint32_t j = 0; j < flavorCount; j++) { - nsCOMPtr currentFlavor = do_QueryElementAt(flavorList, j); - if (!currentFlavor) - continue; - nsXPIDLCString flavorStr; - currentFlavor->ToString(getter_Copies(flavorStr)); - if (dataFlavor.Equals(flavorStr)) { - *_retval = true; - return NS_OK; - } - } - } - } - - const NSString* type = nil; - bool allowFileURL = false; - if (dataFlavor.EqualsLiteral(kFileMime)) { - type = (const NSString*)kUTTypeFileURL; - allowFileURL = true; - } else if (dataFlavor.EqualsLiteral(kUnicodeMime)) { - type = (const NSString*)kUTTypeUTF8PlainText; - } else if (dataFlavor.EqualsLiteral(kHTMLMime)) { - type = (const NSString*)kUTTypeHTML; - } else if (dataFlavor.EqualsLiteral(kURLMime) || - dataFlavor.EqualsLiteral(kURLDataMime)) { - type = (const NSString*)kUTTypeURL; - } else if (dataFlavor.EqualsLiteral(kURLDescriptionMime)) { - type = (const NSString*)kUTTypeURLName; - } else if (dataFlavor.EqualsLiteral(kRTFMime)) { - type = (const NSString*)kUTTypeRTF; - } else if (dataFlavor.EqualsLiteral(kCustomTypesMime)) { - type = (const NSString*)kCustomTypesPboardType; - } - - NSString* availableType = [globalDragPboard availableTypeFromArray:[NSArray arrayWithObjects:(id)type, nil]]; - if (availableType && IsValidType(availableType, allowFileURL)) { - *_retval = true; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsDragService::GetNumDropItems(uint32_t* aNumItems) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *aNumItems = 0; - - // first check to see if we have a number of items cached - if (mDataItems) { - mDataItems->GetLength(aNumItems); - return NS_OK; - } - - NSArray* droppedItems = [globalDragPboard pasteboardItems]; - if (droppedItems) { - *aNumItems = [droppedItems count]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsDragService::EndDragSession(bool aDoneDrag) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mNativeDragView) { - [mNativeDragView release]; - mNativeDragView = nil; - } - if (mNativeDragEvent) { - [mNativeDragEvent release]; - mNativeDragEvent = nil; - } - - mUserCancelled = gUserCancelledDrag; - - nsresult rv = nsBaseDragService::EndDragSession(aDoneDrag); - mDataItems = nullptr; - return rv; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsFilePicker.h b/widget/cocoa/nsFilePicker.h deleted file mode 100644 index 1aeb22cc18..0000000000 --- a/widget/cocoa/nsFilePicker.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 nsFilePicker_h_ -#define nsFilePicker_h_ - -#include "nsBaseFilePicker.h" -#include "nsString.h" -#include "nsIFileChannel.h" -#include "nsIFile.h" -#include "nsCOMArray.h" -#include "nsTArray.h" - -class nsILocalFileMac; -@class NSArray; - -class nsFilePicker : public nsBaseFilePicker -{ -public: - nsFilePicker(); - - NS_DECL_ISUPPORTS - - // nsIFilePicker (less what's in nsBaseFilePicker) - NS_IMETHOD GetDefaultString(nsAString& aDefaultString) override; - NS_IMETHOD SetDefaultString(const nsAString& aDefaultString) override; - NS_IMETHOD GetDefaultExtension(nsAString& aDefaultExtension) override; - NS_IMETHOD GetFilterIndex(int32_t *aFilterIndex) override; - NS_IMETHOD SetFilterIndex(int32_t aFilterIndex) override; - NS_IMETHOD SetDefaultExtension(const nsAString& aDefaultExtension) override; - NS_IMETHOD GetFile(nsIFile * *aFile) override; - NS_IMETHOD GetFileURL(nsIURI * *aFileURL) override; - NS_IMETHOD GetFiles(nsISimpleEnumerator **aFiles) override; - NS_IMETHOD Show(int16_t *_retval) override; - NS_IMETHOD AppendFilter(const nsAString& aTitle, const nsAString& aFilter) override; - - /** - * Returns the current filter list in the format used by Cocoa's NSSavePanel - * and NSOpenPanel. - * Returns nil if no filter currently apply. - */ - NSArray* GetFilterList(); - -protected: - virtual ~nsFilePicker(); - - virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle) override; - - // actual implementations of get/put dialogs using NSOpenPanel & NSSavePanel - // aFile is an existing but unspecified file. These functions must specify it. - // - // will return |returnCancel| or |returnOK| as result. - int16_t GetLocalFiles(const nsString& inTitle, bool inAllowMultiple, nsCOMArray& outFiles); - int16_t GetLocalFolder(const nsString& inTitle, nsIFile** outFile); - int16_t PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsIFile** outFile); - - void SetDialogTitle(const nsString& inTitle, id aDialog); - NSString *PanelDefaultDirectory(); - NSView* GetAccessoryView(); - - nsString mTitle; - nsCOMArray mFiles; - nsString mDefault; - - nsTArray mFilters; - nsTArray mTitles; - - int32_t mSelectedTypeIndex; -}; - -#endif // nsFilePicker_h_ diff --git a/widget/cocoa/nsFilePicker.mm b/widget/cocoa/nsFilePicker.mm deleted file mode 100644 index 5213dee241..0000000000 --- a/widget/cocoa/nsFilePicker.mm +++ /dev/null @@ -1,676 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#import - -#include "nsFilePicker.h" -#include "nsCOMPtr.h" -#include "nsReadableUtils.h" -#include "nsNetUtil.h" -#include "nsIComponentManager.h" -#include "nsIFile.h" -#include "nsILocalFileMac.h" -#include "nsIURL.h" -#include "nsArrayEnumerator.h" -#include "nsIStringBundle.h" -#include "nsCocoaUtils.h" -#include "mozilla/Preferences.h" - -// This must be included last: -#include "nsObjCExceptions.h" - -using namespace mozilla; - -const float kAccessoryViewPadding = 5; -const int kSaveTypeControlTag = 1; - -static bool gCallSecretHiddenFileAPI = false; -const char kShowHiddenFilesPref[] = "filepicker.showHiddenFiles"; - -/** - * This class is an observer of NSPopUpButton selection change. - */ -@interface NSPopUpButtonObserver : NSObject -{ - NSPopUpButton* mPopUpButton; - NSOpenPanel* mOpenPanel; - nsFilePicker* mFilePicker; -} -- (void) setPopUpButton:(NSPopUpButton*)aPopUpButton; -- (void) setOpenPanel:(NSOpenPanel*)aOpenPanel; -- (void) setFilePicker:(nsFilePicker*)aFilePicker; -- (void) menuChangedItem:(NSNotification*)aSender; -@end - -NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker) - -// We never want to call the secret show hidden files API unless the pref -// has been set. Once the pref has been set we always need to call it even -// if it disappears so that we stop showing hidden files if a user deletes -// the pref. If the secret API was used once and things worked out it should -// continue working for subsequent calls so the user is at no more risk. -static void SetShowHiddenFileState(NSSavePanel* panel) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - bool show = false; - if (NS_SUCCEEDED(Preferences::GetBool(kShowHiddenFilesPref, &show))) { - gCallSecretHiddenFileAPI = true; - } - - if (gCallSecretHiddenFileAPI) { - // invoke a method to get a Cocoa-internal nav view - SEL navViewSelector = @selector(_navView); - NSMethodSignature* navViewSignature = [panel methodSignatureForSelector:navViewSelector]; - if (!navViewSignature) - return; - NSInvocation* navViewInvocation = [NSInvocation invocationWithMethodSignature:navViewSignature]; - [navViewInvocation setSelector:navViewSelector]; - [navViewInvocation setTarget:panel]; - [navViewInvocation invoke]; - - // get the returned nav view - id navView = nil; - [navViewInvocation getReturnValue:&navView]; - - // invoke the secret show hidden file state method on the nav view - SEL showHiddenFilesSelector = @selector(setShowsHiddenFiles:); - NSMethodSignature* showHiddenFilesSignature = [navView methodSignatureForSelector:showHiddenFilesSelector]; - if (!showHiddenFilesSignature) - return; - NSInvocation* showHiddenFilesInvocation = [NSInvocation invocationWithMethodSignature:showHiddenFilesSignature]; - [showHiddenFilesInvocation setSelector:showHiddenFilesSelector]; - [showHiddenFilesInvocation setTarget:navView]; - [showHiddenFilesInvocation setArgument:&show atIndex:2]; - [showHiddenFilesInvocation invoke]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsFilePicker::nsFilePicker() -: mSelectedTypeIndex(0) -{ -} - -nsFilePicker::~nsFilePicker() -{ -} - -void -nsFilePicker::InitNative(nsIWidget *aParent, const nsAString& aTitle) -{ - mTitle = aTitle; -} - -NSView* nsFilePicker::GetAccessoryView() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSView* accessoryView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)] autorelease]; - - // Set a label's default value. - NSString* label = @"Format:"; - - // Try to get the localized string. - nsCOMPtr sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID); - nsCOMPtr bundle; - nsresult rv = sbs->CreateBundle("chrome://global/locale/filepicker.properties", getter_AddRefs(bundle)); - if (NS_SUCCEEDED(rv)) { - nsXPIDLString locaLabel; - bundle->GetStringFromName(u"formatLabel", getter_Copies(locaLabel)); - if (locaLabel) { - label = [NSString stringWithCharacters:reinterpret_cast(locaLabel.get()) - length:locaLabel.Length()]; - } - } - - // set up label text field - NSTextField* textField = [[[NSTextField alloc] init] autorelease]; - [textField setEditable:NO]; - [textField setSelectable:NO]; - [textField setDrawsBackground:NO]; - [textField setBezeled:NO]; - [textField setBordered:NO]; - [textField setFont:[NSFont labelFontOfSize:13.0]]; - [textField setStringValue:label]; - [textField setTag:0]; - [textField sizeToFit]; - - // set up popup button - NSPopUpButton* popupButton = [[[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 0, 0) pullsDown:NO] autorelease]; - uint32_t numMenuItems = mTitles.Length(); - for (uint32_t i = 0; i < numMenuItems; i++) { - const nsString& currentTitle = mTitles[i]; - NSString *titleString; - if (currentTitle.IsEmpty()) { - const nsString& currentFilter = mFilters[i]; - titleString = [[NSString alloc] initWithCharacters:reinterpret_cast(currentFilter.get()) - length:currentFilter.Length()]; - } - else { - titleString = [[NSString alloc] initWithCharacters:reinterpret_cast(currentTitle.get()) - length:currentTitle.Length()]; - } - [popupButton addItemWithTitle:titleString]; - [titleString release]; - } - if (mSelectedTypeIndex >= 0 && (uint32_t)mSelectedTypeIndex < numMenuItems) - [popupButton selectItemAtIndex:mSelectedTypeIndex]; - [popupButton setTag:kSaveTypeControlTag]; - [popupButton sizeToFit]; // we have to do sizeToFit to get the height calculated for us - // This is just a default width that works well, doesn't truncate the vast majority of - // things that might end up in the menu. - [popupButton setFrameSize:NSMakeSize(180, [popupButton frame].size.height)]; - - // position everything based on control sizes with kAccessoryViewPadding pix padding - // on each side kAccessoryViewPadding pix horizontal padding between controls - float greatestHeight = [textField frame].size.height; - if ([popupButton frame].size.height > greatestHeight) - greatestHeight = [popupButton frame].size.height; - float totalViewHeight = greatestHeight + kAccessoryViewPadding * 2; - float totalViewWidth = [textField frame].size.width + [popupButton frame].size.width + kAccessoryViewPadding * 3; - [accessoryView setFrameSize:NSMakeSize(totalViewWidth, totalViewHeight)]; - - float textFieldOriginY = ((greatestHeight - [textField frame].size.height) / 2 + 1) + kAccessoryViewPadding; - [textField setFrameOrigin:NSMakePoint(kAccessoryViewPadding, textFieldOriginY)]; - - float popupOriginX = [textField frame].size.width + kAccessoryViewPadding * 2; - float popupOriginY = ((greatestHeight - [popupButton frame].size.height) / 2) + kAccessoryViewPadding; - [popupButton setFrameOrigin:NSMakePoint(popupOriginX, popupOriginY)]; - - [accessoryView addSubview:textField]; - [accessoryView addSubview:popupButton]; - return accessoryView; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// Display the file dialog -NS_IMETHODIMP nsFilePicker::Show(int16_t *retval) -{ - NS_ENSURE_ARG_POINTER(retval); - - *retval = returnCancel; - - int16_t userClicksOK = returnCancel; - -// Random questions from DHH: -// -// Why do we pass mTitle, mDefault to the functions? Can GetLocalFile. PutLocalFile, -// and GetLocalFolder get called someplace else? It generates a bunch of warnings -// as it is right now. -// -// I think we could easily combine GetLocalFile and GetLocalFolder together, just -// setting panel pick options based on mMode. I didn't do it here b/c I wanted to -// make this look as much like Carbon nsFilePicker as possible. - - mFiles.Clear(); - nsCOMPtr theFile; - - switch (mMode) - { - case modeOpen: - userClicksOK = GetLocalFiles(mTitle, false, mFiles); - break; - - case modeOpenMultiple: - userClicksOK = GetLocalFiles(mTitle, true, mFiles); - break; - - case modeSave: - userClicksOK = PutLocalFile(mTitle, mDefault, getter_AddRefs(theFile)); - break; - - case modeGetFolder: - userClicksOK = GetLocalFolder(mTitle, getter_AddRefs(theFile)); - break; - - default: - NS_ERROR("Unknown file picker mode"); - break; - } - - if (theFile) - mFiles.AppendObject(theFile); - - *retval = userClicksOK; - return NS_OK; -} - -static -void UpdatePanelFileTypes(NSOpenPanel* aPanel, NSArray* aFilters) -{ - // If we show all file types, also "expose" bundles' contents. - [aPanel setTreatsFilePackagesAsDirectories:!aFilters]; - - [aPanel setAllowedFileTypes:aFilters]; -} - -@implementation NSPopUpButtonObserver -- (void) setPopUpButton:(NSPopUpButton*)aPopUpButton -{ - mPopUpButton = aPopUpButton; -} - -- (void) setOpenPanel:(NSOpenPanel*)aOpenPanel -{ - mOpenPanel = aOpenPanel; -} - -- (void) setFilePicker:(nsFilePicker*)aFilePicker -{ - mFilePicker = aFilePicker; -} - -- (void) menuChangedItem:(NSNotification *)aSender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - int32_t selectedItem = [mPopUpButton indexOfSelectedItem]; - if (selectedItem < 0) { - return; - } - - mFilePicker->SetFilterIndex(selectedItem); - UpdatePanelFileTypes(mOpenPanel, mFilePicker->GetFilterList()); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(); -} -@end - -// Use OpenPanel to do a GetFile. Returns |returnOK| if the user presses OK in the dialog. -int16_t -nsFilePicker::GetLocalFiles(const nsString& inTitle, bool inAllowMultiple, nsCOMArray& outFiles) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - int16_t retVal = (int16_t)returnCancel; - NSOpenPanel *thePanel = [NSOpenPanel openPanel]; - - SetShowHiddenFileState(thePanel); - - // Set the options for how the get file dialog will appear - SetDialogTitle(inTitle, thePanel); - [thePanel setAllowsMultipleSelection:inAllowMultiple]; - [thePanel setCanSelectHiddenExtension:YES]; - [thePanel setCanChooseDirectories:NO]; - [thePanel setCanChooseFiles:YES]; - [thePanel setResolvesAliases:YES]; //this is default - probably doesn't need to be set - - // Get filters - // filters may be null, if we should allow all file types. - NSArray *filters = GetFilterList(); - - // set up default directory - NSString *theDir = PanelDefaultDirectory(); - - // if this is the "Choose application..." dialog, and no other start - // dir has been set, then use the Applications folder. - if (!theDir) { - if (filters && [filters count] == 1 && - [(NSString *)[filters objectAtIndex:0] isEqualToString:@"app"]) - theDir = @"/Applications/"; - else - theDir = @""; - } - - if (theDir) { - [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]]; - } - - int result; - nsCocoaUtils::PrepareForNativeAppModalDialog(); - if (mFilters.Length() > 1) { - // [NSURL initWithString:] (below) throws an exception if URLString is nil. - - NSPopUpButtonObserver* observer = [[NSPopUpButtonObserver alloc] init]; - - NSView* accessoryView = GetAccessoryView(); - [thePanel setAccessoryView:accessoryView]; - - [observer setPopUpButton:[accessoryView viewWithTag:kSaveTypeControlTag]]; - [observer setOpenPanel:thePanel]; - [observer setFilePicker:this]; - - [[NSNotificationCenter defaultCenter] - addObserver:observer - selector:@selector(menuChangedItem:) - name:NSMenuWillSendActionNotification object:nil]; - - UpdatePanelFileTypes(thePanel, filters); - result = [thePanel runModal]; - - [[NSNotificationCenter defaultCenter] removeObserver:observer]; - [observer release]; - } else { - // If we show all file types, also "expose" bundles' contents. - if (!filters) { - [thePanel setTreatsFilePackagesAsDirectories:YES]; - } - [thePanel setAllowedFileTypes:filters]; - result = [thePanel runModal]; - } - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - - if (result == NSFileHandlingPanelCancelButton) - return retVal; - - // Converts data from a NSArray of NSURL to the returned format. - // We should be careful to not call [thePanel URLs] more than once given that - // it creates a new array each time. - // We are using Fast Enumeration, thus the NSURL array is created once then - // iterated. - for (NSURL* url in [thePanel URLs]) { - if (!url) { - continue; - } - - nsCOMPtr localFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile)); - nsCOMPtr macLocalFile = do_QueryInterface(localFile); - if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)url))) { - outFiles.AppendObject(localFile); - } - } - - if (outFiles.Count() > 0) - retVal = returnOK; - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -// Use OpenPanel to do a GetFolder. Returns |returnOK| if the user presses OK in the dialog. -int16_t -nsFilePicker::GetLocalFolder(const nsString& inTitle, nsIFile** outFile) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer"); - - int16_t retVal = (int16_t)returnCancel; - NSOpenPanel *thePanel = [NSOpenPanel openPanel]; - - SetShowHiddenFileState(thePanel); - - // Set the options for how the get file dialog will appear - SetDialogTitle(inTitle, thePanel); - [thePanel setAllowsMultipleSelection:NO]; //this is default -probably doesn't need to be set - [thePanel setCanSelectHiddenExtension:YES]; - [thePanel setCanChooseDirectories:YES]; - [thePanel setCanChooseFiles:NO]; - [thePanel setResolvesAliases:YES]; //this is default - probably doesn't need to be set - [thePanel setCanCreateDirectories:YES]; - - // packages != folders - [thePanel setTreatsFilePackagesAsDirectories:NO]; - - // set up default directory - NSString *theDir = PanelDefaultDirectory(); - if (theDir) { - [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]]; - } - nsCocoaUtils::PrepareForNativeAppModalDialog(); - int result = [thePanel runModal]; - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - - if (result == NSFileHandlingPanelCancelButton) - return retVal; - - // get the path for the folder (we allow just 1, so that's all we get) - NSURL *theURL = [[thePanel URLs] objectAtIndex:0]; - if (theURL) { - nsCOMPtr localFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile)); - nsCOMPtr macLocalFile = do_QueryInterface(localFile); - if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)theURL))) { - *outFile = localFile; - NS_ADDREF(*outFile); - retVal = returnOK; - } - } - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -// Returns |returnOK| if the user presses OK in the dialog. -int16_t -nsFilePicker::PutLocalFile(const nsString& inTitle, const nsString& inDefaultName, nsIFile** outFile) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - NS_ASSERTION(outFile, "this protected member function expects a null initialized out pointer"); - - int16_t retVal = returnCancel; - NSSavePanel *thePanel = [NSSavePanel savePanel]; - - SetShowHiddenFileState(thePanel); - - SetDialogTitle(inTitle, thePanel); - - // set up accessory view for file format options - NSView* accessoryView = GetAccessoryView(); - [thePanel setAccessoryView:accessoryView]; - - // set up default file name - NSString* defaultFilename = [NSString stringWithCharacters:(const unichar*)inDefaultName.get() length:inDefaultName.Length()]; - - // set up allowed types; this prevents the extension from being selected - // use the UTI for the file type to allow alternate extensions (e.g., jpg vs. jpeg) - NSString* extension = defaultFilename.pathExtension; - if (extension.length != 0) { - CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL); - - if (type) { - thePanel.allowedFileTypes = @[(NSString*)type]; - CFRelease(type); - } else { - // if there's no UTI for the file extension, use the extension itself. - thePanel.allowedFileTypes = @[extension]; - } - } - // Allow users to change the extension. - thePanel.allowsOtherFileTypes = YES; - - // set up default directory - NSString *theDir = PanelDefaultDirectory(); - if (theDir) { - [thePanel setDirectoryURL:[NSURL fileURLWithPath:theDir isDirectory:YES]]; - } - - // load the panel - nsCocoaUtils::PrepareForNativeAppModalDialog(); - [thePanel setNameFieldStringValue:defaultFilename]; - int result = [thePanel runModal]; - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - if (result == NSFileHandlingPanelCancelButton) - return retVal; - - // get the save type - NSPopUpButton* popupButton = [accessoryView viewWithTag:kSaveTypeControlTag]; - if (popupButton) { - mSelectedTypeIndex = [popupButton indexOfSelectedItem]; - } - - NSURL* fileURL = [thePanel URL]; - if (fileURL) { - nsCOMPtr localFile; - NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localFile)); - nsCOMPtr macLocalFile = do_QueryInterface(localFile); - if (macLocalFile && NS_SUCCEEDED(macLocalFile->InitWithCFURL((CFURLRef)fileURL))) { - *outFile = localFile; - NS_ADDREF(*outFile); - // We tell if we are replacing or not by just looking to see if the file exists. - // The user could not have hit OK and not meant to replace the file. - if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) - retVal = returnReplace; - else - retVal = returnOK; - } - } - - return retVal; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -NSArray * -nsFilePicker::GetFilterList() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!mFilters.Length()) { - return nil; - } - - if (mFilters.Length() <= (uint32_t)mSelectedTypeIndex) { - NS_WARNING("An out of range index has been selected. Using the first index instead."); - mSelectedTypeIndex = 0; - } - - const nsString& filterWide = mFilters[mSelectedTypeIndex]; - if (!filterWide.Length()) { - return nil; - } - - if (filterWide.Equals(NS_LITERAL_STRING("*"))) { - return nil; - } - - // The extensions in filterWide are in the format "*.ext" but are expected - // in the format "ext" by NSOpenPanel. So we need to filter some characters. - NSMutableString* filterString = [[[NSMutableString alloc] initWithString: - [NSString stringWithCharacters:reinterpret_cast(filterWide.get()) - length:filterWide.Length()]] autorelease]; - NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@". *"]; - NSRange range = [filterString rangeOfCharacterFromSet:set]; - while (range.length) { - [filterString replaceCharactersInRange:range withString:@""]; - range = [filterString rangeOfCharacterFromSet:set]; - } - - return [[[NSArray alloc] initWithArray: - [filterString componentsSeparatedByString:@";"]] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// Sets the dialog title to whatever it should be. If it fails, eh, -// the OS will provide a sensible default. -void -nsFilePicker::SetDialogTitle(const nsString& inTitle, id aPanel) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [aPanel setTitle:[NSString stringWithCharacters:(const unichar*)inTitle.get() length:inTitle.Length()]]; - - if (!mOkButtonLabel.IsEmpty()) { - [aPanel setPrompt:[NSString stringWithCharacters:(const unichar*)mOkButtonLabel.get() length:mOkButtonLabel.Length()]]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Converts path from an nsIFile into a NSString path -// If it fails, returns an empty string. -NSString * -nsFilePicker::PanelDefaultDirectory() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSString *directory = nil; - if (mDisplayDirectory) { - nsAutoString pathStr; - mDisplayDirectory->GetPath(pathStr); - directory = [[[NSString alloc] initWithCharacters:reinterpret_cast(pathStr.get()) - length:pathStr.Length()] autorelease]; - } - return directory; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -NS_IMETHODIMP nsFilePicker::GetFile(nsIFile **aFile) -{ - NS_ENSURE_ARG_POINTER(aFile); - *aFile = nullptr; - - // just return the first file - if (mFiles.Count() > 0) { - *aFile = mFiles.ObjectAt(0); - NS_IF_ADDREF(*aFile); - } - - return NS_OK; -} - -NS_IMETHODIMP nsFilePicker::GetFileURL(nsIURI **aFileURL) -{ - NS_ENSURE_ARG_POINTER(aFileURL); - *aFileURL = nullptr; - - if (mFiles.Count() == 0) - return NS_OK; - - return NS_NewFileURI(aFileURL, mFiles.ObjectAt(0)); -} - -NS_IMETHODIMP nsFilePicker::GetFiles(nsISimpleEnumerator **aFiles) -{ - return NS_NewArrayEnumerator(aFiles, mFiles); -} - -NS_IMETHODIMP nsFilePicker::SetDefaultString(const nsAString& aString) -{ - mDefault = aString; - return NS_OK; -} - -NS_IMETHODIMP nsFilePicker::GetDefaultString(nsAString& aString) -{ - return NS_ERROR_FAILURE; -} - -// The default extension to use for files -NS_IMETHODIMP nsFilePicker::GetDefaultExtension(nsAString& aExtension) -{ - aExtension.Truncate(); - return NS_OK; -} - -NS_IMETHODIMP nsFilePicker::SetDefaultExtension(const nsAString& aExtension) -{ - return NS_OK; -} - -// Append an entry to the filters array -NS_IMETHODIMP -nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) -{ - // "..apps" has to be translated with native executable extensions. - if (aFilter.EqualsLiteral("..apps")) { - mFilters.AppendElement(NS_LITERAL_STRING("*.app")); - } else { - mFilters.AppendElement(aFilter); - } - mTitles.AppendElement(aTitle); - - return NS_OK; -} - -// Get the filter index - do we still need this? -NS_IMETHODIMP nsFilePicker::GetFilterIndex(int32_t *aFilterIndex) -{ - *aFilterIndex = mSelectedTypeIndex; - return NS_OK; -} - -// Set the filter index - do we still need this? -NS_IMETHODIMP nsFilePicker::SetFilterIndex(int32_t aFilterIndex) -{ - mSelectedTypeIndex = aFilterIndex; - return NS_OK; -} diff --git a/widget/cocoa/nsIdleServiceX.h b/widget/cocoa/nsIdleServiceX.h deleted file mode 100644 index f0b3d92ed5..0000000000 --- a/widget/cocoa/nsIdleServiceX.h +++ /dev/null @@ -1,33 +0,0 @@ -/* 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 nsIdleServiceX_h_ -#define nsIdleServiceX_h_ - -#include "nsIdleService.h" - -class nsIdleServiceX : public nsIdleService -{ -public: - NS_DECL_ISUPPORTS_INHERITED - - bool PollIdleTime(uint32_t* aIdleTime) override; - - static already_AddRefed GetInstance() - { - RefPtr idleService = nsIdleService::GetInstance(); - if (!idleService) { - idleService = new nsIdleServiceX(); - } - - return idleService.forget().downcast(); - } - -protected: - nsIdleServiceX() { } - virtual ~nsIdleServiceX() { } - bool UsePollMode() override; -}; - -#endif // nsIdleServiceX_h_ diff --git a/widget/cocoa/nsIdleServiceX.mm b/widget/cocoa/nsIdleServiceX.mm deleted file mode 100644 index 234a154146..0000000000 --- a/widget/cocoa/nsIdleServiceX.mm +++ /dev/null @@ -1,77 +0,0 @@ -/* 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 "nsIdleServiceX.h" -#include "nsObjCExceptions.h" -#include "nsIServiceManager.h" -#import - -NS_IMPL_ISUPPORTS_INHERITED0(nsIdleServiceX, nsIdleService) - -bool -nsIdleServiceX::PollIdleTime(uint32_t *aIdleTime) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - kern_return_t rval; - mach_port_t masterPort; - - rval = IOMasterPort(kIOMasterPortDefault, &masterPort); - if (rval != KERN_SUCCESS) - return false; - - io_iterator_t hidItr; - rval = IOServiceGetMatchingServices(masterPort, - IOServiceMatching("IOHIDSystem"), - &hidItr); - - if (rval != KERN_SUCCESS) - return false; - NS_ASSERTION(hidItr, "Our iterator is null, but it ought not to be!"); - - io_registry_entry_t entry = IOIteratorNext(hidItr); - NS_ASSERTION(entry, "Our IO Registry Entry is null, but it shouldn't be!"); - - IOObjectRelease(hidItr); - - NSMutableDictionary *hidProps; - rval = IORegistryEntryCreateCFProperties(entry, - (CFMutableDictionaryRef*)&hidProps, - kCFAllocatorDefault, 0); - if (rval != KERN_SUCCESS) - return false; - NS_ASSERTION(hidProps, "HIDProperties is null, but no error was returned."); - [hidProps autorelease]; - - id idleObj = [hidProps objectForKey:@"HIDIdleTime"]; - NS_ASSERTION([idleObj isKindOfClass: [NSData class]] || - [idleObj isKindOfClass: [NSNumber class]], - "What we got for the idle object is not what we expect!"); - - uint64_t time; - if ([idleObj isKindOfClass: [NSData class]]) - [idleObj getBytes: &time]; - else - time = [idleObj unsignedLongLongValue]; - - IOObjectRelease(entry); - - // convert to ms from ns - time /= 1000000; - if (time > UINT32_MAX) // Overflow will occur - return false; - - *aIdleTime = static_cast(time); - - return true; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -bool -nsIdleServiceX::UsePollMode() -{ - return true; -} - diff --git a/widget/cocoa/nsLookAndFeel.h b/widget/cocoa/nsLookAndFeel.h deleted file mode 100644 index 2ad31a2aa1..0000000000 --- a/widget/cocoa/nsLookAndFeel.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 nsLookAndFeel_h_ -#define nsLookAndFeel_h_ -#include "nsXPLookAndFeel.h" - -class nsLookAndFeel: public nsXPLookAndFeel { -public: - nsLookAndFeel(); - virtual ~nsLookAndFeel(); - - virtual nsresult NativeGetColor(ColorID aID, nscolor &aResult); - virtual nsresult GetIntImpl(IntID aID, int32_t &aResult); - virtual nsresult GetFloatImpl(FloatID aID, float &aResult); - virtual bool GetFontImpl(FontID aID, nsString& aFontName, - gfxFontStyle& aFontStyle, - float aDevPixPerCSSPixel); - virtual char16_t GetPasswordCharacterImpl() - { - // unicode value for the bullet character, used for password textfields. - return 0x2022; - } - - static bool UseOverlayScrollbars(); - - virtual nsTArray GetIntCacheImpl(); - virtual void SetIntCacheImpl(const nsTArray& aLookAndFeelIntCache); - - virtual void RefreshImpl(); - -protected: - static bool SystemWantsOverlayScrollbars(); - static bool AllowOverlayScrollbarsOverlap(); - -private: - int32_t mUseOverlayScrollbars; - bool mUseOverlayScrollbarsCached; - - int32_t mAllowOverlayScrollbarsOverlap; - bool mAllowOverlayScrollbarsOverlapCached; -}; - -#endif // nsLookAndFeel_h_ diff --git a/widget/cocoa/nsLookAndFeel.mm b/widget/cocoa/nsLookAndFeel.mm deleted file mode 100644 index 0b68cd0e4f..0000000000 --- a/widget/cocoa/nsLookAndFeel.mm +++ /dev/null @@ -1,584 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 "nsLookAndFeel.h" -#include "nsCocoaFeatures.h" -#include "nsIServiceManager.h" -#include "nsNativeThemeColors.h" -#include "nsStyleConsts.h" -#include "nsCocoaFeatures.h" -#include "nsIContent.h" -#include "gfxFont.h" -#include "gfxFontConstants.h" -#include "gfxPlatformMac.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/widget/WidgetMessageUtils.h" - -#import - -// This must be included last: -#include "nsObjCExceptions.h" - -enum { - mozNSScrollerStyleLegacy = 0, - mozNSScrollerStyleOverlay = 1 -}; -typedef NSInteger mozNSScrollerStyle; - -@interface NSScroller(AvailableSinceLion) -+ (mozNSScrollerStyle)preferredScrollerStyle; -@end - -nsLookAndFeel::nsLookAndFeel() - : nsXPLookAndFeel() - , mUseOverlayScrollbars(-1) - , mUseOverlayScrollbarsCached(false) - , mAllowOverlayScrollbarsOverlap(-1) - , mAllowOverlayScrollbarsOverlapCached(false) -{ -} - -nsLookAndFeel::~nsLookAndFeel() -{ -} - -static nscolor GetColorFromNSColor(NSColor* aColor) -{ - NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - return NS_RGB((unsigned int)([deviceColor redComponent] * 255.0), - (unsigned int)([deviceColor greenComponent] * 255.0), - (unsigned int)([deviceColor blueComponent] * 255.0)); -} - -static nscolor GetColorFromNSColorWithAlpha(NSColor* aColor, float alpha) -{ - NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - return NS_RGBA((unsigned int)([deviceColor redComponent] * 255.0), - (unsigned int)([deviceColor greenComponent] * 255.0), - (unsigned int)([deviceColor blueComponent] * 255.0), - (unsigned int)(alpha * 255.0)); -} - -nsresult -nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsresult res = NS_OK; - - switch (aID) { - case eColorID_WindowBackground: - aColor = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_WindowForeground: - aColor = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_WidgetBackground: - aColor = NS_RGB(0xdd,0xdd,0xdd); - break; - case eColorID_WidgetForeground: - aColor = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_WidgetSelectBackground: - aColor = NS_RGB(0x80,0x80,0x80); - break; - case eColorID_WidgetSelectForeground: - aColor = NS_RGB(0x00,0x00,0x80); - break; - case eColorID_Widget3DHighlight: - aColor = NS_RGB(0xa0,0xa0,0xa0); - break; - case eColorID_Widget3DShadow: - aColor = NS_RGB(0x40,0x40,0x40); - break; - case eColorID_TextBackground: - aColor = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_TextForeground: - aColor = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_TextSelectBackground: - aColor = GetColorFromNSColor([NSColor selectedTextBackgroundColor]); - break; - case eColorID_highlight: // CSS2 color - aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]); - break; - case eColorID__moz_menuhover: - aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]); - break; - case eColorID_TextSelectForeground: - GetColor(eColorID_TextSelectBackground, aColor); - if (aColor == 0x000000) - aColor = NS_RGB(0xff,0xff,0xff); - else - aColor = NS_DONT_CHANGE_COLOR; - break; - case eColorID_highlighttext: // CSS2 color - case eColorID__moz_menuhovertext: - aColor = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]); - break; - case eColorID_IMESelectedRawTextBackground: - case eColorID_IMESelectedConvertedTextBackground: - case eColorID_IMERawInputBackground: - case eColorID_IMEConvertedTextBackground: - aColor = NS_TRANSPARENT; - break; - case eColorID_IMESelectedRawTextForeground: - case eColorID_IMESelectedConvertedTextForeground: - case eColorID_IMERawInputForeground: - case eColorID_IMEConvertedTextForeground: - aColor = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_IMERawInputUnderline: - case eColorID_IMEConvertedTextUnderline: - aColor = NS_40PERCENT_FOREGROUND_COLOR; - break; - case eColorID_IMESelectedRawTextUnderline: - case eColorID_IMESelectedConvertedTextUnderline: - aColor = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_SpellCheckerUnderline: - aColor = NS_RGB(0xff, 0, 0); - break; - - // - // css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors - // - // It's really hard to effectively map these to the Appearance Manager properly, - // since they are modeled word for word after the win32 system colors and don't have any - // real counterparts in the Mac world. I'm sure we'll be tweaking these for - // years to come. - // - // Thanks to mpt26@student.canterbury.ac.nz for the hardcoded values that form the defaults - // if querying the Appearance Manager fails ;) - // - case eColorID__moz_mac_buttonactivetext: - case eColorID__moz_mac_defaultbuttontext: - if (nsCocoaFeatures::OnYosemiteOrLater()) { - aColor = NS_RGB(0xFF,0xFF,0xFF); - break; - } - // Otherwise fall through and return the regular button text: - - case eColorID_buttontext: - case eColorID__moz_buttonhovertext: - aColor = GetColorFromNSColor([NSColor controlTextColor]); - break; - case eColorID_captiontext: - case eColorID_menutext: - case eColorID_infotext: - case eColorID__moz_menubartext: - aColor = GetColorFromNSColor([NSColor textColor]); - break; - case eColorID_windowtext: - aColor = GetColorFromNSColor([NSColor windowFrameTextColor]); - break; - case eColorID_activecaption: - aColor = GetColorFromNSColor([NSColor gridColor]); - break; - case eColorID_activeborder: - aColor = GetColorFromNSColor([NSColor keyboardFocusIndicatorColor]); - break; - case eColorID_appworkspace: - aColor = NS_RGB(0xFF,0xFF,0xFF); - break; - case eColorID_background: - aColor = NS_RGB(0x63,0x63,0xCE); - break; - case eColorID_buttonface: - case eColorID__moz_buttonhoverface: - aColor = NS_RGB(0xF0,0xF0,0xF0); - break; - case eColorID_buttonhighlight: - aColor = NS_RGB(0xFF,0xFF,0xFF); - break; - case eColorID_buttonshadow: - aColor = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID_graytext: - aColor = GetColorFromNSColor([NSColor disabledControlTextColor]); - break; - case eColorID_inactiveborder: - aColor = GetColorFromNSColor([NSColor controlBackgroundColor]); - break; - case eColorID_inactivecaption: - aColor = GetColorFromNSColor([NSColor controlBackgroundColor]); - break; - case eColorID_inactivecaptiontext: - aColor = NS_RGB(0x45,0x45,0x45); - break; - case eColorID_scrollbar: - aColor = GetColorFromNSColor([NSColor scrollBarColor]); - break; - case eColorID_threeddarkshadow: - aColor = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID_threedshadow: - aColor = NS_RGB(0xE0,0xE0,0xE0); - break; - case eColorID_threedface: - aColor = NS_RGB(0xF0,0xF0,0xF0); - break; - case eColorID_threedhighlight: - aColor = GetColorFromNSColor([NSColor highlightColor]); - break; - case eColorID_threedlightshadow: - aColor = NS_RGB(0xDA,0xDA,0xDA); - break; - case eColorID_menu: - aColor = GetColorFromNSColor([NSColor alternateSelectedControlTextColor]); - break; - case eColorID_infobackground: - aColor = NS_RGB(0xFF,0xFF,0xC7); - break; - case eColorID_windowframe: - aColor = GetColorFromNSColor([NSColor gridColor]); - break; - case eColorID_window: - case eColorID__moz_field: - case eColorID__moz_combobox: - aColor = NS_RGB(0xff,0xff,0xff); - break; - case eColorID__moz_fieldtext: - case eColorID__moz_comboboxtext: - aColor = GetColorFromNSColor([NSColor controlTextColor]); - break; - case eColorID__moz_dialog: - aColor = GetColorFromNSColor([NSColor controlHighlightColor]); - break; - case eColorID__moz_dialogtext: - case eColorID__moz_cellhighlighttext: - case eColorID__moz_html_cellhighlighttext: - aColor = GetColorFromNSColor([NSColor controlTextColor]); - break; - case eColorID__moz_dragtargetzone: - aColor = GetColorFromNSColor([NSColor selectedControlColor]); - break; - case eColorID__moz_mac_chrome_active: - case eColorID__moz_mac_chrome_inactive: { - int grey = NativeGreyColorAsInt(toolbarFillGrey, (aID == eColorID__moz_mac_chrome_active)); - aColor = NS_RGB(grey, grey, grey); - } - break; - case eColorID__moz_mac_focusring: - aColor = GetColorFromNSColorWithAlpha([NSColor keyboardFocusIndicatorColor], 0.48); - break; - case eColorID__moz_mac_menushadow: - aColor = NS_RGB(0xA3,0xA3,0xA3); - break; - case eColorID__moz_mac_menutextdisable: - aColor = NS_RGB(0x98,0x98,0x98); - break; - case eColorID__moz_mac_menutextselect: - aColor = GetColorFromNSColor([NSColor selectedMenuItemTextColor]); - break; - case eColorID__moz_mac_disabledtoolbartext: - aColor = GetColorFromNSColor([NSColor disabledControlTextColor]); - break; - case eColorID__moz_mac_menuselect: - aColor = GetColorFromNSColor([NSColor alternateSelectedControlColor]); - break; - case eColorID__moz_buttondefault: - aColor = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID__moz_cellhighlight: - case eColorID__moz_html_cellhighlight: - case eColorID__moz_mac_secondaryhighlight: - // For inactive list selection - aColor = GetColorFromNSColor([NSColor secondarySelectedControlColor]); - break; - case eColorID__moz_eventreerow: - // Background color of even list rows. - aColor = GetColorFromNSColor([[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:0]); - break; - case eColorID__moz_oddtreerow: - // Background color of odd list rows. - aColor = GetColorFromNSColor([[NSColor controlAlternatingRowBackgroundColors] objectAtIndex:1]); - break; - case eColorID__moz_nativehyperlinktext: - // There appears to be no available system defined color. HARDCODING to the appropriate color. - aColor = NS_RGB(0x14,0x4F,0xAE); - break; - default: - NS_WARNING("Someone asked nsILookAndFeel for a color I don't know about"); - aColor = NS_RGB(0xff,0xff,0xff); - res = NS_ERROR_FAILURE; - break; - } - - return res; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult -nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsresult res = nsXPLookAndFeel::GetIntImpl(aID, aResult); - if (NS_SUCCEEDED(res)) - return res; - res = NS_OK; - - switch (aID) { - case eIntID_CaretBlinkTime: - aResult = 567; - break; - case eIntID_CaretWidth: - aResult = 1; - break; - case eIntID_ShowCaretDuringSelection: - aResult = 0; - break; - case eIntID_SelectTextfieldsOnKeyFocus: - // Select textfield content when focused by kbd - // used by EventStateManager::sTextfieldSelectModel - aResult = 1; - break; - case eIntID_SubmenuDelay: - aResult = 200; - break; - case eIntID_TooltipDelay: - aResult = 500; - break; - case eIntID_MenusCanOverlapOSBar: - // xul popups are not allowed to overlap the menubar. - aResult = 0; - break; - case eIntID_SkipNavigatingDisabledMenuItem: - aResult = 1; - break; - case eIntID_DragThresholdX: - case eIntID_DragThresholdY: - aResult = 4; - break; - case eIntID_ScrollArrowStyle: - aResult = eScrollArrow_None; - break; - case eIntID_ScrollSliderStyle: - aResult = eScrollThumbStyle_Proportional; - break; - case eIntID_UseOverlayScrollbars: - if (!mUseOverlayScrollbarsCached) { - mUseOverlayScrollbars = SystemWantsOverlayScrollbars() ? 1 : 0; - mUseOverlayScrollbarsCached = true; - } - aResult = mUseOverlayScrollbars; - break; - case eIntID_AllowOverlayScrollbarsOverlap: - if (!mAllowOverlayScrollbarsOverlapCached) { - mAllowOverlayScrollbarsOverlap = AllowOverlayScrollbarsOverlap() ? 1 : 0; - mAllowOverlayScrollbarsOverlapCached = true; - } - aResult = mAllowOverlayScrollbarsOverlap; - break; - case eIntID_ScrollbarDisplayOnMouseMove: - aResult = 0; - break; - case eIntID_ScrollbarFadeBeginDelay: - aResult = 450; - break; - case eIntID_ScrollbarFadeDuration: - aResult = 200; - break; - case eIntID_TreeOpenDelay: - aResult = 1000; - break; - case eIntID_TreeCloseDelay: - aResult = 1000; - break; - case eIntID_TreeLazyScrollDelay: - aResult = 150; - break; - case eIntID_TreeScrollDelay: - aResult = 100; - break; - case eIntID_TreeScrollLinesMax: - aResult = 3; - break; - case eIntID_DWMCompositor: - case eIntID_WindowsClassic: - case eIntID_WindowsDefaultTheme: - case eIntID_TouchEnabled: - case eIntID_WindowsThemeIdentifier: - case eIntID_OperatingSystemVersionIdentifier: - aResult = 0; - res = NS_ERROR_NOT_IMPLEMENTED; - break; - case eIntID_MacGraphiteTheme: - aResult = [NSColor currentControlTint] == NSGraphiteControlTint; - break; - case eIntID_MacLionTheme: - aResult = 1; - break; - case eIntID_MacYosemiteTheme: - aResult = nsCocoaFeatures::OnYosemiteOrLater(); - break; - case eIntID_AlertNotificationOrigin: - aResult = NS_ALERT_TOP; - break; - case eIntID_TabFocusModel: - aResult = [NSApp isFullKeyboardAccessEnabled] ? - nsIContent::eTabFocus_any : nsIContent::eTabFocus_textControlsMask; - break; - case eIntID_ScrollToClick: - { - aResult = [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"]; - } - break; - case eIntID_ChosenMenuItemsShouldBlink: - aResult = 1; - break; - case eIntID_IMERawInputUnderlineStyle: - case eIntID_IMEConvertedTextUnderlineStyle: - case eIntID_IMESelectedRawTextUnderlineStyle: - case eIntID_IMESelectedConvertedTextUnderline: - aResult = NS_STYLE_TEXT_DECORATION_STYLE_SOLID; - break; - case eIntID_SpellCheckerUnderlineStyle: - aResult = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED; - break; - case eIntID_ScrollbarButtonAutoRepeatBehavior: - aResult = 0; - break; - case eIntID_SwipeAnimationEnabled: - aResult = 0; - if ([NSEvent respondsToSelector:@selector( - isSwipeTrackingFromScrollEventsEnabled)]) { - aResult = [NSEvent isSwipeTrackingFromScrollEventsEnabled] ? 1 : 0; - } - break; - case eIntID_ColorPickerAvailable: - aResult = 1; - break; - case eIntID_ContextMenuOffsetVertical: - aResult = -6; - break; - case eIntID_ContextMenuOffsetHorizontal: - aResult = 1; - break; - default: - aResult = 0; - res = NS_ERROR_FAILURE; - } - return res; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult -nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult) -{ - nsresult res = nsXPLookAndFeel::GetFloatImpl(aID, aResult); - if (NS_SUCCEEDED(res)) - return res; - res = NS_OK; - - switch (aID) { - case eFloatID_IMEUnderlineRelativeSize: - aResult = 2.0f; - break; - case eFloatID_SpellCheckerUnderlineRelativeSize: - aResult = 2.0f; - break; - default: - aResult = -1.0; - res = NS_ERROR_FAILURE; - } - - return res; -} - -bool nsLookAndFeel::UseOverlayScrollbars() -{ - return GetInt(eIntID_UseOverlayScrollbars) != 0; -} - -bool nsLookAndFeel::SystemWantsOverlayScrollbars() -{ - return ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)] && - [NSScroller preferredScrollerStyle] == mozNSScrollerStyleOverlay); -} - -bool nsLookAndFeel::AllowOverlayScrollbarsOverlap() -{ - return (UseOverlayScrollbars()); -} - -bool -nsLookAndFeel::GetFontImpl(FontID aID, nsString &aFontName, - gfxFontStyle &aFontStyle, - float aDevPixPerCSSPixel) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - // hack for now - if (aID == eFont_Window || aID == eFont_Document) { - aFontStyle.style = NS_FONT_STYLE_NORMAL; - aFontStyle.weight = NS_FONT_WEIGHT_NORMAL; - aFontStyle.stretch = NS_FONT_STRETCH_NORMAL; - aFontStyle.size = 14 * aDevPixPerCSSPixel; - aFontStyle.systemFont = true; - - aFontName.AssignLiteral("sans-serif"); - return true; - } - - gfxPlatformMac::LookupSystemFont(aID, aFontName, aFontStyle, - aDevPixPerCSSPixel); - - return true; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -nsTArray -nsLookAndFeel::GetIntCacheImpl() -{ - nsTArray lookAndFeelIntCache = - nsXPLookAndFeel::GetIntCacheImpl(); - - LookAndFeelInt useOverlayScrollbars; - useOverlayScrollbars.id = eIntID_UseOverlayScrollbars; - useOverlayScrollbars.value = GetInt(eIntID_UseOverlayScrollbars); - lookAndFeelIntCache.AppendElement(useOverlayScrollbars); - - LookAndFeelInt allowOverlayScrollbarsOverlap; - allowOverlayScrollbarsOverlap.id = eIntID_AllowOverlayScrollbarsOverlap; - allowOverlayScrollbarsOverlap.value = GetInt(eIntID_AllowOverlayScrollbarsOverlap); - lookAndFeelIntCache.AppendElement(allowOverlayScrollbarsOverlap); - - return lookAndFeelIntCache; -} - -void -nsLookAndFeel::SetIntCacheImpl(const nsTArray& aLookAndFeelIntCache) -{ - for (auto entry : aLookAndFeelIntCache) { - switch(entry.id) { - case eIntID_UseOverlayScrollbars: - mUseOverlayScrollbars = entry.value; - mUseOverlayScrollbarsCached = true; - break; - case eIntID_AllowOverlayScrollbarsOverlap: - mAllowOverlayScrollbarsOverlap = entry.value; - mAllowOverlayScrollbarsOverlapCached = true; - break; - } - } -} - -void -nsLookAndFeel::RefreshImpl() -{ - // We should only clear the cache if we're in the main browser process. - // Otherwise, we should wait for the parent to inform us of new values - // to cache via LookAndFeel::SetIntCache. - if (XRE_IsParentProcess()) { - mUseOverlayScrollbarsCached = false; - mAllowOverlayScrollbarsOverlapCached = false; - } -} diff --git a/widget/cocoa/nsMacCursor.h b/widget/cocoa/nsMacCursor.h deleted file mode 100644 index cf9c84c7ea..0000000000 --- a/widget/cocoa/nsMacCursor.h +++ /dev/null @@ -1,105 +0,0 @@ -/* 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 nsMacCursor_h_ -#define nsMacCursor_h_ - -#import -#import "nsIWidget.h" - -/*! @class nsMacCursor - @abstract Represents a native Mac cursor. - @discussion nsMacCursor provides a simple API for creating and working with native Macintosh cursors. - Cursors can be created used without needing to be aware of the way different cursors are implemented, - in particular the details of managing an animated cursor are hidden. -*/ -@interface nsMacCursor : NSObject -{ - @private - NSTimer *mTimer; - @protected - nsCursor mType; - int mFrameCounter; -} - -/*! @method cursorWithCursor: - @abstract Create a cursor by specifying a Cocoa NSCursor. - @discussion Creates a cursor representing the given Cocoa built-in cursor. - @param aCursor the NSCursor to use - @param aType the corresponding nsCursor constant - @result an autoreleased instance of nsMacCursor representing the given NSCursor - */ -+ (nsMacCursor *) cursorWithCursor: (NSCursor *) aCursor type: (nsCursor) aType; - -/*! @method cursorWithImageNamed:hotSpot:type: - @abstract Create a cursor by specifying the name of an image resource to use for the cursor and a hotspot. - @discussion Creates a cursor by loading the named image using the +[NSImage imageNamed:] method. -

The image must be compatible with any restrictions laid down by NSCursor. These vary - by operating system version.

-

The hotspot precisely determines the point where the user clicks when using the cursor.

- @param aCursor the name of the image to use for the cursor - @param aPoint the point within the cursor to use as the hotspot - @param aType the corresponding nsCursor constant - @result an autoreleased instance of nsMacCursor that uses the given image and hotspot - */ -+ (nsMacCursor *) cursorWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType; - -/*! @method cursorWithFrames:type: - @abstract Create an animated cursor by specifying the frames to use for the animation. - @discussion Creates a cursor that will animate by cycling through the given frames. Each element of the array - must be an instance of NSCursor - @param aCursorFrames an array of NSCursor, representing the frames of an animated cursor, in the - order they should be played. - @param aType the corresponding nsCursor constant - @result an autoreleased instance of nsMacCursor that will animate the given cursor frames - */ -+ (nsMacCursor *) cursorWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType; - -/*! @method cocoaCursorWithImageNamed:hotSpot: - @abstract Create a Cocoa NSCursor object with a Gecko image resource name and a hotspot point. - @discussion Create a Cocoa NSCursor object with a Gecko image resource name and a hotspot point. - @param imageName the name of the gecko image resource, "tiff" extension is assumed, do not append. - @param aPoint the point within the cursor to use as the hotspot - @result an autoreleased instance of nsMacCursor that will animate the given cursor frames - */ -+ (NSCursor *) cocoaCursorWithImageNamed: (NSString *) imageName hotSpot: (NSPoint) aPoint; - -/*! @method isSet - @abstract Determines whether this cursor is currently active. - @discussion This can be helpful when the Cocoa NSCursor state can be influenced without going - through nsCursorManager. - @result whether the cursor is currently set - */ -- (BOOL) isSet; - -/*! @method set - @abstract Set the cursor. - @discussion Makes this cursor the current cursor. If the cursor is animated, the animation is started. - */ -- (void) set; - -/*! @method unset - @abstract Unset the cursor. The cursor will return to the default (usually the arrow cursor). - @discussion Unsets the cursor. If the cursor is animated, the animation is stopped. - */ -- (void) unset; - -/*! @method isAnimated - @abstract Tests whether this cursor is animated. - @discussion Use this method to determine whether a cursor is animated - @result YES if the cursor is animated (has more than one frame), NO if it is a simple static cursor. - */ -- (BOOL) isAnimated; - -/** @method cursorType - @abstract Get the cursor type for this cursor - @discussion This method returns the nsCursor constant that corresponds to this cursor, which is - equivalent to the CSS name for the cursor. - @result The nsCursor constant corresponding to this cursor, or nsCursor's 'eCursorCount' if the cursor - is a custom cursor loaded from a URI - */ -- (nsCursor) type; -@end - -#endif // nsMacCursor_h_ diff --git a/widget/cocoa/nsMacCursor.mm b/widget/cocoa/nsMacCursor.mm deleted file mode 100644 index 4fcdfd3e5d..0000000000 --- a/widget/cocoa/nsMacCursor.mm +++ /dev/null @@ -1,382 +0,0 @@ -/* 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 "nsMacCursor.h" -#include "nsObjCExceptions.h" -#include "nsDebug.h" -#include "nsDirectoryServiceDefs.h" -#include "nsCOMPtr.h" -#include "nsIFile.h" -#include "nsString.h" - -/*! @category nsMacCursor (PrivateMethods) - @abstract Private methods internal to the nsMacCursor class. - @discussion nsMacCursor is effectively an abstract class. It does not define complete - behaviour in and of itself, the subclasses defined in this file provide the useful implementations. -*/ -@interface nsMacCursor (PrivateMethods) - -/*! @method getNextCursorFrame - @abstract get the index of the next cursor frame to display. - @discussion Increments and returns the frame counter of an animated cursor. - @result The index of the next frame to display in the cursor animation -*/ -- (int) getNextCursorFrame; - -/*! @method numFrames - @abstract Query the number of frames in this cursor's animation. - @discussion Returns the number of frames in this cursor's animation. Static cursors return 1. -*/ -- (int) numFrames; - -/*! @method createTimer - @abstract Create a Timer to use to animate the cursor. - @discussion Creates an instance of NSTimer which is used to drive the cursor animation. - This method should only be called for cursors that are animated. -*/ -- (void) createTimer; - -/*! @method destroyTimer - @abstract Destroy any timer instance associated with this cursor. - @discussion Invalidates and releases any NSTimer instance associated with this cursor. - */ -- (void) destroyTimer; -/*! @method destroyTimer - @abstract Destroy any timer instance associated with this cursor. - @discussion Invalidates and releases any NSTimer instance associated with this cursor. -*/ - -/*! @method advanceAnimatedCursor: - @abstract Method called by animation timer to perform animation. - @discussion Called by an animated cursor's associated timer to advance the animation to the next frame. - Determines which frame should occur next and sets the cursor to that frame. - @param aTimer the timer causing the animation -*/ -- (void) advanceAnimatedCursor: (NSTimer *) aTimer; - -/*! @method setFrame: - @abstract Sets the current cursor, using an index to determine which frame in the animation to display. - @discussion Sets the current cursor. The frame index determines which frame is shown if the cursor is animated. - Frames and numbered from 0 to -[nsMacCursor numFrames] - 1. A static cursor - has a single frame, numbered 0. - @param aFrameIndex the index indicating which frame from the animation to display -*/ -- (void) setFrame: (int) aFrameIndex; - -@end - -/*! @class nsCocoaCursor - @abstract Implementation of nsMacCursor that uses Cocoa NSCursor instances. - @discussion Displays a static or animated cursor, using Cocoa NSCursor instances. These can be either - built-in NSCursor instances, or custom NSCursors created from images. - When more than one NSCursor is provided, the cursor will use these as animation frames. -*/ -@interface nsCocoaCursor : nsMacCursor -{ - @private - NSArray *mFrames; - NSCursor *mLastSetCocoaCursor; -} - -/*! @method initWithFrames: - @abstract Create an animated cursor by specifying the frames to use for the animation. - @discussion Creates a cursor that will animate by cycling through the given frames. Each element of the array - must be an instance of NSCursor - @param aCursorFrames an array of NSCursor, representing the frames of an animated cursor, in the - order they should be played. - @param aType the corresponding nsCursor constant - @result an instance of nsCocoaCursor that will animate the given cursor frames - */ -- (id) initWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType; - -/*! @method initWithCursor: - @abstract Create a cursor by specifying a Cocoa NSCursor. - @discussion Creates a cursor representing the given Cocoa built-in cursor. - @param aCursor the NSCursor to use - @param aType the corresponding nsCursor constant - @result an instance of nsCocoaCursor representing the given NSCursor -*/ -- (id) initWithCursor: (NSCursor *) aCursor type: (nsCursor) aType; - -/*! @method initWithImageNamed:hotSpot: - @abstract Create a cursor by specifying the name of an image resource to use for the cursor and a hotspot. - @discussion Creates a cursor by loading the named image using the +[NSImage imageNamed:] method. -

The image must be compatible with any restrictions laid down by NSCursor. These vary - by operating system version.

-

The hotspot precisely determines the point where the user clicks when using the cursor.

- @param aCursor the name of the image to use for the cursor - @param aPoint the point within the cursor to use as the hotspot - @param aType the corresponding nsCursor constant - @result an instance of nsCocoaCursor that uses the given image and hotspot -*/ -- (id) initWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType; - -@end - -@implementation nsMacCursor - -+ (nsMacCursor *) cursorWithCursor: (NSCursor *) aCursor type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [[[nsCocoaCursor alloc] initWithCursor:aCursor type:aType] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (nsMacCursor *) cursorWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [[[nsCocoaCursor alloc] initWithImageNamed:aCursorImage hotSpot:aPoint type:aType] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (nsMacCursor *) cursorWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [[[nsCocoaCursor alloc] initWithFrames:aCursorFrames type:aType] autorelease]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -+ (NSCursor *) cocoaCursorWithImageNamed: (NSString *) imageName hotSpot: (NSPoint) aPoint -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsCOMPtr resDir; - nsAutoCString resPath; - NSString* pathToImage, *pathToHiDpiImage; - NSImage* cursorImage, *hiDpiCursorImage; - - nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(resDir)); - if (NS_FAILED(rv)) - goto INIT_FAILURE; - resDir->AppendNative(NS_LITERAL_CSTRING("res")); - resDir->AppendNative(NS_LITERAL_CSTRING("cursors")); - - rv = resDir->GetNativePath(resPath); - if (NS_FAILED(rv)) - goto INIT_FAILURE; - - pathToImage = [NSString stringWithUTF8String:(const char*)resPath.get()]; - if (!pathToImage) - goto INIT_FAILURE; - pathToImage = [pathToImage stringByAppendingPathComponent:imageName]; - pathToHiDpiImage = [pathToImage stringByAppendingString:@"@2x"]; - // Add same extension to both image paths. - pathToImage = [pathToImage stringByAppendingPathExtension:@"png"]; - pathToHiDpiImage = [pathToHiDpiImage stringByAppendingPathExtension:@"png"]; - - cursorImage = [[[NSImage alloc] initWithContentsOfFile:pathToImage] autorelease]; - if (!cursorImage) - goto INIT_FAILURE; - - // Note 1: There are a few different ways to get a hidpi image via - // initWithContentsOfFile. We let the OS handle this here: when the - // file basename ends in "@2x", it will be displayed at native resolution - // instead of being pixel-doubled. See bug 784909 comment 7 for alternates ways. - // - // Note 2: The OS is picky, and will ignore the hidpi representation - // unless it is exactly twice the size of the lowdpi image. - hiDpiCursorImage = [[[NSImage alloc] initWithContentsOfFile:pathToHiDpiImage] autorelease]; - if (hiDpiCursorImage) { - NSImageRep *imageRep = [[hiDpiCursorImage representations] objectAtIndex:0]; - [cursorImage addRepresentation: imageRep]; - } - return [[[NSCursor alloc] initWithImage:cursorImage hotSpot:aPoint] autorelease]; - -INIT_FAILURE: - NS_WARNING("Problem getting path to cursor image file!"); - [self release]; - return nil; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL) isSet -{ - // implemented by subclasses - return NO; -} - -- (void) set -{ - if ([self isAnimated]) { - [self createTimer]; - } - // if the cursor isn't animated or the timer creation fails for any reason... - if (!mTimer) { - [self setFrame:0]; - } -} - -- (void) unset -{ - [self destroyTimer]; -} - -- (BOOL) isAnimated -{ - return [self numFrames] > 1; -} - -- (int) numFrames -{ - // subclasses need to override this to support animation - return 1; -} - -- (int) getNextCursorFrame -{ - mFrameCounter = (mFrameCounter + 1) % [self numFrames]; - return mFrameCounter; -} - -- (void) createTimer -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!mTimer) { - mTimer = [[NSTimer scheduledTimerWithTimeInterval:0.25 - target:self - selector:@selector(advanceAnimatedCursor:) - userInfo:nil - repeats:YES] retain]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void) destroyTimer -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mTimer) { - [mTimer invalidate]; - [mTimer release]; - mTimer = nil; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void) advanceAnimatedCursor: (NSTimer *) aTimer -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if ([aTimer isValid]) { - [self setFrame:[self getNextCursorFrame]]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void) setFrame: (int) aFrameIndex -{ - // subclasses need to do something useful here -} - -- (nsCursor) type { - return mType; -} - -- (void) dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [self destroyTimer]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -@implementation nsCocoaCursor - -- (id) initWithFrames: (NSArray *) aCursorFrames type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - self = [super init]; - NSEnumerator *it = [aCursorFrames objectEnumerator]; - NSObject *frame = nil; - while ((frame = [it nextObject])) { - NS_ASSERTION([frame isKindOfClass:[NSCursor class]], "Invalid argument: All frames must be of type NSCursor"); - } - mFrames = [aCursorFrames retain]; - mFrameCounter = 0; - mType = aType; - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id) initWithCursor: (NSCursor *) aCursor type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSArray *frame = [NSArray arrayWithObjects:aCursor, nil]; - return [self initWithFrames:frame type:aType]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id) initWithImageNamed: (NSString *) aCursorImage hotSpot: (NSPoint) aPoint type: (nsCursor) aType -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [self initWithCursor:[nsMacCursor cocoaCursorWithImageNamed:aCursorImage hotSpot:aPoint] type:aType]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (BOOL) isSet -{ - return [NSCursor currentCursor] == mLastSetCocoaCursor; -} - -- (void) setFrame: (int) aFrameIndex -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSCursor* newCursor = [mFrames objectAtIndex:aFrameIndex]; - [newCursor set]; - mLastSetCocoaCursor = newCursor; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (int) numFrames -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return [mFrames count]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -- (NSString *) description -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [mFrames description]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void) dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mFrames release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end diff --git a/widget/cocoa/nsMacDockSupport.h b/widget/cocoa/nsMacDockSupport.h deleted file mode 100644 index a638b89e03..0000000000 --- a/widget/cocoa/nsMacDockSupport.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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 "nsIMacDockSupport.h" -#include "nsIStandaloneNativeMenu.h" -#include "nsITaskbarProgress.h" -#include "nsITimer.h" -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsNativeThemeCocoa.h" - -class nsMacDockSupport : public nsIMacDockSupport, public nsITaskbarProgress -{ -public: - nsMacDockSupport(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIMACDOCKSUPPORT - NS_DECL_NSITASKBARPROGRESS - -protected: - virtual ~nsMacDockSupport(); - - nsCOMPtr mDockMenu; - nsString mBadgeText; - - NSImage *mAppIcon, *mProgressBackground; - - HIRect mProgressBounds; - nsTaskbarProgressState mProgressState; - double mProgressFraction; - nsCOMPtr mProgressTimer; - RefPtr mTheme; - - static void RedrawIconCallback(nsITimer* aTimer, void* aClosure); - - bool InitProgress(); - nsresult RedrawIcon(); -}; diff --git a/widget/cocoa/nsMacDockSupport.mm b/widget/cocoa/nsMacDockSupport.mm deleted file mode 100644 index 56b37822bd..0000000000 --- a/widget/cocoa/nsMacDockSupport.mm +++ /dev/null @@ -1,174 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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/. */ - -#import - -#include "nsComponentManagerUtils.h" -#include "nsMacDockSupport.h" -#include "nsObjCExceptions.h" - -NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress) - -nsMacDockSupport::nsMacDockSupport() -: mAppIcon(nil) -, mProgressBackground(nil) -, mProgressState(STATE_NO_PROGRESS) -, mProgressFraction(0.0) -{ - mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID); -} - -nsMacDockSupport::~nsMacDockSupport() -{ - if (mAppIcon) { - [mAppIcon release]; - mAppIcon = nil; - } - if (mProgressBackground) { - [mProgressBackground release]; - mProgressBackground = nil; - } - if (mProgressTimer) { - mProgressTimer->Cancel(); - mProgressTimer = nullptr; - } -} - -NS_IMETHODIMP -nsMacDockSupport::GetDockMenu(nsIStandaloneNativeMenu ** aDockMenu) -{ - nsCOMPtr dockMenu(mDockMenu); - dockMenu.forget(aDockMenu); - return NS_OK; -} - -NS_IMETHODIMP -nsMacDockSupport::SetDockMenu(nsIStandaloneNativeMenu * aDockMenu) -{ - mDockMenu = aDockMenu; - return NS_OK; -} - -NS_IMETHODIMP -nsMacDockSupport::ActivateApplication(bool aIgnoreOtherApplications) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - [[NSApplication sharedApplication] activateIgnoringOtherApps:aIgnoreOtherApplications]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsMacDockSupport::SetBadgeText(const nsAString& aBadgeText) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; - mBadgeText = aBadgeText; - if (aBadgeText.IsEmpty()) - [tile setBadgeLabel: nil]; - else - [tile setBadgeLabel:[NSString stringWithCharacters:reinterpret_cast(mBadgeText.get()) - length:mBadgeText.Length()]]; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsMacDockSupport::GetBadgeText(nsAString& aBadgeText) -{ - aBadgeText = mBadgeText; - return NS_OK; -} - -NS_IMETHODIMP -nsMacDockSupport::SetProgressState(nsTaskbarProgressState aState, - uint64_t aCurrentValue, - uint64_t aMaxValue) -{ - NS_ENSURE_ARG_RANGE(aState, 0, STATE_PAUSED); - if (aState == STATE_NO_PROGRESS || aState == STATE_INDETERMINATE) { - NS_ENSURE_TRUE(aCurrentValue == 0, NS_ERROR_INVALID_ARG); - NS_ENSURE_TRUE(aMaxValue == 0, NS_ERROR_INVALID_ARG); - } - if (aCurrentValue > aMaxValue) { - return NS_ERROR_ILLEGAL_VALUE; - } - - mProgressState = aState; - if (aMaxValue == 0) { - mProgressFraction = 0; - } else { - mProgressFraction = (double)aCurrentValue / aMaxValue; - } - - if (mProgressState == STATE_NORMAL || mProgressState == STATE_INDETERMINATE) { - int perSecond = 8; // Empirically determined, see bug 848792 - mProgressTimer->InitWithFuncCallback(RedrawIconCallback, this, 1000 / perSecond, - nsITimer::TYPE_REPEATING_SLACK); - return NS_OK; - } else { - mProgressTimer->Cancel(); - return RedrawIcon(); - } -} - -// static -void nsMacDockSupport::RedrawIconCallback(nsITimer* aTimer, void* aClosure) -{ - static_cast(aClosure)->RedrawIcon(); -} - -// Return whether to draw progress -bool nsMacDockSupport::InitProgress() -{ - if (mProgressState != STATE_NORMAL && mProgressState != STATE_INDETERMINATE) { - return false; - } - - if (!mAppIcon) { - mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID); - mAppIcon = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; - mProgressBackground = [mAppIcon copyWithZone:nil]; - mTheme = new nsNativeThemeCocoa(); - - NSSize sz = [mProgressBackground size]; - mProgressBounds = CGRectMake(sz.width * 1/32, sz.height * 3/32, - sz.width * 30/32, sz.height * 4/32); - [mProgressBackground lockFocus]; - [[NSColor whiteColor] set]; - NSRectFill(NSRectFromCGRect(mProgressBounds)); - [mProgressBackground unlockFocus]; - } - return true; -} - -nsresult -nsMacDockSupport::RedrawIcon() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (InitProgress()) { - // TODO: - Implement ERROR and PAUSED states? - NSImage *icon = [mProgressBackground copyWithZone:nil]; - bool isIndeterminate = (mProgressState != STATE_NORMAL); - - [icon lockFocus]; - CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - mTheme->DrawProgress(ctx, mProgressBounds, isIndeterminate, - true, mProgressFraction, 1.0, NULL); - [icon unlockFocus]; - [NSApp setApplicationIconImage:icon]; - [icon release]; - } else { - [NSApp setApplicationIconImage:mAppIcon]; - } - - return NS_OK; - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsMacWebAppUtils.h b/widget/cocoa/nsMacWebAppUtils.h deleted file mode 100644 index 98ef235615..0000000000 --- a/widget/cocoa/nsMacWebAppUtils.h +++ /dev/null @@ -1,22 +0,0 @@ -/* 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 _MAC_WEB_APP_UTILS_H_ -#define _MAC_WEB_APP_UTILS_H_ - -#include "nsIMacWebAppUtils.h" - -#define NS_MACWEBAPPUTILS_CONTRACTID "@mozilla.org/widget/mac-web-app-utils;1" - -class nsMacWebAppUtils : public nsIMacWebAppUtils { -public: - nsMacWebAppUtils() {} - - NS_DECL_ISUPPORTS - NS_DECL_NSIMACWEBAPPUTILS - -protected: - virtual ~nsMacWebAppUtils() {} -}; - -#endif //_MAC_WEB_APP_UTILS_H_ diff --git a/widget/cocoa/nsMacWebAppUtils.mm b/widget/cocoa/nsMacWebAppUtils.mm deleted file mode 100644 index 1b98cef7cc..0000000000 --- a/widget/cocoa/nsMacWebAppUtils.mm +++ /dev/null @@ -1,82 +0,0 @@ -/* 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/. */ - -#import - -#include "nsMacWebAppUtils.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" -#include "nsString.h" - -// This must be included last: -#include "nsObjCExceptions.h" - -// Find the path to the app with the given bundleIdentifier, if any. -// Note that the OS will return the path to the newest binary, if there is more than one. -// The determination of 'newest' is complex and beyond the scope of this comment. - -NS_IMPL_ISUPPORTS(nsMacWebAppUtils, nsIMacWebAppUtils) - -NS_IMETHODIMP nsMacWebAppUtils::PathForAppWithIdentifier(const nsAString& bundleIdentifier, nsAString& outPath) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - outPath.Truncate(); - - nsAutoreleasePool localPool; - - //note that the result of this expression might be nil, meaning no matching app was found. - NSString* temp = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier: - [NSString stringWithCharacters:reinterpret_cast(((nsString)bundleIdentifier).get()) - length:((nsString)bundleIdentifier).Length()]]; - - if (temp) { - // Copy out the resultant absolute path into outPath if non-nil. - nsCocoaUtils::GetStringForNSString(temp, outPath); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsMacWebAppUtils::LaunchAppWithIdentifier(const nsAString& bundleIdentifier) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsAutoreleasePool localPool; - - // Note this might return false, meaning the app wasnt launched for some reason. - BOOL success = [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier: - [NSString stringWithCharacters:reinterpret_cast(((nsString)bundleIdentifier).get()) - length:((nsString)bundleIdentifier).Length()] - options: (NSWorkspaceLaunchOptions)0 - additionalEventParamDescriptor: nil - launchIdentifier: NULL]; - - return success ? NS_OK : NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsMacWebAppUtils::TrashApp(const nsAString& path, nsITrashAppCallback* aCallback) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (NS_WARN_IF(!aCallback)) { - return NS_ERROR_INVALID_ARG; - } - - nsCOMPtr callback = aCallback; - - NSString* tempString = [NSString stringWithCharacters:reinterpret_cast(((nsString)path).get()) - length:path.Length()]; - - [[NSWorkspace sharedWorkspace] recycleURLs: [NSArray arrayWithObject:[NSURL fileURLWithPath:tempString]] - completionHandler: ^(NSDictionary *newURLs, NSError *error) { - nsresult rv = (error == nil) ? NS_OK : NS_ERROR_FAILURE; - callback->TrashAppFinished(rv); - }]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsMenuBarX.h b/widget/cocoa/nsMenuBarX.h deleted file mode 100644 index 7cbb8ce62a..0000000000 --- a/widget/cocoa/nsMenuBarX.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsMenuBarX_h_ -#define nsMenuBarX_h_ - -#import - -#include "mozilla/UniquePtr.h" -#include "nsMenuBaseX.h" -#include "nsMenuGroupOwnerX.h" -#include "nsChangeObserver.h" -#include "nsINativeMenuService.h" -#include "nsString.h" - -class nsMenuX; -class nsIWidget; -class nsIContent; - -// The native menu service for creating native menu bars. -class nsNativeMenuServiceX : public nsINativeMenuService -{ -public: - NS_DECL_ISUPPORTS - - nsNativeMenuServiceX() {} - - NS_IMETHOD CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode) override; - -protected: - virtual ~nsNativeMenuServiceX() {} -}; - -// Objective-C class used to allow us to intervene with keyboard event handling. -// We allow mouse actions to work normally. -@interface GeckoNSMenu : NSMenu -{ -} -@end - -// Objective-C class used as action target for menu items -@interface NativeMenuItemTarget : NSObject -{ -} --(IBAction)menuItemHit:(id)sender; -@end - -// Objective-C class used for menu items on the Services menu to allow Gecko -// to override their standard behavior in order to stop key equivalents from -// firing in certain instances. -@interface GeckoServicesNSMenuItem : NSMenuItem -{ -} -- (id) target; -- (SEL) action; -- (void) _doNothing:(id)sender; -@end - -// Objective-C class used as the Services menu so that Gecko can override the -// standard behavior of the Services menu in order to stop key equivalents -// from firing in certain instances. -@interface GeckoServicesNSMenu : NSMenu -{ -} -- (void)addItem:(NSMenuItem *)newItem; -- (NSMenuItem *)addItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv; -- (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index; -- (NSMenuItem *)insertItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv atIndex:(NSInteger)index; -- (void) _overrideClassOfMenuItem:(NSMenuItem *)menuItem; -@end - -// Once instantiated, this object lives until its DOM node or its parent window is destroyed. -// Do not hold references to this, they can become invalid any time the DOM node can be destroyed. -class nsMenuBarX : public nsMenuGroupOwnerX, public nsChangeObserver -{ -public: - nsMenuBarX(); - virtual ~nsMenuBarX(); - - static NativeMenuItemTarget* sNativeEventTarget; - static nsMenuBarX* sLastGeckoMenuBarPainted; - - // The following content nodes have been removed from the menu system. - // We save them here for use in command handling. - nsCOMPtr mAboutItemContent; - nsCOMPtr mPrefItemContent; - nsCOMPtr mQuitItemContent; - - // nsChangeObserver - NS_DECL_CHANGEOBSERVER - - // nsMenuObjectX - void* NativeData() override {return (void*)mNativeMenu;} - nsMenuObjectTypeX MenuObjectType() override {return eMenuBarObjectType;} - - // nsMenuBarX - nsresult Create(nsIWidget* aParent, nsIContent* aContent); - void SetParent(nsIWidget* aParent); - uint32_t GetMenuCount(); - bool MenuContainsAppMenu(); - nsMenuX* GetMenuAt(uint32_t aIndex); - nsMenuX* GetXULHelpMenu(); - void SetSystemHelpMenu(); - nsresult Paint(); - void ForceUpdateNativeMenuAt(const nsAString& indexString); - void ForceNativeMenuReload(); // used for testing - static char GetLocalizedAccelKey(const char *shortcutID); - static void ResetNativeApplicationMenu(); - -protected: - void ConstructNativeMenus(); - void ConstructFallbackNativeMenus(); - nsresult InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex); - void RemoveMenuAtIndex(uint32_t aIndex); - void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode); - void AquifyMenuBar(); - NSMenuItem* CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString& nodeID, SEL action, - int tag, NativeMenuItemTarget* target); - nsresult CreateApplicationMenu(nsMenuX* inMenu); - - nsTArray> mMenuArray; - nsIWidget* mParentWindow; // [weak] - GeckoNSMenu* mNativeMenu; // root menu, representing entire menu bar -}; - -#endif // nsMenuBarX_h_ diff --git a/widget/cocoa/nsMenuBarX.mm b/widget/cocoa/nsMenuBarX.mm deleted file mode 100644 index ff25eb81fc..0000000000 --- a/widget/cocoa/nsMenuBarX.mm +++ /dev/null @@ -1,979 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 - -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsMenuUtilsX.h" -#include "nsCocoaUtils.h" -#include "nsCocoaWindow.h" -#include "nsChildView.h" - -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsGkAtoms.h" -#include "nsObjCExceptions.h" -#include "nsThreadUtils.h" - -#include "nsIContent.h" -#include "nsIWidget.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" -#include "nsIAppStartup.h" -#include "nsIStringBundle.h" -#include "nsToolkitCompsCID.h" - -NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil; -nsMenuBarX* nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; -NSMenu* sApplicationMenu = nil; -BOOL sApplicationMenuIsFallback = NO; -BOOL gSomeMenuBarPainted = NO; - -// We keep references to the first quit and pref item content nodes we find, which -// will be from the hidden window. We use these when the document for the current -// window does not have a quit or pref item. We don't need strong refs here because -// these items are always strong ref'd by their owning menu bar (instance variable). -static nsIContent* sAboutItemContent = nullptr; -static nsIContent* sPrefItemContent = nullptr; -static nsIContent* sQuitItemContent = nullptr; - -NS_IMPL_ISUPPORTS(nsNativeMenuServiceX, nsINativeMenuService) - -NS_IMETHODIMP nsNativeMenuServiceX::CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode) -{ - NS_ASSERTION(NS_IsMainThread(), "Attempting to create native menu bar on wrong thread!"); - - RefPtr mb = new nsMenuBarX(); - if (!mb) - return NS_ERROR_OUT_OF_MEMORY; - - return mb->Create(aParent, aMenuBarNode); -} - -nsMenuBarX::nsMenuBarX() -: nsMenuGroupOwnerX(), mParentWindow(nullptr) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mNativeMenu = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsMenuBarX::~nsMenuBarX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (nsMenuBarX::sLastGeckoMenuBarPainted == this) - nsMenuBarX::sLastGeckoMenuBarPainted = nullptr; - - // the quit/pref items of a random window might have been used if there was no - // hidden window, thus we need to invalidate the weak references. - if (sAboutItemContent == mAboutItemContent) - sAboutItemContent = nullptr; - if (sQuitItemContent == mQuitItemContent) - sQuitItemContent = nullptr; - if (sPrefItemContent == mPrefItemContent) - sPrefItemContent = nullptr; - - // make sure we unregister ourselves as a content observer - if (mContent) { - UnregisterForContentChanges(mContent); - } - - // We have to manually clear the array here because clearing causes menu items - // to call back into the menu bar to unregister themselves. We don't want to - // depend on member variable ordering to ensure that the array gets cleared - // before the registration hash table is destroyed. - mMenuArray.Clear(); - - [mNativeMenu release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent) -{ - if (!aParent) - return NS_ERROR_INVALID_ARG; - - mParentWindow = aParent; - mContent = aContent; - - if (mContent) { - AquifyMenuBar(); - - nsresult rv = nsMenuGroupOwnerX::Create(mContent); - if (NS_FAILED(rv)) - return rv; - - RegisterForContentChanges(mContent, this); - ConstructNativeMenus(); - } else { - ConstructFallbackNativeMenus(); - } - - // Give this to the parent window. The parent takes ownership. - static_cast(mParentWindow)->SetMenuBar(this); - - return NS_OK; -} - -void nsMenuBarX::ConstructNativeMenus() -{ - uint32_t count = mContent->GetChildCount(); - for (uint32_t i = 0; i < count; i++) { - nsIContent *menuContent = mContent->GetChildAt(i); - if (menuContent && - menuContent->IsXULElement(nsGkAtoms::menu)) { - nsMenuX* newMenu = new nsMenuX(); - if (newMenu) { - nsresult rv = newMenu->Create(this, this, menuContent); - if (NS_SUCCEEDED(rv)) - InsertMenuAtIndex(newMenu, GetMenuCount()); - else - delete newMenu; - } - } - } -} - -void nsMenuBarX::ConstructFallbackNativeMenus() -{ - if (sApplicationMenu) { - // Menu has already been built. - return; - } - - nsCOMPtr stringBundle; - - nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); - bundleSvc->CreateBundle("chrome://global/locale/fallbackMenubar.properties", getter_AddRefs(stringBundle)); - - if (!stringBundle) { - return; - } - - nsXPIDLString labelUTF16; - nsXPIDLString keyUTF16; - - const char16_t* labelProp = u"quitMenuitem.label"; - const char16_t* keyProp = u"quitMenuitem.key"; - - stringBundle->GetStringFromName(labelProp, getter_Copies(labelUTF16)); - stringBundle->GetStringFromName(keyProp, getter_Copies(keyUTF16)); - - NSString* labelStr = [NSString stringWithUTF8String: - NS_ConvertUTF16toUTF8(labelUTF16).get()]; - NSString* keyStr= [NSString stringWithUTF8String: - NS_ConvertUTF16toUTF8(keyUTF16).get()]; - - if (!nsMenuBarX::sNativeEventTarget) { - nsMenuBarX::sNativeEventTarget = [[NativeMenuItemTarget alloc] init]; - } - - sApplicationMenu = [[[[NSApp mainMenu] itemAtIndex:0] submenu] retain]; - NSMenuItem* quitMenuItem = [[[NSMenuItem alloc] initWithTitle:labelStr - action:@selector(menuItemHit:) - keyEquivalent:keyStr] autorelease]; - [quitMenuItem setTarget:nsMenuBarX::sNativeEventTarget]; - [quitMenuItem setTag:eCommand_ID_Quit]; - [sApplicationMenu addItem:quitMenuItem]; - sApplicationMenuIsFallback = YES; -} - -uint32_t nsMenuBarX::GetMenuCount() -{ - return mMenuArray.Length(); -} - -bool nsMenuBarX::MenuContainsAppMenu() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return ([mNativeMenu numberOfItems] > 0 && - [[mNativeMenu itemAtIndex:0] submenu] == sApplicationMenu); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - -nsresult nsMenuBarX::InsertMenuAtIndex(nsMenuX* aMenu, uint32_t aIndex) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // If we've only yet created a fallback global Application menu (using - // ContructFallbackNativeMenus()), destroy it before recreating it properly. - if (sApplicationMenu && sApplicationMenuIsFallback) { - ResetNativeApplicationMenu(); - } - // If we haven't created a global Application menu yet, do it. - if (!sApplicationMenu) { - nsresult rv = NS_OK; // avoid warning about rv being unused - rv = CreateApplicationMenu(aMenu); - NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create Application menu"); - - // Hook the new Application menu up to the menu bar. - NSMenu* mainMenu = [NSApp mainMenu]; - NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - [[mainMenu itemAtIndex:0] setSubmenu:sApplicationMenu]; - } - - // add menu to array that owns our menus - mMenuArray.InsertElementAt(aIndex, aMenu); - - // hook up submenus - nsIContent* menuContent = aMenu->Content(); - if (menuContent->GetChildCount() > 0 && - !nsMenuUtilsX::NodeIsHiddenOrCollapsed(menuContent)) { - int insertionIndex = nsMenuUtilsX::CalculateNativeInsertionPoint(this, aMenu); - if (MenuContainsAppMenu()) - insertionIndex++; - [mNativeMenu insertItem:aMenu->NativeMenuItem() atIndex:insertionIndex]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsMenuBarX::RemoveMenuAtIndex(uint32_t aIndex) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mMenuArray.Length() <= aIndex) { - NS_ERROR("Attempting submenu removal with bad index!"); - return; - } - - // Our native menu and our internal menu object array might be out of sync. - // This happens, for example, when a submenu is hidden. Because of this we - // should not assume that a native submenu is hooked up. - NSMenuItem* nativeMenuItem = mMenuArray[aIndex]->NativeMenuItem(); - int nativeMenuItemIndex = [mNativeMenu indexOfItem:nativeMenuItem]; - if (nativeMenuItemIndex != -1) - [mNativeMenu removeItemAtIndex:nativeMenuItemIndex]; - - mMenuArray.RemoveElementAt(aIndex); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsMenuBarX::ObserveAttributeChanged(nsIDocument* aDocument, - nsIContent* aContent, - nsIAtom* aAttribute) -{ -} - -void nsMenuBarX::ObserveContentRemoved(nsIDocument* aDocument, - nsIContent* aChild, - int32_t aIndexInContainer) -{ - RemoveMenuAtIndex(aIndexInContainer); -} - -void nsMenuBarX::ObserveContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild) -{ - nsMenuX* newMenu = new nsMenuX(); - if (newMenu) { - nsresult rv = newMenu->Create(this, this, aChild); - if (NS_SUCCEEDED(rv)) - InsertMenuAtIndex(newMenu, aContainer->IndexOf(aChild)); - else - delete newMenu; - } -} - -void nsMenuBarX::ForceUpdateNativeMenuAt(const nsAString& indexString) -{ - NSString* locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSArray* indexes = [locationString componentsSeparatedByString:@"|"]; - unsigned int indexCount = [indexes count]; - if (indexCount == 0) - return; - - nsMenuX* currentMenu = NULL; - int targetIndex = [[indexes objectAtIndex:0] intValue]; - int visible = 0; - uint32_t length = mMenuArray.Length(); - // first find a menu in the menu bar - for (unsigned int i = 0; i < length; i++) { - nsMenuX* menu = mMenuArray[i].get(); - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(menu->Content())) { - visible++; - if (visible == (targetIndex + 1)) { - currentMenu = menu; - break; - } - } - } - - if (!currentMenu) - return; - - // fake open/close to cause lazy update to happen so submenus populate - currentMenu->MenuOpened(); - currentMenu->MenuClosed(); - - // now find the correct submenu - for (unsigned int i = 1; currentMenu && i < indexCount; i++) { - targetIndex = [[indexes objectAtIndex:i] intValue]; - visible = 0; - length = currentMenu->GetItemCount(); - for (unsigned int j = 0; j < length; j++) { - nsMenuObjectX* targetMenu = currentMenu->GetItemAt(j); - if (!targetMenu) - return; - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(targetMenu->Content())) { - visible++; - if (targetMenu->MenuObjectType() == eSubmenuObjectType && visible == (targetIndex + 1)) { - currentMenu = static_cast(targetMenu); - // fake open/close to cause lazy update to happen - currentMenu->MenuOpened(); - currentMenu->MenuClosed(); - break; - } - } - } - } -} - -// Calling this forces a full reload of the menu system, reloading all native -// menus and their items. -// Without this testing is hard because changes to the DOM affect the native -// menu system lazily. -void nsMenuBarX::ForceNativeMenuReload() -{ - // tear down everything - while (GetMenuCount() > 0) - RemoveMenuAtIndex(0); - - // construct everything - ConstructNativeMenus(); -} - -nsMenuX* nsMenuBarX::GetMenuAt(uint32_t aIndex) -{ - if (mMenuArray.Length() <= aIndex) { - NS_ERROR("Requesting menu at invalid index!"); - return NULL; - } - return mMenuArray[aIndex].get(); -} - -nsMenuX* nsMenuBarX::GetXULHelpMenu() -{ - // The Help menu is usually (always?) the last one, so we start there and - // count back. - for (int32_t i = GetMenuCount() - 1; i >= 0; --i) { - nsMenuX* aMenu = GetMenuAt(i); - if (aMenu && nsMenuX::IsXULHelpMenu(aMenu->Content())) - return aMenu; - } - return nil; -} - -// On SnowLeopard and later we must tell the OS which is our Help menu. -// Otherwise it will only add Spotlight for Help (the Search item) to our -// Help menu if its label/title is "Help" -- i.e. if the menu is in English. -// This resolves bugs 489196 and 539317. -void nsMenuBarX::SetSystemHelpMenu() -{ - nsMenuX* xulHelpMenu = GetXULHelpMenu(); - if (xulHelpMenu) { - NSMenu* helpMenu = (NSMenu*)xulHelpMenu->NativeData(); - if (helpMenu) - [NSApp setHelpMenu:helpMenu]; - } -} - -nsresult nsMenuBarX::Paint() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Don't try to optimize anything in this painting by checking - // sLastGeckoMenuBarPainted because the menubar can be manipulated by - // native dialogs and sheet code and other things besides this paint method. - - // We have to keep the same menu item for the Application menu so we keep - // passing it along. - NSMenu* outgoingMenu = [NSApp mainMenu]; - NS_ASSERTION([outgoingMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - - NSMenuItem* appMenuItem = [[outgoingMenu itemAtIndex:0] retain]; - [outgoingMenu removeItemAtIndex:0]; - [mNativeMenu insertItem:appMenuItem atIndex:0]; - [appMenuItem release]; - - // Set menu bar and event target. - [NSApp setMainMenu:mNativeMenu]; - SetSystemHelpMenu(); - nsMenuBarX::sLastGeckoMenuBarPainted = this; - - gSomeMenuBarPainted = YES; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Returns the 'key' attribute of the 'shortcutID' object (if any) in the -// currently active menubar's DOM document. 'shortcutID' should be the id -// (i.e. the name) of a component that defines a commonly used (and -// localized) cmd+key shortcut, and belongs to a keyset containing similar -// objects. For example "key_selectAll". Returns a value that can be -// compared to the first character of [NSEvent charactersIgnoringModifiers] -// when [NSEvent modifierFlags] == NSCommandKeyMask. -char nsMenuBarX::GetLocalizedAccelKey(const char *shortcutID) -{ - if (!sLastGeckoMenuBarPainted) - return 0; - - nsCOMPtr domDoc(do_QueryInterface(sLastGeckoMenuBarPainted->mContent->OwnerDoc())); - if (!domDoc) - return 0; - - NS_ConvertASCIItoUTF16 shortcutIDStr((const char *)shortcutID); - nsCOMPtr shortcutElement; - domDoc->GetElementById(shortcutIDStr, getter_AddRefs(shortcutElement)); - nsCOMPtr shortcutContent = do_QueryInterface(shortcutElement); - if (!shortcutContent) - return 0; - - nsAutoString key; - shortcutContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, key); - NS_LossyConvertUTF16toASCII keyASC(key.get()); - const char *keyASCPtr = keyASC.get(); - if (!keyASCPtr) - return 0; - // If keyID's 'key' attribute isn't exactly one character long, it's not - // what we're looking for. - if (strlen(keyASCPtr) != sizeof(char)) - return 0; - // Make sure retval is lower case. - char retval = tolower(keyASCPtr[0]); - - return retval; -} - -/* static */ -void nsMenuBarX::ResetNativeApplicationMenu() -{ - [sApplicationMenu removeAllItems]; - [sApplicationMenu release]; - sApplicationMenu = nil; - sApplicationMenuIsFallback = NO; -} - -// Hide the item in the menu by setting the 'hidden' attribute. Returns it in |outHiddenNode| so -// the caller can hang onto it if they so choose. It is acceptable to pass nsull -// for |outHiddenNode| if the caller doesn't care about the hidden node. -void nsMenuBarX::HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode) -{ - nsCOMPtr menuItem; - inDoc->GetElementById(inID, getter_AddRefs(menuItem)); - nsCOMPtr menuContent(do_QueryInterface(menuItem)); - if (menuContent) { - menuContent->SetAttr(kNameSpaceID_None, nsGkAtoms::hidden, NS_LITERAL_STRING("true"), false); - if (outHiddenNode) { - *outHiddenNode = menuContent.get(); - NS_IF_ADDREF(*outHiddenNode); - } - } -} - -// Do what is necessary to conform to the Aqua guidelines for menus. -void nsMenuBarX::AquifyMenuBar() -{ - nsCOMPtr domDoc(do_QueryInterface(mContent->GetComposedDoc())); - if (domDoc) { - // remove the "About..." item and its separator - HideItem(domDoc, NS_LITERAL_STRING("aboutSeparator"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("aboutName"), getter_AddRefs(mAboutItemContent)); - if (!sAboutItemContent) - sAboutItemContent = mAboutItemContent; - - // remove quit item and its separator - HideItem(domDoc, NS_LITERAL_STRING("menu_FileQuitSeparator"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_FileQuitItem"), getter_AddRefs(mQuitItemContent)); - if (!sQuitItemContent) - sQuitItemContent = mQuitItemContent; - - // remove prefs item and its separator, but save off the pref content node - // so we can invoke its command later. - HideItem(domDoc, NS_LITERAL_STRING("menu_PrefsSeparator"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_preferences"), getter_AddRefs(mPrefItemContent)); - if (!sPrefItemContent) - sPrefItemContent = mPrefItemContent; - - // hide items that we use for the Application menu - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_services"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_hide_app"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_hide_others"), nullptr); - HideItem(domDoc, NS_LITERAL_STRING("menu_mac_show_all"), nullptr); - } -} - -// for creating menu items destined for the Application menu -NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString& nodeID, SEL action, - int tag, NativeMenuItemTarget* target) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - nsCOMPtr doc = inMenu->Content()->GetUncomposedDoc(); - if (!doc) { - return nil; - } - - nsCOMPtr domdoc(do_QueryInterface(doc)); - if (!domdoc) { - return nil; - } - - // Get information from the gecko menu item - nsAutoString label; - nsAutoString modifiers; - nsAutoString key; - nsCOMPtr menuItem; - domdoc->GetElementById(nodeID, getter_AddRefs(menuItem)); - if (menuItem) { - menuItem->GetAttribute(NS_LITERAL_STRING("label"), label); - menuItem->GetAttribute(NS_LITERAL_STRING("modifiers"), modifiers); - menuItem->GetAttribute(NS_LITERAL_STRING("key"), key); - } - else { - return nil; - } - - // Get more information about the key equivalent. Start by - // finding the key node we need. - NSString* keyEquiv = nil; - unsigned int macKeyModifiers = 0; - if (!key.IsEmpty()) { - nsCOMPtr keyElement; - domdoc->GetElementById(key, getter_AddRefs(keyElement)); - if (keyElement) { - nsCOMPtr keyContent (do_QueryInterface(keyElement)); - // first grab the key equivalent character - nsAutoString keyChar(NS_LITERAL_STRING(" ")); - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyChar); - if (!keyChar.EqualsLiteral(" ")) { - keyEquiv = [[NSString stringWithCharacters:reinterpret_cast(keyChar.get()) - length:keyChar.Length()] lowercaseString]; - } - // now grab the key equivalent modifiers - nsAutoString modifiersStr; - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr); - uint8_t geckoModifiers = nsMenuUtilsX::GeckoModifiersForNodeAttribute(modifiersStr); - macKeyModifiers = nsMenuUtilsX::MacModifiersForGeckoModifiers(geckoModifiers); - } - } - // get the label into NSString-form - NSString* labelString = [NSString stringWithCharacters:reinterpret_cast(label.get()) - length:label.Length()]; - - if (!labelString) - labelString = @""; - if (!keyEquiv) - keyEquiv = @""; - - // put together the actual NSMenuItem - NSMenuItem* newMenuItem = [[NSMenuItem alloc] initWithTitle:labelString action:action keyEquivalent:keyEquiv]; - - [newMenuItem setTag:tag]; - [newMenuItem setTarget:target]; - [newMenuItem setKeyEquivalentModifierMask:macKeyModifiers]; - - MenuItemInfo * info = [[MenuItemInfo alloc] initWithMenuGroupOwner:this]; - [newMenuItem setRepresentedObject:info]; - [info release]; - - return newMenuItem; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -// build the Application menu shared by all menu bars -nsresult nsMenuBarX::CreateApplicationMenu(nsMenuX* inMenu) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // At this point, the application menu is the application menu from - // the nib in cocoa widgets. We do not have a way to create an application - // menu manually, so we grab the one from the nib and use that. - sApplicationMenu = [[[[NSApp mainMenu] itemAtIndex:0] submenu] retain]; - -/* - We support the following menu items here: - - Menu Item DOM Node ID Notes - - ======================== - = About This App = <- aboutName - ======================== - = Preferences... = <- menu_preferences - ======================== - = Services > = <- menu_mac_services <- (do not define key equivalent) - ======================== - = Hide App = <- menu_mac_hide_app - = Hide Others = <- menu_mac_hide_others - = Show All = <- menu_mac_show_all - ======================== - = Quit = <- menu_FileQuitItem - ======================== - - If any of them are ommitted from the application's DOM, we just don't add - them. We always add a "Quit" item, but if an app developer does not provide a - DOM node with the right ID for the Quit item, we add it in English. App - developers need only add each node with a label and a key equivalent (if they - want one). Other attributes are optional. Like so: - - - - We need to use this system for localization purposes, until we have a better way - to define the Application menu to be used on Mac OS X. -*/ - - if (sApplicationMenu) { - // This code reads attributes we are going to care about from the DOM elements - - NSMenuItem *itemBeingAdded = nil; - BOOL addAboutSeparator = FALSE; - - // Add the About menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("aboutName"), @selector(menuItemHit:), - eCommand_ID_About, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addAboutSeparator = TRUE; - } - - // Add separator if either the About item or software update item exists - if (addAboutSeparator) - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - - // Add the Preferences menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_preferences"), @selector(menuItemHit:), - eCommand_ID_Prefs, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - // Add separator after Preferences menu - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - } - - // Add Services menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_services"), nil, - 0, nil); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - - // set this menu item up as the Mac OS X Services menu - NSMenu* servicesMenu = [[GeckoServicesNSMenu alloc] initWithTitle:@""]; - [itemBeingAdded setSubmenu:servicesMenu]; - [NSApp setServicesMenu:servicesMenu]; - - [itemBeingAdded release]; - itemBeingAdded = nil; - - // Add separator after Services menu - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - } - - BOOL addHideShowSeparator = FALSE; - - // Add menu item to hide this application - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_hide_app"), @selector(menuItemHit:), - eCommand_ID_HideApp, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addHideShowSeparator = TRUE; - } - - // Add menu item to hide other applications - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_hide_others"), @selector(menuItemHit:), - eCommand_ID_HideOthers, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addHideShowSeparator = TRUE; - } - - // Add menu item to show all applications - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_mac_show_all"), @selector(menuItemHit:), - eCommand_ID_ShowAll, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - - addHideShowSeparator = TRUE; - } - - // Add a separator after the hide/show menus if at least one exists - if (addHideShowSeparator) - [sApplicationMenu addItem:[NSMenuItem separatorItem]]; - - // Add quit menu item - itemBeingAdded = CreateNativeAppMenuItem(inMenu, NS_LITERAL_STRING("menu_FileQuitItem"), @selector(menuItemHit:), - eCommand_ID_Quit, nsMenuBarX::sNativeEventTarget); - if (itemBeingAdded) { - [sApplicationMenu addItem:itemBeingAdded]; - [itemBeingAdded release]; - itemBeingAdded = nil; - } - else { - // the current application does not have a DOM node for "Quit". Add one - // anyway, in English. - NSMenuItem* defaultQuitItem = [[[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(menuItemHit:) - keyEquivalent:@"q"] autorelease]; - [defaultQuitItem setTarget:nsMenuBarX::sNativeEventTarget]; - [defaultQuitItem setTag:eCommand_ID_Quit]; - [sApplicationMenu addItem:defaultQuitItem]; - } - } - - return (sApplicationMenu) ? NS_OK : NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void nsMenuBarX::SetParent(nsIWidget* aParent) -{ - mParentWindow = aParent; -} - -// -// Objective-C class used to allow us to have keyboard commands -// look like they are doing something but actually do nothing. -// We allow mouse actions to work normally. -// - -// Controls whether or not native menu items should invoke their commands. -static BOOL gMenuItemsExecuteCommands = YES; - -@implementation GeckoNSMenu - -// Keyboard commands should not cause menu items to invoke their -// commands when there is a key window because we'd rather send -// the keyboard command to the window. We still have the menus -// go through the mechanics so they'll give the proper visual -// feedback. -- (BOOL)performKeyEquivalent:(NSEvent *)theEvent -{ - // We've noticed that Mac OS X expects this check in subclasses before - // calling NSMenu's "performKeyEquivalent:". - // - // There is no case in which we'd need to do anything or return YES - // when we have no items so we can just do this check first. - if ([self numberOfItems] <= 0) { - return NO; - } - - NSWindow *keyWindow = [NSApp keyWindow]; - - // If there is no key window then just behave normally. This - // probably means that this menu is associated with Gecko's - // hidden window. - if (!keyWindow) { - return [super performKeyEquivalent:theEvent]; - } - - NSResponder *firstResponder = [keyWindow firstResponder]; - - gMenuItemsExecuteCommands = NO; - [super performKeyEquivalent:theEvent]; - gMenuItemsExecuteCommands = YES; // return to default - - // Return YES if we invoked a command and there is now no key window or we changed - // the first responder. In this case we do not want to propagate the event because - // we don't want it handled again. - if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) { - return YES; - } - - // Return NO so that we can handle the event via NSView's "keyDown:". - return NO; -} - -@end - -// -// Objective-C class used as action target for menu items -// - -@implementation NativeMenuItemTarget - -// called when some menu item in this menu gets hit --(IBAction)menuItemHit:(id)sender -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!gMenuItemsExecuteCommands) { - return; - } - - int tag = [sender tag]; - - nsMenuGroupOwnerX* menuGroupOwner = nullptr; - nsMenuBarX* menuBar = nullptr; - MenuItemInfo* info = [sender representedObject]; - - if (info) { - menuGroupOwner = [info menuGroupOwner]; - if (!menuGroupOwner) { - return; - } - if (menuGroupOwner->MenuObjectType() == eMenuBarObjectType) { - menuBar = static_cast(menuGroupOwner); - } - } - - // Do special processing if this is for an app-global command. - if (tag == eCommand_ID_About) { - nsIContent* mostSpecificContent = sAboutItemContent; - if (menuBar && menuBar->mAboutItemContent) - mostSpecificContent = menuBar->mAboutItemContent; - nsMenuUtilsX::DispatchCommandTo(mostSpecificContent); - return; - } - else if (tag == eCommand_ID_Prefs) { - nsIContent* mostSpecificContent = sPrefItemContent; - if (menuBar && menuBar->mPrefItemContent) - mostSpecificContent = menuBar->mPrefItemContent; - nsMenuUtilsX::DispatchCommandTo(mostSpecificContent); - return; - } - else if (tag == eCommand_ID_HideApp) { - [NSApp hide:sender]; - return; - } - else if (tag == eCommand_ID_HideOthers) { - [NSApp hideOtherApplications:sender]; - return; - } - else if (tag == eCommand_ID_ShowAll) { - [NSApp unhideAllApplications:sender]; - return; - } - else if (tag == eCommand_ID_Quit) { - nsIContent* mostSpecificContent = sQuitItemContent; - if (menuBar && menuBar->mQuitItemContent) - mostSpecificContent = menuBar->mQuitItemContent; - // If we have some content for quit we execute it. Otherwise we send a native app terminate - // message. If you want to stop a quit from happening, provide quit content and return - // the event as unhandled. - if (mostSpecificContent) { - nsMenuUtilsX::DispatchCommandTo(mostSpecificContent); - } - else { - nsCOMPtr appStartup = do_GetService(NS_APPSTARTUP_CONTRACTID); - if (appStartup) { - appStartup->Quit(nsIAppStartup::eAttemptQuit); - } - } - return; - } - - // given the commandID, look it up in our hashtable and dispatch to - // that menu item. - if (menuGroupOwner) { - nsMenuItemX* menuItem = menuGroupOwner->GetMenuItemForCommandID(static_cast(tag)); - if (menuItem) - menuItem->DoCommand(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -// Objective-C class used for menu items on the Services menu to allow Gecko -// to override their standard behavior in order to stop key equivalents from -// firing in certain instances. When gMenuItemsExecuteCommands is NO, we return -// a dummy target and action instead of the actual target and action. - -@implementation GeckoServicesNSMenuItem - -- (id) target -{ - id realTarget = [super target]; - if (gMenuItemsExecuteCommands) - return realTarget; - else - return realTarget ? self : nil; -} - -- (SEL) action -{ - SEL realAction = [super action]; - if (gMenuItemsExecuteCommands) - return realAction; - else - return realAction ? @selector(_doNothing:) : NULL; -} - -- (void) _doNothing:(id)sender -{ -} - -@end - -// Objective-C class used as the Services menu so that Gecko can override the -// standard behavior of the Services menu in order to stop key equivalents -// from firing in certain instances. - -@implementation GeckoServicesNSMenu - -- (void)addItem:(NSMenuItem *)newItem -{ - [self _overrideClassOfMenuItem:newItem]; - [super addItem:newItem]; -} - -- (NSMenuItem *)addItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv -{ - NSMenuItem * newItem = [super addItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv]; - [self _overrideClassOfMenuItem:newItem]; - return newItem; -} - -- (void)insertItem:(NSMenuItem *)newItem atIndex:(NSInteger)index -{ - [self _overrideClassOfMenuItem:newItem]; - [super insertItem:newItem atIndex:index]; -} - -- (NSMenuItem *)insertItemWithTitle:(NSString *)aString action:(SEL)aSelector keyEquivalent:(NSString *)keyEquiv atIndex:(NSInteger)index -{ - NSMenuItem * newItem = [super insertItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv atIndex:index]; - [self _overrideClassOfMenuItem:newItem]; - return newItem; -} - -- (void) _overrideClassOfMenuItem:(NSMenuItem *)menuItem -{ - if ([menuItem class] == [NSMenuItem class]) - object_setClass(menuItem, [GeckoServicesNSMenuItem class]); -} - -@end diff --git a/widget/cocoa/nsMenuBaseX.h b/widget/cocoa/nsMenuBaseX.h deleted file mode 100644 index 5b9f89c560..0000000000 --- a/widget/cocoa/nsMenuBaseX.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsMenuBaseX_h_ -#define nsMenuBaseX_h_ - -#import - -#include "nsCOMPtr.h" -#include "nsIContent.h" - -enum nsMenuObjectTypeX { - eMenuBarObjectType, - eSubmenuObjectType, - eMenuItemObjectType, - eStandaloneNativeMenuObjectType, -}; - -// All menu objects subclass this. -// Menu bars are owned by their top-level nsIWidgets. -// All other objects are memory-managed based on the DOM. -// Content removal deletes them immediately and nothing else should. -// Do not attempt to hold strong references to them or delete them. -class nsMenuObjectX -{ -public: - virtual ~nsMenuObjectX() { } - virtual nsMenuObjectTypeX MenuObjectType()=0; - virtual void* NativeData()=0; - nsIContent* Content() { return mContent; } - - /** - * Called when an icon of a menu item somewhere in this menu has updated. - * Menu objects with parents need to propagate the notification to their - * parent. - */ - virtual void IconUpdated() {} - -protected: - nsCOMPtr mContent; -}; - - -// -// Object stored as "representedObject" for all menu items -// - -class nsMenuGroupOwnerX; - -@interface MenuItemInfo : NSObject -{ - nsMenuGroupOwnerX * mMenuGroupOwner; -} - -- (id) initWithMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner; -- (nsMenuGroupOwnerX *) menuGroupOwner; -- (void) setMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner; - -@end - - -// Special command IDs that we know Mac OS X does not use for anything else. -// We use these in place of carbon's IDs for these commands in order to stop -// Carbon from messing with our event handlers. See bug 346883. - -enum { - eCommand_ID_About = 1, - eCommand_ID_Prefs = 2, - eCommand_ID_Quit = 3, - eCommand_ID_HideApp = 4, - eCommand_ID_HideOthers = 5, - eCommand_ID_ShowAll = 6, - eCommand_ID_Update = 7, - eCommand_ID_Last = 8 -}; - -#endif // nsMenuBaseX_h_ diff --git a/widget/cocoa/nsMenuGroupOwnerX.h b/widget/cocoa/nsMenuGroupOwnerX.h deleted file mode 100644 index 657f420b56..0000000000 --- a/widget/cocoa/nsMenuGroupOwnerX.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsMenuGroupOwnerX_h_ -#define nsMenuGroupOwnerX_h_ - -#import - -#include "nsMenuBaseX.h" -#include "nsIMutationObserver.h" -#include "nsHashKeys.h" -#include "nsDataHashtable.h" -#include "nsString.h" - -class nsMenuItemX; -class nsChangeObserver; -class nsIWidget; -class nsIContent; - -class nsMenuGroupOwnerX : public nsMenuObjectX, public nsIMutationObserver -{ -public: - nsMenuGroupOwnerX(); - - nsresult Create(nsIContent * aContent); - - void RegisterForContentChanges(nsIContent* aContent, - nsChangeObserver* aMenuObject); - void UnregisterForContentChanges(nsIContent* aContent); - uint32_t RegisterForCommand(nsMenuItemX* aItem); - void UnregisterCommand(uint32_t aCommandID); - nsMenuItemX* GetMenuItemForCommandID(uint32_t inCommandID); - void AddMenuItemInfoToSet(MenuItemInfo* info); - - NS_DECL_ISUPPORTS - NS_DECL_NSIMUTATIONOBSERVER - -protected: - virtual ~nsMenuGroupOwnerX(); - - nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent); - - uint32_t mCurrentCommandID; // unique command id (per menu-bar) to - // give to next item that asks - - // stores observers for content change notification - nsDataHashtable, nsChangeObserver *> mContentToObserverTable; - - // stores mapping of command IDs to menu objects - nsDataHashtable mCommandToMenuObjectTable; - - // Stores references to all the MenuItemInfo objects created with weak - // references to us. They may live longer than we do, so when we're - // destroyed we need to clear all their weak references. This avoids - // crashes in -[NativeMenuItemTarget menuItemHit:]. See bug 1131473. - NSMutableSet* mInfoSet; -}; - -#endif // nsMenuGroupOwner_h_ diff --git a/widget/cocoa/nsMenuGroupOwnerX.mm b/widget/cocoa/nsMenuGroupOwnerX.mm deleted file mode 100644 index 661a52bd80..0000000000 --- a/widget/cocoa/nsMenuGroupOwnerX.mm +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsMenuGroupOwnerX.h" -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsMenuUtilsX.h" -#include "nsCocoaUtils.h" -#include "nsCocoaWindow.h" - -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsObjCExceptions.h" -#include "nsThreadUtils.h" - -#include "mozilla/dom/Element.h" -#include "nsIWidget.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" - -#include "nsINode.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsMenuGroupOwnerX, nsIMutationObserver) - - -nsMenuGroupOwnerX::nsMenuGroupOwnerX() -: mCurrentCommandID(eCommand_ID_Last) -{ - mInfoSet = [[NSMutableSet setWithCapacity:10] retain]; -} - - -nsMenuGroupOwnerX::~nsMenuGroupOwnerX() -{ - MOZ_ASSERT(mContentToObserverTable.Count() == 0, "have outstanding mutation observers!\n"); - - // The MenuItemInfo objects in mInfoSet may live longer than we do. So when - // we get destroyed we need to invalidate all their mMenuGroupOwner pointers. - NSEnumerator* counter = [mInfoSet objectEnumerator]; - MenuItemInfo* info; - while ((info = (MenuItemInfo*) [counter nextObject])) { - [info setMenuGroupOwner:nil]; - } - [mInfoSet release]; -} - - -nsresult nsMenuGroupOwnerX::Create(nsIContent* aContent) -{ - if (!aContent) - return NS_ERROR_INVALID_ARG; - - mContent = aContent; - - return NS_OK; -} - - -// -// nsIMutationObserver -// - - -void nsMenuGroupOwnerX::CharacterDataWillChange(nsIDocument* aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo) -{ -} - - -void nsMenuGroupOwnerX::CharacterDataChanged(nsIDocument* aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo) -{ -} - - -void nsMenuGroupOwnerX::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - int32_t /* unused */) -{ - for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) { - ContentInserted(aDocument, aContainer, cur, 0); - } -} - - -void nsMenuGroupOwnerX::NodeWillBeDestroyed(const nsINode * aNode) -{ -} - - -void nsMenuGroupOwnerX::AttributeWillChange(nsIDocument* aDocument, - dom::Element* aContent, - int32_t aNameSpaceID, - nsIAtom* aAttribute, - int32_t aModType, - const nsAttrValue* aNewValue) -{ -} - -void nsMenuGroupOwnerX::NativeAnonymousChildListChange(nsIDocument* aDocument, - nsIContent* aContent, - bool aIsRemove) -{ -} - -void nsMenuGroupOwnerX::AttributeChanged(nsIDocument* aDocument, - dom::Element* aElement, - int32_t aNameSpaceID, - nsIAtom* aAttribute, - int32_t aModType, - const nsAttrValue* aOldValue) -{ - nsCOMPtr kungFuDeathGrip(this); - nsChangeObserver* obs = LookupContentChangeObserver(aElement); - if (obs) - obs->ObserveAttributeChanged(aDocument, aElement, aAttribute); -} - - -void nsMenuGroupOwnerX::ContentRemoved(nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aChild, - int32_t aIndexInContainer, - nsIContent * aPreviousSibling) -{ - if (!aContainer) { - return; - } - - nsCOMPtr kungFuDeathGrip(this); - nsChangeObserver* obs = LookupContentChangeObserver(aContainer); - if (obs) - obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer); - else if (aContainer != mContent) { - // We do a lookup on the parent container in case things were removed - // under a "menupopup" item. That is basically a wrapper for the contents - // of a "menu" node. - nsCOMPtr parent = aContainer->GetParent(); - if (parent) { - obs = LookupContentChangeObserver(parent); - if (obs) - obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer); - } - } -} - - -void nsMenuGroupOwnerX::ContentInserted(nsIDocument * aDocument, - nsIContent * aContainer, - nsIContent * aChild, - int32_t /* unused */) -{ - if (!aContainer) { - return; - } - - nsCOMPtr kungFuDeathGrip(this); - nsChangeObserver* obs = LookupContentChangeObserver(aContainer); - if (obs) - obs->ObserveContentInserted(aDocument, aContainer, aChild); - else if (aContainer != mContent) { - // We do a lookup on the parent container in case things were removed - // under a "menupopup" item. That is basically a wrapper for the contents - // of a "menu" node. - nsCOMPtr parent = aContainer->GetParent(); - if (parent) { - obs = LookupContentChangeObserver(parent); - if (obs) - obs->ObserveContentInserted(aDocument, aContainer, aChild); - } - } -} - - -void nsMenuGroupOwnerX::ParentChainChanged(nsIContent *aContent) -{ -} - - -// For change management, we don't use a |nsSupportsHashtable| because -// we know that the lifetime of all these items is bounded by the -// lifetime of the menubar. No need to add any more strong refs to the -// picture because the containment hierarchy already uses strong refs. -void nsMenuGroupOwnerX::RegisterForContentChanges(nsIContent *aContent, - nsChangeObserver *aMenuObject) -{ - if (!mContentToObserverTable.Contains(aContent)) { - aContent->AddMutationObserver(this); - } - mContentToObserverTable.Put(aContent, aMenuObject); -} - - -void nsMenuGroupOwnerX::UnregisterForContentChanges(nsIContent *aContent) -{ - if (mContentToObserverTable.Contains(aContent)) { - aContent->RemoveMutationObserver(this); - } - mContentToObserverTable.Remove(aContent); -} - - -nsChangeObserver* nsMenuGroupOwnerX::LookupContentChangeObserver(nsIContent* aContent) -{ - nsChangeObserver * result; - if (mContentToObserverTable.Get(aContent, &result)) - return result; - else - return nullptr; -} - - -// Given a menu item, creates a unique 4-character command ID and -// maps it to the item. Returns the id for use by the client. -uint32_t nsMenuGroupOwnerX::RegisterForCommand(nsMenuItemX* inMenuItem) -{ - // no real need to check for uniqueness. We always start afresh with each - // window at 1. Even if we did get close to the reserved Apple command id's, - // those don't start until at least ' ', which is integer 538976288. If - // we have that many menu items in one window, I think we have other - // problems. - - // make id unique - ++mCurrentCommandID; - - mCommandToMenuObjectTable.Put(mCurrentCommandID, inMenuItem); - - return mCurrentCommandID; -} - - -// Removes the mapping between the given 4-character command ID -// and its associated menu item. -void nsMenuGroupOwnerX::UnregisterCommand(uint32_t inCommandID) -{ - mCommandToMenuObjectTable.Remove(inCommandID); -} - - -nsMenuItemX* nsMenuGroupOwnerX::GetMenuItemForCommandID(uint32_t inCommandID) -{ - nsMenuItemX * result; - if (mCommandToMenuObjectTable.Get(inCommandID, &result)) - return result; - else - return nullptr; -} - -void nsMenuGroupOwnerX::AddMenuItemInfoToSet(MenuItemInfo* info) -{ - [mInfoSet addObject:info]; -} diff --git a/widget/cocoa/nsMenuItemIconX.h b/widget/cocoa/nsMenuItemIconX.h deleted file mode 100644 index 7352a94e2a..0000000000 --- a/widget/cocoa/nsMenuItemIconX.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -/* - * Retrieves and displays icons in native menu items on Mac OS X. - */ - -#ifndef nsMenuItemIconX_h_ -#define nsMenuItemIconX_h_ - -#include "mozilla/RefPtr.h" -#include "nsCOMPtr.h" -#include "imgINotificationObserver.h" - -class nsIURI; -class nsIContent; -class imgRequestProxy; -class nsMenuObjectX; - -#import - -class nsMenuItemIconX : public imgINotificationObserver -{ -public: - nsMenuItemIconX(nsMenuObjectX* aMenuItem, - nsIContent* aContent, - NSMenuItem* aNativeMenuItem); -private: - virtual ~nsMenuItemIconX(); - -public: - NS_DECL_ISUPPORTS - NS_DECL_IMGINOTIFICATIONOBSERVER - - // SetupIcon succeeds if it was able to set up the icon, or if there should - // be no icon, in which case it clears any existing icon but still succeeds. - nsresult SetupIcon(); - - // GetIconURI fails if the item should not have any icon. - nsresult GetIconURI(nsIURI** aIconURI); - - // LoadIcon will set a placeholder image and start a load request for the - // icon. The request may not complete until after LoadIcon returns. - nsresult LoadIcon(nsIURI* aIconURI); - - // Unless we take precautions, we may outlive the object that created us - // (mMenuObject, which owns our native menu item (mNativeMenuItem)). - // Destroy() should be called from mMenuObject's destructor to prevent - // this from happening. See bug 499600. - void Destroy(); - -protected: - nsresult OnFrameComplete(imgIRequest* aRequest); - - nsCOMPtr mContent; - RefPtr mIconRequest; - nsMenuObjectX* mMenuObject; // [weak] - nsIntRect mImageRegionRect; - bool mLoadedIcon; - bool mSetIcon; - NSMenuItem* mNativeMenuItem; // [weak] -}; - -#endif // nsMenuItemIconX_h_ diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm deleted file mode 100644 index 7589c279e5..0000000000 --- a/widget/cocoa/nsMenuItemIconX.mm +++ /dev/null @@ -1,466 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -/* - * Retrieves and displays icons in native menu items on Mac OS X. - */ - -/* exception_defines.h defines 'try' to 'if (true)' which breaks objective-c - exceptions and produces errors like: error: unexpected '@' in program'. - If we define __EXCEPTIONS exception_defines.h will avoid doing this. - - See bug 666609 for more information. - - We use to get the libstdc++ version. */ -#include -#if __GLIBCXX__ <= 20070719 -#ifndef __EXCEPTIONS -#define __EXCEPTIONS -#endif -#endif - -#include "nsMenuItemIconX.h" -#include "nsObjCExceptions.h" -#include "nsIContent.h" -#include "nsIDocument.h" -#include "nsNameSpaceManager.h" -#include "nsGkAtoms.h" -#include "nsIDOMElement.h" -#include "nsICSSDeclaration.h" -#include "nsIDOMCSSValue.h" -#include "nsIDOMCSSPrimitiveValue.h" -#include "nsIDOMRect.h" -#include "nsThreadUtils.h" -#include "nsToolkit.h" -#include "nsNetUtil.h" -#include "imgLoader.h" -#include "imgRequestProxy.h" -#include "nsMenuItemX.h" -#include "gfxPlatform.h" -#include "imgIContainer.h" -#include "nsCocoaUtils.h" -#include "nsContentUtils.h" -#include "nsIContentPolicy.h" - -using mozilla::dom::Element; -using mozilla::gfx::SourceSurface; - -static const uint32_t kIconWidth = 16; -static const uint32_t kIconHeight = 16; - -typedef NS_STDCALL_FUNCPROTO(nsresult, GetRectSideMethod, nsIDOMRect, - GetBottom, (nsIDOMCSSPrimitiveValue**)); - -NS_IMPL_ISUPPORTS(nsMenuItemIconX, imgINotificationObserver) - -nsMenuItemIconX::nsMenuItemIconX(nsMenuObjectX* aMenuItem, - nsIContent* aContent, - NSMenuItem* aNativeMenuItem) -: mContent(aContent) -, mMenuObject(aMenuItem) -, mLoadedIcon(false) -, mSetIcon(false) -, mNativeMenuItem(aNativeMenuItem) -{ - // printf("Creating icon for menu item %d, menu %d, native item is %d\n", aMenuItem, aMenu, aNativeMenuItem); -} - -nsMenuItemIconX::~nsMenuItemIconX() -{ - if (mIconRequest) - mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); -} - -// Called from mMenuObjectX's destructor, to prevent us from outliving it -// (as might otherwise happen if calls to our imgINotificationObserver methods -// are still outstanding). mMenuObjectX owns our nNativeMenuItem. -void nsMenuItemIconX::Destroy() -{ - if (mIconRequest) { - mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - mMenuObject = nullptr; - mNativeMenuItem = nil; -} - -nsresult -nsMenuItemIconX::SetupIcon() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // Still don't have one, then something is wrong, get out of here. - if (!mNativeMenuItem) { - NS_ERROR("No native menu item"); - return NS_ERROR_FAILURE; - } - - nsCOMPtr iconURI; - nsresult rv = GetIconURI(getter_AddRefs(iconURI)); - if (NS_FAILED(rv)) { - // There is no icon for this menu item. An icon might have been set - // earlier. Clear it. - [mNativeMenuItem setImage:nil]; - - return NS_OK; - } - - rv = LoadIcon(iconURI); - if (NS_FAILED(rv)) { - // There is no icon for this menu item, as an error occurred while loading it. - // An icon might have been set earlier or the place holder icon may have - // been set. Clear it. - [mNativeMenuItem setImage:nil]; - } - return rv; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -static int32_t -GetDOMRectSide(nsIDOMRect* aRect, GetRectSideMethod aMethod) -{ - nsCOMPtr dimensionValue; - (aRect->*aMethod)(getter_AddRefs(dimensionValue)); - if (!dimensionValue) - return -1; - - uint16_t primitiveType; - nsresult rv = dimensionValue->GetPrimitiveType(&primitiveType); - if (NS_FAILED(rv) || primitiveType != nsIDOMCSSPrimitiveValue::CSS_PX) - return -1; - - float dimension = 0; - rv = dimensionValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX, - &dimension); - if (NS_FAILED(rv)) - return -1; - - return NSToIntRound(dimension); -} - -nsresult -nsMenuItemIconX::GetIconURI(nsIURI** aIconURI) -{ - if (!mMenuObject) - return NS_ERROR_FAILURE; - - // Mac native menu items support having both a checkmark and an icon - // simultaneously, but this is unheard of in the cross-platform toolkit, - // seemingly because the win32 theme is unable to cope with both at once. - // The downside is that it's possible to get a menu item marked with a - // native checkmark and a checkmark for an icon. Head off that possibility - // by pretending that no icon exists if this is a checkable menu item. - if (mMenuObject->MenuObjectType() == eMenuItemObjectType) { - nsMenuItemX* menuItem = static_cast(mMenuObject); - if (menuItem->GetMenuItemType() != eRegularMenuItemType) - return NS_ERROR_FAILURE; - } - - if (!mContent) - return NS_ERROR_FAILURE; - - // First, look at the content node's "image" attribute. - nsAutoString imageURIString; - bool hasImageAttr = mContent->GetAttr(kNameSpaceID_None, - nsGkAtoms::image, - imageURIString); - - nsresult rv; - nsCOMPtr cssValue; - nsCOMPtr cssStyleDecl; - nsCOMPtr primitiveValue; - uint16_t primitiveType; - if (!hasImageAttr) { - // If the content node has no "image" attribute, get the - // "list-style-image" property from CSS. - nsCOMPtr document = mContent->GetComposedDoc(); - if (!document) - return NS_ERROR_FAILURE; - - nsCOMPtr window = document->GetInnerWindow(); - if (!window) - return NS_ERROR_FAILURE; - - nsCOMPtr domElement = do_QueryInterface(mContent); - if (!domElement) - return NS_ERROR_FAILURE; - - ErrorResult dummy; - cssStyleDecl = window->GetComputedStyle(*domElement, EmptyString(), dummy); - dummy.SuppressException(); - if (!cssStyleDecl) - return NS_ERROR_FAILURE; - - NS_NAMED_LITERAL_STRING(listStyleImage, "list-style-image"); - rv = cssStyleDecl->GetPropertyCSSValue(listStyleImage, - getter_AddRefs(cssValue)); - if (NS_FAILED(rv)) return rv; - - primitiveValue = do_QueryInterface(cssValue); - if (!primitiveValue) return NS_ERROR_FAILURE; - - rv = primitiveValue->GetPrimitiveType(&primitiveType); - if (NS_FAILED(rv)) return rv; - if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_URI) - return NS_ERROR_FAILURE; - - rv = primitiveValue->GetStringValue(imageURIString); - if (NS_FAILED(rv)) return rv; - } - - // Empty the mImageRegionRect initially as the image region CSS could - // have been changed and now have an error or have been removed since the - // last GetIconURI call. - mImageRegionRect.SetEmpty(); - - // If this menu item shouldn't have an icon, the string will be empty, - // and NS_NewURI will fail. - nsCOMPtr iconURI; - rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString); - if (NS_FAILED(rv)) return rv; - - *aIconURI = iconURI; - NS_ADDREF(*aIconURI); - - if (!hasImageAttr) { - // Check if the icon has a specified image region so that it can be - // cropped appropriately before being displayed. - NS_NAMED_LITERAL_STRING(imageRegion, "-moz-image-region"); - rv = cssStyleDecl->GetPropertyCSSValue(imageRegion, - getter_AddRefs(cssValue)); - // Just return NS_OK if there if there is a failure due to no - // moz-image region specified so the whole icon will be drawn anyway. - if (NS_FAILED(rv)) return NS_OK; - - primitiveValue = do_QueryInterface(cssValue); - if (!primitiveValue) return NS_OK; - - rv = primitiveValue->GetPrimitiveType(&primitiveType); - if (NS_FAILED(rv)) return NS_OK; - if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_RECT) - return NS_OK; - - nsCOMPtr imageRegionRect; - rv = primitiveValue->GetRectValue(getter_AddRefs(imageRegionRect)); - if (NS_FAILED(rv)) return NS_OK; - - if (imageRegionRect) { - // Return NS_ERROR_FAILURE if the image region is invalid so the image - // is not drawn, and behavior is similar to XUL menus. - int32_t bottom = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetBottom); - int32_t right = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetRight); - int32_t top = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetTop); - int32_t left = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetLeft); - - if (top < 0 || left < 0 || bottom <= top || right <= left) - return NS_ERROR_FAILURE; - - mImageRegionRect.SetRect(left, top, right - left, bottom - top); - } - } - - return NS_OK; -} - -nsresult -nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mIconRequest) { - // Another icon request is already in flight. Kill it. - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - - mLoadedIcon = false; - - if (!mContent) return NS_ERROR_FAILURE; - - nsCOMPtr document = mContent->OwnerDoc(); - - nsCOMPtr loadGroup = document->GetDocumentLoadGroup(); - if (!loadGroup) return NS_ERROR_FAILURE; - - RefPtr loader = nsContentUtils::GetImgLoaderForDocument(document); - if (!loader) return NS_ERROR_FAILURE; - - if (!mSetIcon) { - // Set a completely transparent 16x16 image as the icon on this menu item - // as a placeholder. This keeps the menu item text displayed in the same - // position that it will be displayed when the real icon is loaded, and - // prevents it from jumping around or looking misaligned. - - static bool sInitializedPlaceholder; - static NSImage* sPlaceholderIconImage; - if (!sInitializedPlaceholder) { - sInitializedPlaceholder = true; - - // Note that we only create the one and reuse it forever, so this is not a leak. - sPlaceholderIconImage = [[NSImage alloc] initWithSize:NSMakeSize(kIconWidth, kIconHeight)]; - } - - if (!sPlaceholderIconImage) return NS_ERROR_FAILURE; - - if (mNativeMenuItem) - [mNativeMenuItem setImage:sPlaceholderIconImage]; - } - - nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, - mozilla::net::RP_Default, - nullptr, loadGroup, this, - nullptr, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), - getter_AddRefs(mIconRequest)); - if (NS_FAILED(rv)) return rv; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// -// imgINotificationObserver -// - -NS_IMETHODIMP -nsMenuItemIconX::Notify(imgIRequest* aRequest, - int32_t aType, - const nsIntRect* aData) -{ - if (aType == imgINotificationObserver::LOAD_COMPLETE) { - // Make sure the image loaded successfully. - uint32_t status = imgIRequest::STATUS_ERROR; - if (NS_FAILED(aRequest->GetImageStatus(&status)) || - (status & imgIRequest::STATUS_ERROR)) { - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - return NS_ERROR_FAILURE; - } - - nsCOMPtr image; - aRequest->GetImage(getter_AddRefs(image)); - MOZ_ASSERT(image); - - // Ask the image to decode at its intrinsic size. - int32_t width = 0, height = 0; - image->GetWidth(&width); - image->GetHeight(&height); - image->RequestDecodeForSize(nsIntSize(width, height), imgIContainer::FLAG_NONE); - } - - if (aType == imgINotificationObserver::FRAME_COMPLETE) { - return OnFrameComplete(aRequest); - } - - if (aType == imgINotificationObserver::DECODE_COMPLETE) { - if (mIconRequest && mIconRequest == aRequest) { - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - } - - return NS_OK; -} - -nsresult -nsMenuItemIconX::OnFrameComplete(imgIRequest* aRequest) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (aRequest != mIconRequest) - return NS_ERROR_FAILURE; - - // Only support one frame. - if (mLoadedIcon) - return NS_OK; - - if (!mNativeMenuItem) - return NS_ERROR_FAILURE; - - nsCOMPtr imageContainer; - aRequest->GetImage(getter_AddRefs(imageContainer)); - if (!imageContainer) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - int32_t origWidth = 0, origHeight = 0; - imageContainer->GetWidth(&origWidth); - imageContainer->GetHeight(&origHeight); - - // If the image region is invalid, don't draw the image to almost match - // the behavior of other platforms. - if (!mImageRegionRect.IsEmpty() && - (mImageRegionRect.XMost() > origWidth || - mImageRegionRect.YMost() > origHeight)) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - if (mImageRegionRect.IsEmpty()) { - mImageRegionRect.SetRect(0, 0, origWidth, origHeight); - } - - RefPtr surface = - imageContainer->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - if (!surface) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - CGImageRef origImage = NULL; - nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &origImage); - if (NS_FAILED(rv) || !origImage) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - - bool createSubImage = !(mImageRegionRect.x == 0 && mImageRegionRect.y == 0 && - mImageRegionRect.width == origWidth && mImageRegionRect.height == origHeight); - - CGImageRef finalImage = origImage; - if (createSubImage) { - // if mImageRegionRect is set using CSS, we need to slice a piece out of the overall - // image to use as the icon - finalImage = ::CGImageCreateWithImageInRect(origImage, - ::CGRectMake(mImageRegionRect.x, - mImageRegionRect.y, - mImageRegionRect.width, - mImageRegionRect.height)); - ::CGImageRelease(origImage); - if (!finalImage) { - [mNativeMenuItem setImage:nil]; - return NS_ERROR_FAILURE; - } - } - - NSImage *newImage = nil; - rv = nsCocoaUtils::CreateNSImageFromCGImage(finalImage, &newImage); - if (NS_FAILED(rv) || !newImage) { - [mNativeMenuItem setImage:nil]; - ::CGImageRelease(finalImage); - return NS_ERROR_FAILURE; - } - - [newImage setSize:NSMakeSize(kIconWidth, kIconHeight)]; - [mNativeMenuItem setImage:newImage]; - - [newImage release]; - ::CGImageRelease(finalImage); - - mLoadedIcon = true; - mSetIcon = true; - - if (mMenuObject) { - mMenuObject->IconUpdated(); - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsMenuItemX.h b/widget/cocoa/nsMenuItemX.h deleted file mode 100644 index 67ae32c99c..0000000000 --- a/widget/cocoa/nsMenuItemX.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsMenuItemX_h_ -#define nsMenuItemX_h_ - -#include "mozilla/RefPtr.h" -#include "nsMenuBaseX.h" -#include "nsMenuGroupOwnerX.h" -#include "nsChangeObserver.h" - -#import - -class nsString; -class nsMenuItemIconX; -class nsMenuX; - -enum { - knsMenuItemNoModifier = 0, - knsMenuItemShiftModifier = (1 << 0), - knsMenuItemAltModifier = (1 << 1), - knsMenuItemControlModifier = (1 << 2), - knsMenuItemCommandModifier = (1 << 3) -}; - -enum EMenuItemType { - eRegularMenuItemType = 0, - eCheckboxMenuItemType, - eRadioMenuItemType, - eSeparatorMenuItemType -}; - - -// Once instantiated, this object lives until its DOM node or its parent window is destroyed. -// Do not hold references to this, they can become invalid any time the DOM node can be destroyed. -class nsMenuItemX : public nsMenuObjectX, - public nsChangeObserver -{ -public: - nsMenuItemX(); - virtual ~nsMenuItemX(); - - NS_DECL_CHANGEOBSERVER - - // nsMenuObjectX - void* NativeData() override {return (void*)mNativeMenuItem;} - nsMenuObjectTypeX MenuObjectType() override {return eMenuItemObjectType;} - - // nsMenuItemX - nsresult Create(nsMenuX* aParent, const nsString& aLabel, EMenuItemType aItemType, - nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode); - nsresult SetChecked(bool aIsChecked); - EMenuItemType GetMenuItemType(); - void DoCommand(); - nsresult DispatchDOMEvent(const nsString &eventName, bool* preventDefaultCalled); - void SetupIcon(); - -protected: - void UncheckRadioSiblings(nsIContent* inCheckedElement); - void SetKeyEquiv(); - - EMenuItemType mType; - // nsMenuItemX objects should always have a valid native menu item. - NSMenuItem* mNativeMenuItem; // [strong] - nsMenuX* mMenuParent; // [weak] - nsMenuGroupOwnerX* mMenuGroupOwner; // [weak] - nsCOMPtr mCommandContent; - // The icon object should never outlive its creating nsMenuItemX object. - RefPtr mIcon; - bool mIsChecked; -}; - -#endif // nsMenuItemX_h_ diff --git a/widget/cocoa/nsMenuItemX.mm b/widget/cocoa/nsMenuItemX.mm deleted file mode 100644 index 114b69f430..0000000000 --- a/widget/cocoa/nsMenuItemX.mm +++ /dev/null @@ -1,369 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsMenuItemX.h" -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemIconX.h" -#include "nsMenuUtilsX.h" -#include "nsCocoaUtils.h" - -#include "nsObjCExceptions.h" - -#include "nsCOMPtr.h" -#include "nsGkAtoms.h" - -#include "mozilla/dom/Element.h" -#include "nsIWidget.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" -#include "nsIDOMEvent.h" - -nsMenuItemX::nsMenuItemX() -{ - mType = eRegularMenuItemType; - mNativeMenuItem = nil; - mMenuParent = nullptr; - mMenuGroupOwner = nullptr; - mIsChecked = false; - - MOZ_COUNT_CTOR(nsMenuItemX); -} - -nsMenuItemX::~nsMenuItemX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Prevent the icon object from outliving us. - if (mIcon) - mIcon->Destroy(); - - // autorelease the native menu item so that anything else happening to this - // object happens before the native menu item actually dies - [mNativeMenuItem autorelease]; - - if (mContent) - mMenuGroupOwner->UnregisterForContentChanges(mContent); - if (mCommandContent) - mMenuGroupOwner->UnregisterForContentChanges(mCommandContent); - - MOZ_COUNT_DTOR(nsMenuItemX); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult nsMenuItemX::Create(nsMenuX* aParent, const nsString& aLabel, EMenuItemType aItemType, - nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mType = aItemType; - mMenuParent = aParent; - mContent = aNode; - - mMenuGroupOwner = aMenuGroupOwner; - NS_ASSERTION(mMenuGroupOwner, "No menu owner given, must have one!"); - - mMenuGroupOwner->RegisterForContentChanges(mContent, this); - - nsIDocument *doc = mContent->GetUncomposedDoc(); - - // if we have a command associated with this menu item, register for changes - // to the command DOM node - if (doc) { - nsAutoString ourCommand; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::command, ourCommand); - - if (!ourCommand.IsEmpty()) { - nsIContent *commandElement = doc->GetElementById(ourCommand); - - if (commandElement) { - mCommandContent = commandElement; - // register to observe the command DOM element - mMenuGroupOwner->RegisterForContentChanges(mCommandContent, this); - } - } - } - - // decide enabled state based on command content if it exists, otherwise do it based - // on our own content - bool isEnabled; - if (mCommandContent) - isEnabled = !mCommandContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters); - else - isEnabled = !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters); - - // set up the native menu item - if (mType == eSeparatorMenuItemType) { - mNativeMenuItem = [[NSMenuItem separatorItem] retain]; - } - else { - NSString *newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(aLabel); - mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""]; - - [mNativeMenuItem setEnabled:(BOOL)isEnabled]; - - SetChecked(mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked, - nsGkAtoms::_true, eCaseMatters)); - SetKeyEquiv(); - } - - mIcon = new nsMenuItemIconX(this, mContent, mNativeMenuItem); - if (!mIcon) - return NS_ERROR_OUT_OF_MEMORY; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsMenuItemX::SetChecked(bool aIsChecked) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mIsChecked = aIsChecked; - - // update the content model. This will also handle unchecking our siblings - // if we are a radiomenu - mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::checked, - mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), true); - - // update native menu item - if (mIsChecked) - [mNativeMenuItem setState:NSOnState]; - else - [mNativeMenuItem setState:NSOffState]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -EMenuItemType nsMenuItemX::GetMenuItemType() -{ - return mType; -} - -// Executes the "cached" javaScript command. -// Returns NS_OK if the command was executed properly, otherwise an error code. -void nsMenuItemX::DoCommand() -{ - // flip "checked" state if we're a checkbox menu, or an un-checked radio menu - if (mType == eCheckboxMenuItemType || - (mType == eRadioMenuItemType && !mIsChecked)) { - if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocheck, - nsGkAtoms::_false, eCaseMatters)) - SetChecked(!mIsChecked); - /* the AttributeChanged code will update all the internal state */ - } - - nsMenuUtilsX::DispatchCommandTo(mContent); -} - -nsresult nsMenuItemX::DispatchDOMEvent(const nsString &eventName, bool *preventDefaultCalled) -{ - if (!mContent) - return NS_ERROR_FAILURE; - - // get owner document for content - nsCOMPtr parentDoc = mContent->OwnerDoc(); - - // get interface for creating DOM events from content owner document - nsCOMPtr domDoc = do_QueryInterface(parentDoc); - if (!domDoc) { - NS_WARNING("Failed to QI parent nsIDocument to nsIDOMDocument"); - return NS_ERROR_FAILURE; - } - - // create DOM event - nsCOMPtr event; - nsresult rv = domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event)); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create nsIDOMEvent"); - return rv; - } - event->InitEvent(eventName, true, true); - - // mark DOM event as trusted - event->SetTrusted(true); - - // send DOM event - rv = mContent->DispatchEvent(event, preventDefaultCalled); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to send DOM event via EventTarget"); - return rv; - } - - return NS_OK; -} - -// Walk the sibling list looking for nodes with the same name and -// uncheck them all. -void nsMenuItemX::UncheckRadioSiblings(nsIContent* inCheckedContent) -{ - nsAutoString myGroupName; - inCheckedContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, myGroupName); - if (!myGroupName.Length()) // no groupname, nothing to do - return; - - nsCOMPtr parent = inCheckedContent->GetParent(); - if (!parent) - return; - - // loop over siblings - uint32_t count = parent->GetChildCount(); - for (uint32_t i = 0; i < count; i++) { - nsIContent *sibling = parent->GetChildAt(i); - if (sibling) { - if (sibling != inCheckedContent) { // skip this node - // if the current sibling is in the same group, clear it - if (sibling->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, - myGroupName, eCaseMatters)) - sibling->SetAttr(kNameSpaceID_None, nsGkAtoms::checked, NS_LITERAL_STRING("false"), true); - } - } - } -} - -void nsMenuItemX::SetKeyEquiv() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Set key shortcut and modifiers - nsAutoString keyValue; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyValue); - if (!keyValue.IsEmpty() && mContent->GetUncomposedDoc()) { - nsIContent *keyContent = mContent->GetUncomposedDoc()->GetElementById(keyValue); - if (keyContent) { - nsAutoString keyChar; - bool hasKey = keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyChar); - - if (!hasKey || keyChar.IsEmpty()) { - nsAutoString keyCodeName; - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCodeName); - uint32_t charCode = - nsCocoaUtils::ConvertGeckoNameToMacCharCode(keyCodeName); - if (charCode) { - keyChar.Assign(charCode); - } - else { - keyChar.Assign(NS_LITERAL_STRING(" ")); - } - } - - nsAutoString modifiersStr; - keyContent->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr); - uint8_t modifiers = nsMenuUtilsX::GeckoModifiersForNodeAttribute(modifiersStr); - - unsigned int macModifiers = nsMenuUtilsX::MacModifiersForGeckoModifiers(modifiers); - [mNativeMenuItem setKeyEquivalentModifierMask:macModifiers]; - - NSString *keyEquivalent = [[NSString stringWithCharacters:(unichar*)keyChar.get() - length:keyChar.Length()] lowercaseString]; - if ([keyEquivalent isEqualToString:@" "]) - [mNativeMenuItem setKeyEquivalent:@""]; - else - [mNativeMenuItem setKeyEquivalent:keyEquivalent]; - - return; - } - } - - // if the key was removed, clear the key - [mNativeMenuItem setKeyEquivalent:@""]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// -// nsChangeObserver -// - -void -nsMenuItemX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aContent, nsIAtom *aAttribute) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!aContent) - return; - - if (aContent == mContent) { // our own content node changed - if (aAttribute == nsGkAtoms::checked) { - // if we're a radio menu, uncheck our sibling radio items. No need to - // do any of this if we're just a normal check menu. - if (mType == eRadioMenuItemType) { - if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked, - nsGkAtoms::_true, eCaseMatters)) - UncheckRadioSiblings(mContent); - } - mMenuParent->SetRebuild(true); - } - else if (aAttribute == nsGkAtoms::hidden || - aAttribute == nsGkAtoms::collapsed || - aAttribute == nsGkAtoms::label) { - mMenuParent->SetRebuild(true); - } - else if (aAttribute == nsGkAtoms::key) { - SetKeyEquiv(); - } - else if (aAttribute == nsGkAtoms::image) { - SetupIcon(); - } - else if (aAttribute == nsGkAtoms::disabled) { - if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters)) - [mNativeMenuItem setEnabled:NO]; - else - [mNativeMenuItem setEnabled:YES]; - } - } - else if (aContent == mCommandContent) { - // the only thing that really matters when the menu isn't showing is the - // enabled state since it enables/disables keyboard commands - if (aAttribute == nsGkAtoms::disabled) { - // first we sync our menu item DOM node with the command DOM node - nsAutoString commandDisabled; - nsAutoString menuDisabled; - aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::disabled, commandDisabled); - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::disabled, menuDisabled); - if (!commandDisabled.Equals(menuDisabled)) { - // The menu's disabled state needs to be updated to match the command. - if (commandDisabled.IsEmpty()) - mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true); - else - mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, commandDisabled, true); - } - // now we sync our native menu item with the command DOM node - if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, nsGkAtoms::_true, eCaseMatters)) - [mNativeMenuItem setEnabled:NO]; - else - [mNativeMenuItem setEnabled:YES]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsMenuItemX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, int32_t aIndexInContainer) -{ - if (aChild == mCommandContent) { - mMenuGroupOwner->UnregisterForContentChanges(mCommandContent); - mCommandContent = nullptr; - } - - mMenuParent->SetRebuild(true); -} - -void nsMenuItemX::ObserveContentInserted(nsIDocument *aDocument, nsIContent* aContainer, - nsIContent *aChild) -{ - mMenuParent->SetRebuild(true); -} - -void nsMenuItemX::SetupIcon() -{ - if (mIcon) - mIcon->SetupIcon(); -} diff --git a/widget/cocoa/nsMenuUtilsX.h b/widget/cocoa/nsMenuUtilsX.h deleted file mode 100644 index 1571cdfb0a..0000000000 --- a/widget/cocoa/nsMenuUtilsX.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsMenuUtilsX_h_ -#define nsMenuUtilsX_h_ - -#include "nscore.h" -#include "nsMenuBaseX.h" - -#import - -class nsIContent; -class nsString; -class nsMenuBarX; - -// Namespace containing utility functions used in our native menu implementation. -namespace nsMenuUtilsX -{ - void DispatchCommandTo(nsIContent* aTargetContent); - NSString* GetTruncatedCocoaLabel(const nsString& itemLabel); - uint8_t GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute); - unsigned int MacModifiersForGeckoModifiers(uint8_t geckoModifiers); - nsMenuBarX* GetHiddenWindowMenuBar(); // returned object is not retained - NSMenuItem* GetStandardEditMenuItem(); // returned object is not retained - bool NodeIsHiddenOrCollapsed(nsIContent* inContent); - int CalculateNativeInsertionPoint(nsMenuObjectX* aParent, nsMenuObjectX* aChild); -} // namespace nsMenuUtilsX - -#endif // nsMenuUtilsX_h_ diff --git a/widget/cocoa/nsMenuUtilsX.mm b/widget/cocoa/nsMenuUtilsX.mm deleted file mode 100644 index db64717127..0000000000 --- a/widget/cocoa/nsMenuUtilsX.mm +++ /dev/null @@ -1,223 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/dom/Event.h" -#include "nsMenuUtilsX.h" -#include "nsMenuBarX.h" -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsStandaloneNativeMenu.h" -#include "nsObjCExceptions.h" -#include "nsCocoaUtils.h" -#include "nsCocoaWindow.h" -#include "nsGkAtoms.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDOMXULCommandEvent.h" -#include "nsPIDOMWindow.h" -#include "nsQueryObject.h" - -using namespace mozilla; - -void nsMenuUtilsX::DispatchCommandTo(nsIContent* aTargetContent) -{ - NS_PRECONDITION(aTargetContent, "null ptr"); - - nsIDocument* doc = aTargetContent->OwnerDoc(); - if (doc) { - ErrorResult rv; - RefPtr event = - doc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"), rv); - nsCOMPtr command = do_QueryObject(event); - - // FIXME: Should probably figure out how to init this with the actual - // pressed keys, but this is a big old edge case anyway. -dwh - if (command && - NS_SUCCEEDED(command->InitCommandEvent(NS_LITERAL_STRING("command"), - true, true, - doc->GetInnerWindow(), 0, - false, false, false, - false, nullptr))) { - event->SetTrusted(true); - bool dummy; - aTargetContent->DispatchEvent(event, &dummy); - } - } -} - -NSString* nsMenuUtilsX::GetTruncatedCocoaLabel(const nsString& itemLabel) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - // We want to truncate long strings to some reasonable pixel length but there is no - // good API for doing that which works for all OS versions and architectures. For now - // we'll do nothing for consistency and depend on good user interface design to limit - // string lengths. - return [NSString stringWithCharacters:reinterpret_cast(itemLabel.get()) - length:itemLabel.Length()]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -uint8_t nsMenuUtilsX::GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute) -{ - uint8_t modifiers = knsMenuItemNoModifier; - char* str = ToNewCString(modifiersAttribute); - char* newStr; - char* token = strtok_r(str, ", \t", &newStr); - while (token != NULL) { - if (strcmp(token, "shift") == 0) - modifiers |= knsMenuItemShiftModifier; - else if (strcmp(token, "alt") == 0) - modifiers |= knsMenuItemAltModifier; - else if (strcmp(token, "control") == 0) - modifiers |= knsMenuItemControlModifier; - else if ((strcmp(token, "accel") == 0) || - (strcmp(token, "meta") == 0)) { - modifiers |= knsMenuItemCommandModifier; - } - token = strtok_r(newStr, ", \t", &newStr); - } - free(str); - - return modifiers; -} - -unsigned int nsMenuUtilsX::MacModifiersForGeckoModifiers(uint8_t geckoModifiers) -{ - unsigned int macModifiers = 0; - - if (geckoModifiers & knsMenuItemShiftModifier) - macModifiers |= NSShiftKeyMask; - if (geckoModifiers & knsMenuItemAltModifier) - macModifiers |= NSAlternateKeyMask; - if (geckoModifiers & knsMenuItemControlModifier) - macModifiers |= NSControlKeyMask; - if (geckoModifiers & knsMenuItemCommandModifier) - macModifiers |= NSCommandKeyMask; - - return macModifiers; -} - -nsMenuBarX* nsMenuUtilsX::GetHiddenWindowMenuBar() -{ - nsIWidget* hiddenWindowWidgetNoCOMPtr = nsCocoaUtils::GetHiddenWindowWidget(); - if (hiddenWindowWidgetNoCOMPtr) - return static_cast(hiddenWindowWidgetNoCOMPtr)->GetMenuBar(); - else - return nullptr; -} - -// It would be nice if we could localize these edit menu names. -NSMenuItem* nsMenuUtilsX::GetStandardEditMenuItem() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - // In principle we should be able to allocate this once and then always - // return the same object. But weird interactions happen between native - // app-modal dialogs and Gecko-modal dialogs that open above them. So what - // we return here isn't always released before it needs to be added to - // another menu. See bmo bug 468393. - NSMenuItem* standardEditMenuItem = - [[[NSMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:@""] autorelease]; - NSMenu* standardEditMenu = [[NSMenu alloc] initWithTitle:@"Edit"]; - [standardEditMenuItem setSubmenu:standardEditMenu]; - [standardEditMenu release]; - - // Add Undo - NSMenuItem* undoItem = [[NSMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:@"z"]; - [standardEditMenu addItem:undoItem]; - [undoItem release]; - - // Add Redo - NSMenuItem* redoItem = [[NSMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:@"Z"]; - [standardEditMenu addItem:redoItem]; - [redoItem release]; - - // Add separator - [standardEditMenu addItem:[NSMenuItem separatorItem]]; - - // Add Cut - NSMenuItem* cutItem = [[NSMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"]; - [standardEditMenu addItem:cutItem]; - [cutItem release]; - - // Add Copy - NSMenuItem* copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"]; - [standardEditMenu addItem:copyItem]; - [copyItem release]; - - // Add Paste - NSMenuItem* pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"]; - [standardEditMenu addItem:pasteItem]; - [pasteItem release]; - - // Add Delete - NSMenuItem* deleteItem = [[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:) keyEquivalent:@""]; - [standardEditMenu addItem:deleteItem]; - [deleteItem release]; - - // Add Select All - NSMenuItem* selectAllItem = [[NSMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"]; - [standardEditMenu addItem:selectAllItem]; - [selectAllItem release]; - - return standardEditMenuItem; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -bool nsMenuUtilsX::NodeIsHiddenOrCollapsed(nsIContent* inContent) -{ - return (inContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden, - nsGkAtoms::_true, eCaseMatters) || - inContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::collapsed, - nsGkAtoms::_true, eCaseMatters)); -} - -// Determines how many items are visible among the siblings in a menu that are -// before the given child. This will not count the application menu. -int nsMenuUtilsX::CalculateNativeInsertionPoint(nsMenuObjectX* aParent, - nsMenuObjectX* aChild) -{ - int insertionPoint = 0; - nsMenuObjectTypeX parentType = aParent->MenuObjectType(); - if (parentType == eMenuBarObjectType) { - nsMenuBarX* menubarParent = static_cast(aParent); - uint32_t numMenus = menubarParent->GetMenuCount(); - for (uint32_t i = 0; i < numMenus; i++) { - nsMenuX* currMenu = menubarParent->GetMenuAt(i); - if (currMenu == aChild) - return insertionPoint; // we found ourselves, break out - if (currMenu && [currMenu->NativeMenuItem() menu]) - insertionPoint++; - } - } - else if (parentType == eSubmenuObjectType || - parentType == eStandaloneNativeMenuObjectType) { - nsMenuX* menuParent; - if (parentType == eSubmenuObjectType) - menuParent = static_cast(aParent); - else - menuParent = static_cast(aParent)->GetMenuXObject(); - - uint32_t numItems = menuParent->GetItemCount(); - for (uint32_t i = 0; i < numItems; i++) { - // Using GetItemAt instead of GetVisibleItemAt to avoid O(N^2) - nsMenuObjectX* currItem = menuParent->GetItemAt(i); - if (currItem == aChild) - return insertionPoint; // we found ourselves, break out - NSMenuItem* nativeItem = nil; - nsMenuObjectTypeX currItemType = currItem->MenuObjectType(); - if (currItemType == eSubmenuObjectType) - nativeItem = static_cast(currItem)->NativeMenuItem(); - else - nativeItem = (NSMenuItem*)(currItem->NativeData()); - if ([nativeItem menu]) - insertionPoint++; - } - } - return insertionPoint; -} diff --git a/widget/cocoa/nsMenuX.h b/widget/cocoa/nsMenuX.h deleted file mode 100644 index 7b5146a0b8..0000000000 --- a/widget/cocoa/nsMenuX.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsMenuX_h_ -#define nsMenuX_h_ - -#import - -#include "mozilla/RefPtr.h" -#include "mozilla/UniquePtr.h" -#include "nsMenuBaseX.h" -#include "nsMenuBarX.h" -#include "nsMenuGroupOwnerX.h" -#include "nsCOMPtr.h" -#include "nsChangeObserver.h" - -class nsMenuX; -class nsMenuItemIconX; -class nsMenuItemX; -class nsIWidget; - -// MenuDelegate is used to receive Cocoa notifications for setting -// up carbon events. Protocol is defined as of 10.6 SDK. -@interface MenuDelegate : NSObject < NSMenuDelegate > -{ - nsMenuX* mGeckoMenu; // weak ref -} -- (id)initWithGeckoMenu:(nsMenuX*)geckoMenu; -@end - -// Once instantiated, this object lives until its DOM node or its parent window is destroyed. -// Do not hold references to this, they can become invalid any time the DOM node can be destroyed. -class nsMenuX : public nsMenuObjectX, - public nsChangeObserver -{ -public: - nsMenuX(); - virtual ~nsMenuX(); - - // If > 0, the OS is indexing all the app's menus (triggered by opening - // Help menu on Leopard and higher). There are some things that are - // unsafe to do while this is happening. - static int32_t sIndexingMenuLevel; - - NS_DECL_CHANGEOBSERVER - - // nsMenuObjectX - void* NativeData() override {return (void*)mNativeMenu;} - nsMenuObjectTypeX MenuObjectType() override {return eSubmenuObjectType;} - void IconUpdated() override { mParent->IconUpdated(); } - - // nsMenuX - nsresult Create(nsMenuObjectX* aParent, nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode); - uint32_t GetItemCount(); - nsMenuObjectX* GetItemAt(uint32_t aPos); - nsresult GetVisibleItemCount(uint32_t &aCount); - nsMenuObjectX* GetVisibleItemAt(uint32_t aPos); - nsEventStatus MenuOpened(); - void MenuClosed(); - void SetRebuild(bool aMenuEvent); - NSMenuItem* NativeMenuItem(); - nsresult SetupIcon(); - - static bool IsXULHelpMenu(nsIContent* aMenuContent); - -protected: - void MenuConstruct(); - nsresult RemoveAll(); - nsresult SetEnabled(bool aIsEnabled); - nsresult GetEnabled(bool* aIsEnabled); - void GetMenuPopupContent(nsIContent** aResult); - bool OnOpen(); - bool OnClose(); - nsresult AddMenuItem(nsMenuItemX* aMenuItem); - nsMenuX* AddMenu(mozilla::UniquePtr aMenu); - void LoadMenuItem(nsIContent* inMenuItemContent); - void LoadSubMenu(nsIContent* inMenuContent); - GeckoNSMenu* CreateMenuWithGeckoString(nsString& menuTitle); - - nsTArray> mMenuObjectsArray; - nsString mLabel; - uint32_t mVisibleItemsCount; // cache - nsMenuObjectX* mParent; // [weak] - nsMenuGroupOwnerX* mMenuGroupOwner; // [weak] - // The icon object should never outlive its creating nsMenuX object. - RefPtr mIcon; - GeckoNSMenu* mNativeMenu; // [strong] - MenuDelegate* mMenuDelegate; // [strong] - // nsMenuX objects should always have a valid native menu item. - NSMenuItem* mNativeMenuItem; // [strong] - bool mIsEnabled; - bool mDestroyHandlerCalled; - bool mNeedsRebuild; - bool mConstructed; - bool mVisible; - bool mXBLAttached; -}; - -#endif // nsMenuX_h_ diff --git a/widget/cocoa/nsMenuX.mm b/widget/cocoa/nsMenuX.mm deleted file mode 100644 index 757221eac6..0000000000 --- a/widget/cocoa/nsMenuX.mm +++ /dev/null @@ -1,1051 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 - -#include "nsMenuX.h" -#include "nsMenuItemX.h" -#include "nsMenuUtilsX.h" -#include "nsMenuItemIconX.h" -#include "nsStandaloneNativeMenu.h" - -#include "nsObjCExceptions.h" - -#include "nsToolkit.h" -#include "nsCocoaUtils.h" -#include "nsCOMPtr.h" -#include "prinrval.h" -#include "nsString.h" -#include "nsReadableUtils.h" -#include "nsUnicharUtils.h" -#include "plstr.h" -#include "nsGkAtoms.h" -#include "nsCRT.h" -#include "nsBaseWidget.h" - -#include "nsIDocument.h" -#include "nsIContent.h" -#include "nsIDOMDocument.h" -#include "nsIDocumentObserver.h" -#include "nsIComponentManager.h" -#include "nsIRollupListener.h" -#include "nsIDOMElement.h" -#include "nsBindingManager.h" -#include "nsIServiceManager.h" -#include "nsXULPopupManager.h" -#include "mozilla/dom/ScriptSettings.h" - -#include "jsapi.h" -#include "nsIScriptGlobalObject.h" -#include "nsIScriptContext.h" -#include "nsIXPConnect.h" - -#include "mozilla/MouseEvents.h" - -using namespace mozilla; - -static bool gConstructingMenu = false; -static bool gMenuMethodsSwizzled = false; - -int32_t nsMenuX::sIndexingMenuLevel = 0; - - -// -// Objective-C class used for representedObject -// - -@implementation MenuItemInfo - -- (id) initWithMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner -{ - if ((self = [super init]) != nil) { - [self setMenuGroupOwner:aMenuGroupOwner]; - } - return self; -} - -- (void) dealloc -{ - [self setMenuGroupOwner:nullptr]; - [super dealloc]; -} - -- (nsMenuGroupOwnerX *) menuGroupOwner -{ - return mMenuGroupOwner; -} - -- (void) setMenuGroupOwner:(nsMenuGroupOwnerX *)aMenuGroupOwner -{ - // weak reference as the nsMenuGroupOwnerX owns all of its sub-objects - mMenuGroupOwner = aMenuGroupOwner; - if (aMenuGroupOwner) { - aMenuGroupOwner->AddMenuItemInfoToSet(self); - } -} - -@end - - -// -// nsMenuX -// - -nsMenuX::nsMenuX() -: mVisibleItemsCount(0), mParent(nullptr), mMenuGroupOwner(nullptr), - mNativeMenu(nil), mNativeMenuItem(nil), mIsEnabled(true), - mDestroyHandlerCalled(false), mNeedsRebuild(true), - mConstructed(false), mVisible(true), mXBLAttached(false) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!gMenuMethodsSwizzled) { - nsToolkit::SwizzleMethods([NSMenu class], @selector(_addItem:toTable:), - @selector(nsMenuX_NSMenu_addItem:toTable:), true); - nsToolkit::SwizzleMethods([NSMenu class], @selector(_removeItem:fromTable:), - @selector(nsMenuX_NSMenu_removeItem:fromTable:), true); - // On SnowLeopard the Shortcut framework (which contains the - // SCTGRLIndex class) is loaded on demand, whenever the user first opens - // a menu (which normally hasn't happened yet). So we need to load it - // here explicitly. - dlopen("/System/Library/PrivateFrameworks/Shortcut.framework/Shortcut", RTLD_LAZY); - Class SCTGRLIndexClass = ::NSClassFromString(@"SCTGRLIndex"); - nsToolkit::SwizzleMethods(SCTGRLIndexClass, @selector(indexMenuBarDynamically), - @selector(nsMenuX_SCTGRLIndex_indexMenuBarDynamically)); - - gMenuMethodsSwizzled = true; - } - - mMenuDelegate = [[MenuDelegate alloc] initWithGeckoMenu:this]; - - if (!nsMenuBarX::sNativeEventTarget) - nsMenuBarX::sNativeEventTarget = [[NativeMenuItemTarget alloc] init]; - - MOZ_COUNT_CTOR(nsMenuX); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsMenuX::~nsMenuX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Prevent the icon object from outliving us. - if (mIcon) - mIcon->Destroy(); - - RemoveAll(); - - [mNativeMenu setDelegate:nil]; - [mNativeMenu release]; - [mMenuDelegate release]; - // autorelease the native menu item so that anything else happening to this - // object happens before the native menu item actually dies - [mNativeMenuItem autorelease]; - - // alert the change notifier we don't care no more - if (mContent) - mMenuGroupOwner->UnregisterForContentChanges(mContent); - - MOZ_COUNT_DTOR(nsMenuX); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult nsMenuX::Create(nsMenuObjectX* aParent, nsMenuGroupOwnerX* aMenuGroupOwner, nsIContent* aNode) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mContent = aNode; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, mLabel); - mNativeMenu = CreateMenuWithGeckoString(mLabel); - - // register this menu to be notified when changes are made to our content object - mMenuGroupOwner = aMenuGroupOwner; // weak ref - NS_ASSERTION(mMenuGroupOwner, "No menu owner given, must have one"); - mMenuGroupOwner->RegisterForContentChanges(mContent, this); - - mParent = aParent; - // our parent could be either a menu bar (if we're toplevel) or a menu (if we're a submenu) - -#ifdef DEBUG - nsMenuObjectTypeX parentType = -#endif - mParent->MenuObjectType(); - NS_ASSERTION((parentType == eMenuBarObjectType || parentType == eSubmenuObjectType || parentType == eStandaloneNativeMenuObjectType), - "Menu parent not a menu bar, menu, or native menu!"); - - if (nsMenuUtilsX::NodeIsHiddenOrCollapsed(mContent)) - mVisible = false; - if (mContent->GetChildCount() == 0) - mVisible = false; - - NSString *newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(mLabel); - mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""]; - [mNativeMenuItem setSubmenu:mNativeMenu]; - - SetEnabled(!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, - nsGkAtoms::_true, eCaseMatters)); - - // We call MenuConstruct here because keyboard commands are dependent upon - // native menu items being created. If we only call MenuConstruct when a menu - // is actually selected, then we can't access keyboard commands until the - // menu gets selected, which is bad. - MenuConstruct(); - - mIcon = new nsMenuItemIconX(this, mContent, mNativeMenuItem); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsMenuX::AddMenuItem(nsMenuItemX* aMenuItem) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!aMenuItem) - return NS_ERROR_INVALID_ARG; - - mMenuObjectsArray.AppendElement(aMenuItem); - if (nsMenuUtilsX::NodeIsHiddenOrCollapsed(aMenuItem->Content())) - return NS_OK; - ++mVisibleItemsCount; - - NSMenuItem* newNativeMenuItem = (NSMenuItem*)aMenuItem->NativeData(); - - // add the menu item to this menu - [mNativeMenu addItem:newNativeMenuItem]; - - // set up target/action - [newNativeMenuItem setTarget:nsMenuBarX::sNativeEventTarget]; - [newNativeMenuItem setAction:@selector(menuItemHit:)]; - - // set its command. we get the unique command id from the menubar - [newNativeMenuItem setTag:mMenuGroupOwner->RegisterForCommand(aMenuItem)]; - MenuItemInfo * info = [[MenuItemInfo alloc] initWithMenuGroupOwner:mMenuGroupOwner]; - [newNativeMenuItem setRepresentedObject:info]; - [info release]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsMenuX* nsMenuX::AddMenu(UniquePtr aMenu) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - // aMenu transfers ownership to mMenuObjectsArray and becomes nullptr, so - // we need to keep a raw pointer to access it conveniently. - nsMenuX* menu = aMenu.get(); - mMenuObjectsArray.AppendElement(Move(aMenu)); - - if (nsMenuUtilsX::NodeIsHiddenOrCollapsed(menu->Content())) { - return menu; - } - - ++mVisibleItemsCount; - - // We have to add a menu item and then associate the menu with it - NSMenuItem* newNativeMenuItem = menu->NativeMenuItem(); - if (newNativeMenuItem) { - [mNativeMenu addItem:newNativeMenuItem]; - [newNativeMenuItem setSubmenu:(NSMenu*)menu->NativeData()]; - } - - return menu; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr); -} - -// Includes all items, including hidden/collapsed ones -uint32_t nsMenuX::GetItemCount() -{ - return mMenuObjectsArray.Length(); -} - -// Includes all items, including hidden/collapsed ones -nsMenuObjectX* nsMenuX::GetItemAt(uint32_t aPos) -{ - if (aPos >= (uint32_t)mMenuObjectsArray.Length()) - return NULL; - - return mMenuObjectsArray[aPos].get(); -} - -// Only includes visible items -nsresult nsMenuX::GetVisibleItemCount(uint32_t &aCount) -{ - aCount = mVisibleItemsCount; - return NS_OK; -} - -// Only includes visible items. Note that this is provides O(N) access -// If you need to iterate or search, consider using GetItemAt and doing your own filtering -nsMenuObjectX* nsMenuX::GetVisibleItemAt(uint32_t aPos) -{ - - uint32_t count = mMenuObjectsArray.Length(); - if (aPos >= mVisibleItemsCount || aPos >= count) - return NULL; - - // If there are no invisible items, can provide direct access - if (mVisibleItemsCount == count) - return mMenuObjectsArray[aPos].get(); - - // Otherwise, traverse the array until we find the the item we're looking for. - nsMenuObjectX* item; - uint32_t visibleNodeIndex = 0; - for (uint32_t i = 0; i < count; i++) { - item = mMenuObjectsArray[i].get(); - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(item->Content())) { - if (aPos == visibleNodeIndex) { - // we found the visible node we're looking for, return it - return item; - } - visibleNodeIndex++; - } - } - - return NULL; -} - -nsresult nsMenuX::RemoveAll() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (mNativeMenu) { - // clear command id's - int itemCount = [mNativeMenu numberOfItems]; - for (int i = 0; i < itemCount; i++) - mMenuGroupOwner->UnregisterCommand((uint32_t)[[mNativeMenu itemAtIndex:i] tag]); - // get rid of Cocoa menu items - for (int i = [mNativeMenu numberOfItems] - 1; i >= 0; i--) - [mNativeMenu removeItemAtIndex:i]; - } - - mMenuObjectsArray.Clear(); - mVisibleItemsCount = 0; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsEventStatus nsMenuX::MenuOpened() -{ - // Open the node. - mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::open, NS_LITERAL_STRING("true"), true); - - // Fire a handler. If we're told to stop, don't build the menu at all - bool keepProcessing = OnOpen(); - - if (!mNeedsRebuild || !keepProcessing) - return nsEventStatus_eConsumeNoDefault; - - if (!mConstructed || mNeedsRebuild) { - if (mNeedsRebuild) - RemoveAll(); - - MenuConstruct(); - mConstructed = true; - } - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupShown, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - - return nsEventStatus_eConsumeNoDefault; -} - -void nsMenuX::MenuClosed() -{ - if (mConstructed) { - // Don't close if a handler tells us to stop. - if (!OnClose()) - return; - - if (mNeedsRebuild) - mConstructed = false; - - mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::open, true); - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupHidden, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - - mDestroyHandlerCalled = true; - mConstructed = false; - } -} - -void nsMenuX::MenuConstruct() -{ - mConstructed = false; - gConstructingMenu = true; - - // reset destroy handler flag so that we'll know to fire it next time this menu goes away. - mDestroyHandlerCalled = false; - - //printf("nsMenuX::MenuConstruct called for %s = %d \n", NS_LossyConvertUTF16toASCII(mLabel).get(), mNativeMenu); - - // Retrieve our menupopup. - nsCOMPtr menuPopup; - GetMenuPopupContent(getter_AddRefs(menuPopup)); - if (!menuPopup) { - gConstructingMenu = false; - return; - } - - // bug 365405: Manually wrap the menupopup node to make sure it's bounded - if (!mXBLAttached) { - nsresult rv; - nsCOMPtr xpconnect = - do_GetService(nsIXPConnect::GetCID(), &rv); - if (NS_SUCCEEDED(rv)) { - nsIDocument* ownerDoc = menuPopup->OwnerDoc(); - dom::AutoJSAPI jsapi; - if (ownerDoc && jsapi.Init(ownerDoc->GetInnerWindow())) { - JSContext* cx = jsapi.cx(); - JS::RootedObject ignoredObj(cx); - xpconnect->WrapNative(cx, JS::CurrentGlobalOrNull(cx), menuPopup, - NS_GET_IID(nsISupports), ignoredObj.address()); - mXBLAttached = true; - } - } - } - - // Iterate over the kids - uint32_t count = menuPopup->GetChildCount(); - for (uint32_t i = 0; i < count; i++) { - nsIContent *child = menuPopup->GetChildAt(i); - if (child) { - // depending on the type, create a menu item, separator, or submenu - if (child->IsAnyOfXULElements(nsGkAtoms::menuitem, - nsGkAtoms::menuseparator)) { - LoadMenuItem(child); - } else if (child->IsXULElement(nsGkAtoms::menu)) { - LoadSubMenu(child); - } - } - } // for each menu item - - gConstructingMenu = false; - mNeedsRebuild = false; - // printf("Done building, mMenuObjectsArray.Count() = %d \n", mMenuObjectsArray.Count()); -} - -void nsMenuX::SetRebuild(bool aNeedsRebuild) -{ - if (!gConstructingMenu) - mNeedsRebuild = aNeedsRebuild; -} - -nsresult nsMenuX::SetEnabled(bool aIsEnabled) -{ - if (aIsEnabled != mIsEnabled) { - // we always want to rebuild when this changes - mIsEnabled = aIsEnabled; - [mNativeMenuItem setEnabled:(BOOL)mIsEnabled]; - } - return NS_OK; -} - -nsresult nsMenuX::GetEnabled(bool* aIsEnabled) -{ - NS_ENSURE_ARG_POINTER(aIsEnabled); - *aIsEnabled = mIsEnabled; - return NS_OK; -} - -GeckoNSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& menuTitle) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - NSString* title = [NSString stringWithCharacters:(UniChar*)menuTitle.get() length:menuTitle.Length()]; - GeckoNSMenu* myMenu = [[GeckoNSMenu alloc] initWithTitle:title]; - [myMenu setDelegate:mMenuDelegate]; - - // We don't want this menu to auto-enable menu items because then Cocoa - // overrides our decisions and things get incorrectly enabled/disabled. - [myMenu setAutoenablesItems:NO]; - - // we used to install Carbon event handlers here, but since NSMenu* doesn't - // create its underlying MenuRef until just before display, we delay until - // that happens. Now we install the event handlers when Cocoa notifies - // us that a menu is about to display - see the Cocoa MenuDelegate class. - - return myMenu; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -void nsMenuX::LoadMenuItem(nsIContent* inMenuItemContent) -{ - if (!inMenuItemContent) - return; - - nsAutoString menuitemName; - inMenuItemContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, menuitemName); - - // printf("menuitem %s \n", NS_LossyConvertUTF16toASCII(menuitemName).get()); - - EMenuItemType itemType = eRegularMenuItemType; - if (inMenuItemContent->IsXULElement(nsGkAtoms::menuseparator)) { - itemType = eSeparatorMenuItemType; - } - else { - static nsIContent::AttrValuesArray strings[] = - {&nsGkAtoms::checkbox, &nsGkAtoms::radio, nullptr}; - switch (inMenuItemContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, - strings, eCaseMatters)) { - case 0: itemType = eCheckboxMenuItemType; break; - case 1: itemType = eRadioMenuItemType; break; - } - } - - // Create the item. - nsMenuItemX* menuItem = new nsMenuItemX(); - if (!menuItem) - return; - - nsresult rv = menuItem->Create(this, menuitemName, itemType, mMenuGroupOwner, inMenuItemContent); - if (NS_FAILED(rv)) { - delete menuItem; - return; - } - - AddMenuItem(menuItem); - - // This needs to happen after the nsIMenuItem object is inserted into - // our item array in AddMenuItem() - menuItem->SetupIcon(); -} - -void nsMenuX::LoadSubMenu(nsIContent* inMenuContent) -{ - auto menu = MakeUnique(); - if (!menu) - return; - - nsresult rv = menu->Create(this, mMenuGroupOwner, inMenuContent); - if (NS_FAILED(rv)) - return; - - // |menu|'s ownership is transfer to AddMenu but, if it is successfully - // added, we can access it via the returned raw pointer. - nsMenuX* menu_ptr = AddMenu(Move(menu)); - - // This needs to happen after the nsIMenu object is inserted into - // our item array in AddMenu() - if (menu_ptr) { - menu_ptr->SetupIcon(); - } -} - -// This menu is about to open. Returns TRUE if we should keep processing the event, -// FALSE if the handler wants to stop the opening of the menu. -bool nsMenuX::OnOpen() -{ - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupShowing, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - - nsresult rv = NS_OK; - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - rv = dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault) - return false; - - // If the open is going to succeed we need to walk our menu items, checking to - // see if any of them have a command attribute. If so, several attributes - // must potentially be updated. - - // Get new popup content first since it might have changed as a result of the - // eXULPopupShowing event above. - GetMenuPopupContent(getter_AddRefs(popupContent)); - if (!popupContent) - return true; - - nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm) { - pm->UpdateMenuItems(popupContent); - } - - return true; -} - -// Returns TRUE if we should keep processing the event, FALSE if the handler -// wants to stop the closing of the menu. -bool nsMenuX::OnClose() -{ - if (mDestroyHandlerCalled) - return true; - - nsEventStatus status = nsEventStatus_eIgnore; - WidgetMouseEvent event(true, eXULPopupHiding, nullptr, - WidgetMouseEvent::eReal); - - nsCOMPtr popupContent; - GetMenuPopupContent(getter_AddRefs(popupContent)); - - nsresult rv = NS_OK; - nsIContent* dispatchTo = popupContent ? popupContent : mContent; - rv = dispatchTo->DispatchDOMEvent(&event, nullptr, nullptr, &status); - - mDestroyHandlerCalled = true; - - if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault) - return false; - - return true; -} - -// Find the |menupopup| child in the |popup| representing this menu. It should be one -// of a very few children so we won't be iterating over a bazillion menu items to find -// it (so the strcmp won't kill us). -void nsMenuX::GetMenuPopupContent(nsIContent** aResult) -{ - if (!aResult) - return; - *aResult = nullptr; - - // Check to see if we are a "menupopup" node (if we are a native menu). - { - int32_t dummy; - nsCOMPtr tag = mContent->OwnerDoc()->BindingManager()->ResolveTag(mContent, &dummy); - if (tag == nsGkAtoms::menupopup) { - *aResult = mContent; - NS_ADDREF(*aResult); - return; - } - } - - // Otherwise check our child nodes. - - uint32_t count = mContent->GetChildCount(); - - for (uint32_t i = 0; i < count; i++) { - int32_t dummy; - nsIContent *child = mContent->GetChildAt(i); - nsCOMPtr tag = child->OwnerDoc()->BindingManager()->ResolveTag(child, &dummy); - if (tag == nsGkAtoms::menupopup) { - *aResult = child; - NS_ADDREF(*aResult); - return; - } - } -} - -NSMenuItem* nsMenuX::NativeMenuItem() -{ - return mNativeMenuItem; -} - -bool nsMenuX::IsXULHelpMenu(nsIContent* aMenuContent) -{ - bool retval = false; - if (aMenuContent) { - nsAutoString id; - aMenuContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id); - if (id.Equals(NS_LITERAL_STRING("helpMenu"))) - retval = true; - } - return retval; -} - -// -// nsChangeObserver -// - -void nsMenuX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aContent, - nsIAtom *aAttribute) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // ignore the |open| attribute, which is by far the most common - if (gConstructingMenu || (aAttribute == nsGkAtoms::open)) - return; - - nsMenuObjectTypeX parentType = mParent->MenuObjectType(); - - if (aAttribute == nsGkAtoms::disabled) { - SetEnabled(!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled, - nsGkAtoms::_true, eCaseMatters)); - } - else if (aAttribute == nsGkAtoms::label) { - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, mLabel); - - // invalidate my parent. If we're a submenu parent, we have to rebuild - // the parent menu in order for the changes to be picked up. If we're - // a regular menu, just change the title and redraw the menubar. - if (parentType == eMenuBarObjectType) { - // reuse the existing menu, to avoid rebuilding the root menu bar. - NS_ASSERTION(mNativeMenu, "nsMenuX::AttributeChanged: invalid menu handle."); - NSString *newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(mLabel); - [mNativeMenu setTitle:newCocoaLabelString]; - } - else if (parentType == eSubmenuObjectType) { - static_cast(mParent)->SetRebuild(true); - } - else if (parentType == eStandaloneNativeMenuObjectType) { - static_cast(mParent)->GetMenuXObject()->SetRebuild(true); - } - } - else if (aAttribute == nsGkAtoms::hidden || aAttribute == nsGkAtoms::collapsed) { - SetRebuild(true); - - bool contentIsHiddenOrCollapsed = nsMenuUtilsX::NodeIsHiddenOrCollapsed(mContent); - - // don't do anything if the state is correct already - if (contentIsHiddenOrCollapsed != mVisible) - return; - - if (contentIsHiddenOrCollapsed) { - if (parentType == eMenuBarObjectType || - parentType == eSubmenuObjectType || - parentType == eStandaloneNativeMenuObjectType) { - NSMenu* parentMenu = (NSMenu*)mParent->NativeData(); - // An exception will get thrown if we try to remove an item that isn't - // in the menu. - if ([parentMenu indexOfItem:mNativeMenuItem] != -1) - [parentMenu removeItem:mNativeMenuItem]; - mVisible = false; - } - } - else { - if (parentType == eMenuBarObjectType || - parentType == eSubmenuObjectType || - parentType == eStandaloneNativeMenuObjectType) { - int insertionIndex = nsMenuUtilsX::CalculateNativeInsertionPoint(mParent, this); - if (parentType == eMenuBarObjectType) { - // Before inserting we need to figure out if we should take the native - // application menu into account. - nsMenuBarX* mb = static_cast(mParent); - if (mb->MenuContainsAppMenu()) - insertionIndex++; - } - NSMenu* parentMenu = (NSMenu*)mParent->NativeData(); - [parentMenu insertItem:mNativeMenuItem atIndex:insertionIndex]; - [mNativeMenuItem setSubmenu:mNativeMenu]; - mVisible = true; - } - } - } - else if (aAttribute == nsGkAtoms::image) { - SetupIcon(); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void nsMenuX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, - int32_t aIndexInContainer) -{ - if (gConstructingMenu) - return; - - SetRebuild(true); - mMenuGroupOwner->UnregisterForContentChanges(aChild); -} - -void nsMenuX::ObserveContentInserted(nsIDocument *aDocument, nsIContent* aContainer, - nsIContent *aChild) -{ - if (gConstructingMenu) - return; - - SetRebuild(true); -} - -nsresult nsMenuX::SetupIcon() -{ - // In addition to out-of-memory, menus that are children of the menu bar - // will not have mIcon set. - if (!mIcon) - return NS_ERROR_OUT_OF_MEMORY; - - return mIcon->SetupIcon(); -} - -// -// MenuDelegate Objective-C class, used to set up Carbon events -// - -@implementation MenuDelegate - -- (id)initWithGeckoMenu:(nsMenuX*)geckoMenu -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - NS_ASSERTION(geckoMenu, "Cannot initialize native menu delegate with NULL gecko menu! Will crash!"); - mGeckoMenu = geckoMenu; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item -{ - if (!menu || !item || !mGeckoMenu) - return; - - nsMenuObjectX* target = mGeckoMenu->GetVisibleItemAt((uint32_t)[menu indexOfItem:item]); - if (target && (target->MenuObjectType() == eMenuItemObjectType)) { - nsMenuItemX* targetMenuItem = static_cast(target); - bool handlerCalledPreventDefault; // but we don't actually care - targetMenuItem->DispatchDOMEvent(NS_LITERAL_STRING("DOMMenuItemActive"), &handlerCalledPreventDefault); - } -} - -- (void)menuWillOpen:(NSMenu *)menu -{ - if (!mGeckoMenu) - return; - - // Don't do anything while the OS is (re)indexing our menus (on Leopard and - // higher). This stops the Help menu from being able to search in our - // menus, but it also resolves many other problems. - if (nsMenuX::sIndexingMenuLevel > 0) - return; - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - if (rollupListener) { - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (rollupWidget) { - rollupListener->Rollup(0, true, nullptr, nullptr); - [menu cancelTracking]; - return; - } - } - mGeckoMenu->MenuOpened(); -} - -- (void)menuDidClose:(NSMenu *)menu -{ - if (!mGeckoMenu) - return; - - // Don't do anything while the OS is (re)indexing our menus (on Leopard and - // higher). This stops the Help menu from being able to search in our - // menus, but it also resolves many other problems. - if (nsMenuX::sIndexingMenuLevel > 0) - return; - - mGeckoMenu->MenuClosed(); -} - -@end - -// OS X Leopard (at least as of 10.5.2) has an obscure bug triggered by some -// behavior that's present in Mozilla.org browsers but not (as best I can -// tell) in Apple products like Safari. (It's not yet clear exactly what this -// behavior is.) -// -// The bug is that sometimes you crash on quit in nsMenuX::RemoveAll(), on a -// call to [NSMenu removeItemAtIndex:]. The crash is caused by trying to -// access a deleted NSMenuItem object (sometimes (perhaps always?) by trying -// to send it a _setChangedFlags: message). Though this object was deleted -// some time ago, it remains registered as a potential target for a particular -// key equivalent. So when [NSMenu removeItemAtIndex:] removes the current -// target for that same key equivalent, the OS tries to "activate" the -// previous target. -// -// The underlying reason appears to be that NSMenu's _addItem:toTable: and -// _removeItem:fromTable: methods (which are used to keep a hashtable of -// registered key equivalents) don't properly "retain" and "release" -// NSMenuItem objects as they are added to and removed from the hashtable. -// -// Our (hackish) workaround is to shadow the OS's hashtable with another -// hastable of our own (gShadowKeyEquivDB), and use it to "retain" and -// "release" NSMenuItem objects as needed. This resolves bmo bugs 422287 and -// 423669. When (if) Apple fixes this bug, we can remove this workaround. - -static NSMutableDictionary *gShadowKeyEquivDB = nil; - -// Class for values in gShadowKeyEquivDB. - -@interface KeyEquivDBItem : NSObject -{ - NSMenuItem *mItem; - NSMutableSet *mTables; -} - -- (id)initWithItem:(NSMenuItem *)aItem table:(NSMapTable *)aTable; -- (BOOL)hasTable:(NSMapTable *)aTable; -- (int)addTable:(NSMapTable *)aTable; -- (int)removeTable:(NSMapTable *)aTable; - -@end - -@implementation KeyEquivDBItem - -- (id)initWithItem:(NSMenuItem *)aItem table:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if (!gShadowKeyEquivDB) - gShadowKeyEquivDB = [[NSMutableDictionary alloc] init]; - self = [super init]; - if (aItem && aTable) { - mTables = [[NSMutableSet alloc] init]; - mItem = [aItem retain]; - [mTables addObject:[NSValue valueWithPointer:aTable]]; - } else { - mTables = nil; - mItem = nil; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mTables) - [mTables release]; - if (mItem) - [mItem release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (BOOL)hasTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return [mTables member:[NSValue valueWithPointer:aTable]] ? YES : NO; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); -} - -// Does nothing if aTable (its index value) is already present in mTables. -- (int)addTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (aTable) - [mTables addObject:[NSValue valueWithPointer:aTable]]; - return [mTables count]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -- (int)removeTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (aTable) { - NSValue *objectToRemove = - [mTables member:[NSValue valueWithPointer:aTable]]; - if (objectToRemove) - [mTables removeObject:objectToRemove]; - } - return [mTables count]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0); -} - -@end - -@interface NSMenu (MethodSwizzling) -+ (void)nsMenuX_NSMenu_addItem:(NSMenuItem *)aItem toTable:(NSMapTable *)aTable; -+ (void)nsMenuX_NSMenu_removeItem:(NSMenuItem *)aItem fromTable:(NSMapTable *)aTable; -@end - -@implementation NSMenu (MethodSwizzling) - -+ (void)nsMenuX_NSMenu_addItem:(NSMenuItem *)aItem toTable:(NSMapTable *)aTable -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (aItem && aTable) { - NSValue *key = [NSValue valueWithPointer:aItem]; - KeyEquivDBItem *shadowItem = [gShadowKeyEquivDB objectForKey:key]; - if (shadowItem) { - [shadowItem addTable:aTable]; - } else { - shadowItem = [[KeyEquivDBItem alloc] initWithItem:aItem table:aTable]; - [gShadowKeyEquivDB setObject:shadowItem forKey:key]; - // Release after [NSMutableDictionary setObject:forKey:] retains it (so - // that it will get dealloced when removeObjectForKey: is called). - [shadowItem release]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; - - [self nsMenuX_NSMenu_addItem:aItem toTable:aTable]; -} - -+ (void)nsMenuX_NSMenu_removeItem:(NSMenuItem *)aItem fromTable:(NSMapTable *)aTable -{ - [self nsMenuX_NSMenu_removeItem:aItem fromTable:aTable]; - - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (aItem && aTable) { - NSValue *key = [NSValue valueWithPointer:aItem]; - KeyEquivDBItem *shadowItem = [gShadowKeyEquivDB objectForKey:key]; - if (shadowItem && [shadowItem hasTable:aTable]) { - if (![shadowItem removeTable:aTable]) - [gShadowKeyEquivDB removeObjectForKey:key]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end - -// This class is needed to keep track of when the OS is (re)indexing all of -// our menus. This appears to only happen on Leopard and higher, and can -// be triggered by opening the Help menu. Some operations are unsafe while -// this is happening -- notably the calls to [[NSImage alloc] -// initWithSize:imageRect.size] and [newImage lockFocus] in nsMenuItemIconX:: -// OnStopFrame(). But we don't yet have a complete list, and Apple doesn't -// yet have any documentation on this subject. (Apple also doesn't yet have -// any documented way to find the information we seek here.) The "original" -// of this class (the one whose indexMenuBarDynamically method we hook) is -// defined in the Shortcut framework in /System/Library/PrivateFrameworks. -@interface NSObject (SCTGRLIndexMethodSwizzling) -- (void)nsMenuX_SCTGRLIndex_indexMenuBarDynamically; -@end - -@implementation NSObject (SCTGRLIndexMethodSwizzling) - -- (void)nsMenuX_SCTGRLIndex_indexMenuBarDynamically -{ - // This method appears to be called (once) whenever the OS (re)indexes our - // menus. sIndexingMenuLevel is a int32_t just in case it might be - // reentered. As it's running, it spawns calls to two undocumented - // HIToolbox methods (_SimulateMenuOpening() and _SimulateMenuClosed()), - // which "simulate" the opening and closing of our menus without actually - // displaying them. - ++nsMenuX::sIndexingMenuLevel; - [self nsMenuX_SCTGRLIndex_indexMenuBarDynamically]; - --nsMenuX::sIndexingMenuLevel; -} - -@end diff --git a/widget/cocoa/nsNativeThemeCocoa.h b/widget/cocoa/nsNativeThemeCocoa.h deleted file mode 100644 index 23f2bc4d32..0000000000 --- a/widget/cocoa/nsNativeThemeCocoa.h +++ /dev/null @@ -1,178 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsNativeThemeCocoa_h_ -#define nsNativeThemeCocoa_h_ - -#import -#import - -#include "nsITheme.h" -#include "nsCOMPtr.h" -#include "nsIAtom.h" -#include "nsNativeTheme.h" - -@class CellDrawView; -@class NSProgressBarCell; -@class ContextAwareSearchFieldCell; -class nsDeviceContext; -struct SegmentedControlRenderSettings; - -namespace mozilla { -class EventStates; -} // namespace mozilla - -class nsNativeThemeCocoa : private nsNativeTheme, - public nsITheme -{ -public: - enum { - eThemeGeometryTypeTitlebar = eThemeGeometryTypeUnknown + 1, - eThemeGeometryTypeToolbar, - eThemeGeometryTypeToolbox, - eThemeGeometryTypeWindowButtons, - eThemeGeometryTypeFullscreenButton, - eThemeGeometryTypeMenu, - eThemeGeometryTypeHighlightedMenuItem, - eThemeGeometryTypeVibrancyLight, - eThemeGeometryTypeVibrancyDark, - eThemeGeometryTypeTooltip, - eThemeGeometryTypeSheet, - eThemeGeometryTypeSourceList, - eThemeGeometryTypeSourceListSelection, - eThemeGeometryTypeActiveSourceListSelection - }; - - nsNativeThemeCocoa(); - - NS_DECL_ISUPPORTS_INHERITED - - // The nsITheme interface. - NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) override; - NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) override; - - virtual bool GetWidgetPadding(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) override; - - virtual bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame, - uint8_t aWidgetType, nsRect* aOverflowRect) override; - - NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame, - uint8_t aWidgetType, - mozilla::LayoutDeviceIntSize* aResult, bool* aIsOverridable) override; - NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, - nsIAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) override; - NS_IMETHOD ThemeChanged() override; - bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, uint8_t aWidgetType) override; - bool WidgetIsContainer(uint8_t aWidgetType) override; - bool ThemeDrawsFocusForWidget(uint8_t aWidgetType) override; - bool ThemeNeedsComboboxDropmarker() override; - virtual bool WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) override; - virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, - uint8_t aWidgetType) override; - virtual bool WidgetProvidesFontSmoothingBackgroundColor(nsIFrame* aFrame, uint8_t aWidgetType, - nscolor* aColor) override; - virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame, - uint8_t aWidgetType) override; - virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) override; - - void DrawProgress(CGContextRef context, const HIRect& inBoxRect, - bool inIsIndeterminate, bool inIsHorizontal, - double inValue, double inMaxValue, nsIFrame* aFrame); - - static void DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect, - CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped); - -protected: - virtual ~nsNativeThemeCocoa(); - - nsIntMargin DirectionAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame); - nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter); - CGRect SeparatorAdjustedRect(CGRect aRect, nsIFrame* aLeft, - nsIFrame* aCurrent, nsIFrame* aRight); - bool IsWindowSheet(nsIFrame* aFrame); - - // HITheme drawing routines - void DrawFrame(CGContextRef context, HIThemeFrameKind inKind, - const HIRect& inBoxRect, bool inReadOnly, - mozilla::EventStates inState); - void DrawMeter(CGContextRef context, const HIRect& inBoxRect, - nsIFrame* aFrame); - void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, - mozilla::EventStates inState, nsIFrame* aFrame, - const SegmentedControlRenderSettings& aSettings); - void DrawTabPanel(CGContextRef context, const HIRect& inBoxRect, nsIFrame* aFrame); - void DrawScale(CGContextRef context, const HIRect& inBoxRect, - mozilla::EventStates inState, bool inDirection, - bool inIsReverse, int32_t inCurrentValue, int32_t inMinValue, - int32_t inMaxValue, nsIFrame* aFrame); - void DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, - const HIRect& inBoxRect, bool inSelected, - mozilla::EventStates inState, nsIFrame* aFrame); - void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame, mozilla::EventStates inState); - void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, - mozilla::EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame, float aOriginalHeight); - void DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect, - mozilla::EventStates inState, nsIFrame* aFrame, - const NSSize& aIconSize, NSString* aImageName, - bool aCenterHorizontally); - void DrawButton(CGContextRef context, ThemeButtonKind inKind, - const HIRect& inBoxRect, bool inIsDefault, - ThemeButtonValue inValue, ThemeButtonAdornment inAdornment, - mozilla::EventStates inState, nsIFrame* aFrame); - void DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect, - mozilla::EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame); - void DrawDropdown(CGContextRef context, const HIRect& inBoxRect, - mozilla::EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame); - void DrawSpinButtons(CGContextRef context, ThemeButtonKind inKind, - const HIRect& inBoxRect, ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - mozilla::EventStates inState, nsIFrame* aFrame); - void DrawSpinButton(CGContextRef context, ThemeButtonKind inKind, - const HIRect& inBoxRect, ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - mozilla::EventStates inState, - nsIFrame* aFrame, uint8_t aWidgetType); - void DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect, - NSWindow* aWindow); - void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame *aFrame); - void DrawResizer(CGContextRef cgContext, const HIRect& aRect, nsIFrame *aFrame); - - // Scrollbars - void GetScrollbarPressStates(nsIFrame *aFrame, - mozilla::EventStates aButtonStates[]); - nsIFrame* GetParentScrollbarFrame(nsIFrame *aFrame); - bool IsParentScrollbarRolledOver(nsIFrame* aFrame); - -private: - NSButtonCell* mDisclosureButtonCell; - NSButtonCell* mHelpButtonCell; - NSButtonCell* mPushButtonCell; - NSButtonCell* mRadioButtonCell; - NSButtonCell* mCheckboxCell; - ContextAwareSearchFieldCell* mSearchFieldCell; - NSPopUpButtonCell* mDropdownCell; - NSComboBoxCell* mComboBoxCell; - NSProgressBarCell* mProgressBarCell; - NSLevelIndicatorCell* mMeterBarCell; - CellDrawView* mCellDrawView; -}; - -#endif // nsNativeThemeCocoa_h_ diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm deleted file mode 100644 index 056c453f2a..0000000000 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ /dev/null @@ -1,3961 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsNativeThemeCocoa.h" - -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/Helpers.h" -#include "nsChildView.h" -#include "nsDeviceContext.h" -#include "nsLayoutUtils.h" -#include "nsObjCExceptions.h" -#include "nsNumberControlFrame.h" -#include "nsRangeFrame.h" -#include "nsRenderingContext.h" -#include "nsRect.h" -#include "nsSize.h" -#include "nsThemeConstants.h" -#include "nsIPresShell.h" -#include "nsPresContext.h" -#include "nsIContent.h" -#include "nsIDocument.h" -#include "nsIFrame.h" -#include "nsIAtom.h" -#include "nsNameSpaceManager.h" -#include "nsPresContext.h" -#include "nsGkAtoms.h" -#include "nsCocoaFeatures.h" -#include "nsCocoaWindow.h" -#include "nsNativeThemeColors.h" -#include "nsIScrollableFrame.h" -#include "mozilla/EventStates.h" -#include "mozilla/dom/Element.h" -#include "mozilla/dom/HTMLMeterElement.h" -#include "nsLookAndFeel.h" -#include "VibrancyManager.h" - -#include "gfxContext.h" -#include "gfxQuartzSurface.h" -#include "gfxQuartzNativeDrawing.h" -#include - -using namespace mozilla; -using namespace mozilla::gfx; -using mozilla::dom::HTMLMeterElement; - -#define DRAW_IN_FRAME_DEBUG 0 -#define SCROLLBARS_VISUAL_DEBUG 0 - -// private Quartz routines needed here -extern "C" { - CG_EXTERN void CGContextSetCTM(CGContextRef, CGAffineTransform); - CG_EXTERN void CGContextSetBaseCTM(CGContextRef, CGAffineTransform); - typedef CFTypeRef CUIRendererRef; - void CUIDraw(CUIRendererRef r, CGRect rect, CGContextRef ctx, CFDictionaryRef options, CFDictionaryRef* result); -} - -// Workaround for NSCell control tint drawing -// Without this workaround, NSCells are always drawn with the clear control tint -// as long as they're not attached to an NSControl which is a subview of an active window. -// XXXmstange Why doesn't Webkit need this? -@implementation NSCell (ControlTintWorkaround) -- (int)_realControlTint { return [self controlTint]; } -@end - -// The purpose of this class is to provide objects that can be used when drawing -// NSCells using drawWithFrame:inView: without causing any harm. The only -// messages that will be sent to such an object are "isFlipped" and -// "currentEditor": isFlipped needs to return YES in order to avoid drawing bugs -// on 10.4 (see bug 465069); currentEditor (which isn't even a method of -// NSView) will be called when drawing search fields, and we only provide it in -// order to prevent "unrecognized selector" exceptions. -// There's no need to pass the actual NSView that we're drawing into to -// drawWithFrame:inView:. What's more, doing so even causes unnecessary -// invalidations as soon as we draw a focusring! -@interface CellDrawView : NSView - -@end; - -@implementation CellDrawView - -- (BOOL)isFlipped -{ - return YES; -} - -- (NSText*)currentEditor -{ - return nil; -} - -@end - -// These two classes don't actually add any behavior over NSButtonCell. Their -// purpose is to make it easy to distinguish NSCell objects that are used for -// drawing radio buttons / checkboxes from other cell types. -// The class names are made up, there are no classes with these names in AppKit. -// The reason we need them is that calling [cell setButtonType:NSRadioButton] -// doesn't leave an easy-to-check "marker" on the cell object - there is no -// -[NSButtonCell buttonType] method. -@interface RadioButtonCell : NSButtonCell -@end; -@implementation RadioButtonCell @end; -@interface CheckboxCell : NSButtonCell -@end; -@implementation CheckboxCell @end; - -static void -DrawFocusRingForCellIfNeeded(NSCell* aCell, NSRect aWithFrame, NSView* aInView) -{ - if ([aCell showsFirstResponder]) { - CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextSaveGState(cgContext); - - // It's important to set the focus ring style before we enter the - // transparency layer so that the transparency layer only contains - // the normal button mask without the focus ring, and the conversion - // to the focus ring shape happens only when the transparency layer is - // ended. - NSSetFocusRingStyle(NSFocusRingOnly); - - // We need to draw the whole button into a transparency layer because - // many button types are composed of multiple parts, and if these parts - // were drawn while the focus ring style was active, each individual part - // would produce a focus ring for itself. But we only want one focus ring - // for the whole button. The transparency layer is a way to merge the - // individual button parts together before the focus ring shape is - // calculated. - CGContextBeginTransparencyLayerWithRect(cgContext, NSRectToCGRect(aWithFrame), 0); - [aCell drawFocusRingMaskWithFrame:aWithFrame inView:aInView]; - CGContextEndTransparencyLayer(cgContext); - - CGContextRestoreGState(cgContext); - } -} - -static bool -FocusIsDrawnByDrawWithFrame(NSCell* aCell) -{ -#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - // When building with the 10.8 SDK or higher, focus rings don't draw as part - // of -[NSCell drawWithFrame:inView:] and must be drawn by a separate call - // to -[NSCell drawFocusRingMaskWithFrame:inView:]; . - // See the NSButtonCell section under - // https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/#X10_8Notes - return false; -#else - if (!nsCocoaFeatures::OnYosemiteOrLater()) { - // When building with the 10.7 SDK or lower, focus rings always draw as - // part of -[NSCell drawWithFrame:inView:] if the build is run on 10.9 or - // lower. - return true; - } - - // On 10.10, whether the focus ring is drawn as part of - // -[NSCell drawWithFrame:inView:] depends on the cell type. - // Radio buttons and checkboxes draw their own focus rings, other cell - // types need -[NSCell drawFocusRingMaskWithFrame:inView:]. - return [aCell isKindOfClass:[RadioButtonCell class]] || - [aCell isKindOfClass:[CheckboxCell class]]; -#endif -} - -static void -DrawCellIncludingFocusRing(NSCell* aCell, NSRect aWithFrame, NSView* aInView) -{ - [aCell drawWithFrame:aWithFrame inView:aInView]; - - if (!FocusIsDrawnByDrawWithFrame(aCell)) { - DrawFocusRingForCellIfNeeded(aCell, aWithFrame, aInView); - } -} - -/** - * NSProgressBarCell is used to draw progress bars of any size. - */ -@interface NSProgressBarCell : NSCell -{ - /*All instance variables are private*/ - double mValue; - double mMax; - bool mIsIndeterminate; - bool mIsHorizontal; -} - -- (void)setValue:(double)value; -- (double)value; -- (void)setMax:(double)max; -- (double)max; -- (void)setIndeterminate:(bool)aIndeterminate; -- (bool)isIndeterminate; -- (void)setHorizontal:(bool)aIsHorizontal; -- (bool)isHorizontal; -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; -@end - -@implementation NSProgressBarCell - -- (void)setMax:(double)aMax -{ - mMax = aMax; -} - -- (double)max -{ - return mMax; -} - -- (void)setValue:(double)aValue -{ - mValue = aValue; -} - -- (double)value -{ - return mValue; -} - -- (void)setIndeterminate:(bool)aIndeterminate -{ - mIsIndeterminate = aIndeterminate; -} - -- (bool)isIndeterminate -{ - return mIsIndeterminate; -} - -- (void)setHorizontal:(bool)aIsHorizontal -{ - mIsHorizontal = aIsHorizontal; -} - -- (bool)isHorizontal -{ - return mIsHorizontal; -} - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView -{ - CGContext* cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - - HIThemeTrackDrawInfo tdi; - - tdi.version = 0; - tdi.min = 0; - - tdi.value = INT32_MAX * (mValue / mMax); - tdi.max = INT32_MAX; - tdi.bounds = NSRectToCGRect(cellFrame); - tdi.attributes = mIsHorizontal ? kThemeTrackHorizontal : 0; - tdi.enableState = [self controlTint] == NSClearControlTint ? kThemeTrackInactive - : kThemeTrackActive; - - NSControlSize size = [self controlSize]; - if (size == NSRegularControlSize) { - tdi.kind = mIsIndeterminate ? kThemeLargeIndeterminateBar - : kThemeLargeProgressBar; - } else { - NS_ASSERTION(size == NSSmallControlSize, - "We shouldn't have another size than small and regular for the moment"); - tdi.kind = mIsIndeterminate ? kThemeMediumIndeterminateBar - : kThemeMediumProgressBar; - } - - int32_t stepsPerSecond = mIsIndeterminate ? 60 : 30; - int32_t milliSecondsPerStep = 1000 / stepsPerSecond; - tdi.trackInfo.progress.phase = uint8_t(PR_IntervalToMilliseconds(PR_IntervalNow()) / - milliSecondsPerStep); - - HIThemeDrawTrack(&tdi, NULL, cgContext, kHIThemeOrientationNormal); -} - -@end - -@interface ContextAwareSearchFieldCell : NSSearchFieldCell -{ - nsIFrame* mContext; -} - -// setContext: stores the searchfield nsIFrame so that it can be consulted -// during painting. Please reset this by calling setContext:nullptr as soon as -// you're done with painting because we don't want to keep a dangling pointer. -- (void)setContext:(nsIFrame*)aContext; -@end - -@implementation ContextAwareSearchFieldCell - -- (id)initTextCell:(NSString*)aString -{ - if ((self = [super initTextCell:aString])) { - mContext = nullptr; - } - return self; -} - -- (void)setContext:(nsIFrame*)aContext -{ - mContext = aContext; -} - -static BOOL IsToolbarStyleContainer(nsIFrame* aFrame) -{ - nsIContent* content = aFrame->GetContent(); - if (!content) - return NO; - - if (content->IsAnyOfXULElements(nsGkAtoms::toolbar, - nsGkAtoms::toolbox, - nsGkAtoms::statusbar)) - return YES; - - switch (aFrame->StyleDisplay()->mAppearance) { - case NS_THEME_TOOLBAR: - case NS_THEME_STATUSBAR: - return YES; - default: - return NO; - } -} - -- (BOOL)_isToolbarMode -{ - // On 10.7, searchfields have two different styles, depending on whether - // the searchfield is on top of of window chrome. This function is called on - // 10.7 during drawing in order to determine which style to use. - for (nsIFrame* frame = mContext; frame; frame = frame->GetParent()) { - if (IsToolbarStyleContainer(frame)) { - return YES; - } - } - return NO; -} - -@end - -// Workaround for Bug 542048 -// On 64-bit, NSSearchFieldCells don't draw focus rings. -#if defined(__x86_64__) - -@interface SearchFieldCellWithFocusRing : ContextAwareSearchFieldCell {} @end - -@implementation SearchFieldCellWithFocusRing - -- (void)drawWithFrame:(NSRect)rect inView:(NSView*)controlView -{ - [super drawWithFrame:rect inView:controlView]; - - if (FocusIsDrawnByDrawWithFrame(self)) { - // For some reason, -[NSSearchFieldCell drawWithFrame:inView] doesn't draw a - // focus ring in 64 bit mode, no matter what SDK is used or what OS X version - // we're running on. But if FocusIsDrawnByDrawWithFrame(self), then our - // caller expects us to draw a focus ring. So we just do that here. - DrawFocusRingForCellIfNeeded(self, rect, controlView); - } -} - -- (void)drawFocusRingMaskWithFrame:(NSRect)rect inView:(NSView*)controlView -{ - // By default this draws nothing. I don't know why. - // We just draw the search field again. It's a great mask shape for its own - // focus ring. - [super drawWithFrame:rect inView:controlView]; -} - -@end - -#endif - -#define HITHEME_ORIENTATION kHIThemeOrientationNormal - -static CGFloat kMaxFocusRingWidth = 0; // initialized by the nsNativeThemeCocoa constructor - -// These enums are for indexing into the margin array. -enum { - leopardOSorlater = 0, // 10.6 - 10.9 - yosemiteOSorlater = 1 // 10.10+ -}; - -enum { - miniControlSize, - smallControlSize, - regularControlSize -}; - -enum { - leftMargin, - topMargin, - rightMargin, - bottomMargin -}; - -static size_t EnumSizeForCocoaSize(NSControlSize cocoaControlSize) { - if (cocoaControlSize == NSMiniControlSize) - return miniControlSize; - else if (cocoaControlSize == NSSmallControlSize) - return smallControlSize; - else - return regularControlSize; -} - -static NSControlSize CocoaSizeForEnum(int32_t enumControlSize) { - if (enumControlSize == miniControlSize) - return NSMiniControlSize; - else if (enumControlSize == smallControlSize) - return NSSmallControlSize; - else - return NSRegularControlSize; -} - -static NSString* CUIControlSizeForCocoaSize(NSControlSize aControlSize) -{ - if (aControlSize == NSRegularControlSize) - return @"regular"; - else if (aControlSize == NSSmallControlSize) - return @"small"; - else - return @"mini"; -} - -static void InflateControlRect(NSRect* rect, NSControlSize cocoaControlSize, const float marginSet[][3][4]) -{ - if (!marginSet) - return; - - static int osIndex = nsCocoaFeatures::OnYosemiteOrLater() ? - yosemiteOSorlater : leopardOSorlater; - size_t controlSize = EnumSizeForCocoaSize(cocoaControlSize); - const float* buttonMargins = marginSet[osIndex][controlSize]; - rect->origin.x -= buttonMargins[leftMargin]; - rect->origin.y -= buttonMargins[bottomMargin]; - rect->size.width += buttonMargins[leftMargin] + buttonMargins[rightMargin]; - rect->size.height += buttonMargins[bottomMargin] + buttonMargins[topMargin]; -} - -static ChildView* ChildViewForFrame(nsIFrame* aFrame) -{ - if (!aFrame) - return nil; - - nsIWidget* widget = aFrame->GetNearestWidget(); - if (!widget) - return nil; - - NSWindow* window = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); - return [window isKindOfClass:[BaseWindow class]] ? [(BaseWindow*)window mainChildView] : nil; -} - -static NSWindow* NativeWindowForFrame(nsIFrame* aFrame, - nsIWidget** aTopLevelWidget = NULL) -{ - if (!aFrame) - return nil; - - nsIWidget* widget = aFrame->GetNearestWidget(); - if (!widget) - return nil; - - nsIWidget* topLevelWidget = widget->GetTopLevelWidget(); - if (aTopLevelWidget) - *aTopLevelWidget = topLevelWidget; - - return (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW); -} - -static NSSize -WindowButtonsSize(nsIFrame* aFrame) -{ - NSWindow* window = NativeWindowForFrame(aFrame); - if (!window) { - // Return fallback values. - return NSMakeSize(54, 16); - } - - NSRect buttonBox = NSZeroRect; - NSButton* closeButton = [window standardWindowButton:NSWindowCloseButton]; - if (closeButton) { - buttonBox = NSUnionRect(buttonBox, [closeButton frame]); - } - NSButton* minimizeButton = [window standardWindowButton:NSWindowMiniaturizeButton]; - if (minimizeButton) { - buttonBox = NSUnionRect(buttonBox, [minimizeButton frame]); - } - NSButton* zoomButton = [window standardWindowButton:NSWindowZoomButton]; - if (zoomButton) { - buttonBox = NSUnionRect(buttonBox, [zoomButton frame]); - } - return buttonBox.size; -} - -static BOOL FrameIsInActiveWindow(nsIFrame* aFrame) -{ - nsIWidget* topLevelWidget = NULL; - NSWindow* win = NativeWindowForFrame(aFrame, &topLevelWidget); - if (!topLevelWidget || !win) - return YES; - - // XUL popups, e.g. the toolbar customization popup, can't become key windows, - // but controls in these windows should still get the active look. - if (topLevelWidget->WindowType() == eWindowType_popup) - return YES; - if ([win isSheet]) - return [win isKeyWindow]; - return [win isMainWindow] && ![win attachedSheet]; -} - -// Toolbar controls and content controls respond to different window -// activeness states. -static BOOL IsActive(nsIFrame* aFrame, BOOL aIsToolbarControl) -{ - if (aIsToolbarControl) - return [NativeWindowForFrame(aFrame) isMainWindow]; - return FrameIsInActiveWindow(aFrame); -} - -static bool IsInSourceList(nsIFrame* aFrame) { - for (nsIFrame* frame = aFrame->GetParent(); frame; frame = frame->GetParent()) { - if (frame->StyleDisplay()->mAppearance == NS_THEME_MAC_SOURCE_LIST) { - return true; - } - } - return false; -} - -NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeCocoa, nsNativeTheme, nsITheme) - -nsNativeThemeCocoa::nsNativeThemeCocoa() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - kMaxFocusRingWidth = nsCocoaFeatures::OnYosemiteOrLater() ? 7 : 4; - - // provide a local autorelease pool, as this is called during startup - // before the main event-loop pool is in place - nsAutoreleasePool pool; - - mDisclosureButtonCell = [[NSButtonCell alloc] initTextCell:@""]; - [mDisclosureButtonCell setBezelStyle:NSRoundedDisclosureBezelStyle]; - [mDisclosureButtonCell setButtonType:NSPushOnPushOffButton]; - [mDisclosureButtonCell setHighlightsBy:NSPushInCellMask]; - - mHelpButtonCell = [[NSButtonCell alloc] initTextCell:@""]; - [mHelpButtonCell setBezelStyle:NSHelpButtonBezelStyle]; - [mHelpButtonCell setButtonType:NSMomentaryPushInButton]; - [mHelpButtonCell setHighlightsBy:NSPushInCellMask]; - - mPushButtonCell = [[NSButtonCell alloc] initTextCell:@""]; - [mPushButtonCell setButtonType:NSMomentaryPushInButton]; - [mPushButtonCell setHighlightsBy:NSPushInCellMask]; - - mRadioButtonCell = [[RadioButtonCell alloc] initTextCell:@""]; - [mRadioButtonCell setButtonType:NSRadioButton]; - - mCheckboxCell = [[CheckboxCell alloc] initTextCell:@""]; - [mCheckboxCell setButtonType:NSSwitchButton]; - [mCheckboxCell setAllowsMixedState:YES]; - -#if defined(__x86_64__) - mSearchFieldCell = [[SearchFieldCellWithFocusRing alloc] initTextCell:@""]; -#else - mSearchFieldCell = [[ContextAwareSearchFieldCell alloc] initTextCell:@""]; -#endif - [mSearchFieldCell setBezelStyle:NSTextFieldRoundedBezel]; - [mSearchFieldCell setBezeled:YES]; - [mSearchFieldCell setEditable:YES]; - [mSearchFieldCell setFocusRingType:NSFocusRingTypeExterior]; - - mDropdownCell = [[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]; - - mComboBoxCell = [[NSComboBoxCell alloc] initTextCell:@""]; - [mComboBoxCell setBezeled:YES]; - [mComboBoxCell setEditable:YES]; - [mComboBoxCell setFocusRingType:NSFocusRingTypeExterior]; - - mProgressBarCell = [[NSProgressBarCell alloc] init]; - - mMeterBarCell = [[NSLevelIndicatorCell alloc] - initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]; - - mCellDrawView = [[CellDrawView alloc] init]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsNativeThemeCocoa::~nsNativeThemeCocoa() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mMeterBarCell release]; - [mProgressBarCell release]; - [mDisclosureButtonCell release]; - [mHelpButtonCell release]; - [mPushButtonCell release]; - [mRadioButtonCell release]; - [mCheckboxCell release]; - [mSearchFieldCell release]; - [mDropdownCell release]; - [mComboBoxCell release]; - [mCellDrawView release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Limit on the area of the target rect (in pixels^2) in -// DrawCellWithScaling() and DrawButton() and above which we -// don't draw the object into a bitmap buffer. This is to avoid crashes in -// [NSGraphicsContext graphicsContextWithGraphicsPort:flipped:] and -// CGContextDrawImage(), and also to avoid very poor drawing performance in -// CGContextDrawImage() when it scales the bitmap (particularly if xscale or -// yscale is less than but near 1 -- e.g. 0.9). This value was determined -// by trial and error, on OS X 10.4.11 and 10.5.4, and on systems with -// different amounts of RAM. -#define BITMAP_MAX_AREA 500000 - -static int -GetBackingScaleFactorForRendering(CGContextRef cgContext) -{ - CGAffineTransform ctm = CGContextGetUserSpaceToDeviceSpaceTransform(cgContext); - CGRect transformedUserSpacePixel = CGRectApplyAffineTransform(CGRectMake(0, 0, 1, 1), ctm); - float maxScale = std::max(fabs(transformedUserSpacePixel.size.width), - fabs(transformedUserSpacePixel.size.height)); - return maxScale > 1.0 ? 2 : 1; -} - -/* - * Draw the given NSCell into the given cgContext. - * - * destRect - the size and position of the resulting control rectangle - * controlSize - the NSControlSize which will be given to the NSCell before - * asking it to render - * naturalSize - The natural dimensions of this control. - * If the control rect size is not equal to either of these, a scale - * will be applied to the context so that rendering the control at the - * natural size will result in it filling the destRect space. - * If a control has no natural dimensions in either/both axes, pass 0.0f. - * minimumSize - The minimum dimensions of this control. - * If the control rect size is less than the minimum for a given axis, - * a scale will be applied to the context so that the minimum is used - * for drawing. If a control has no minimum dimensions in either/both - * axes, pass 0.0f. - * marginSet - an array of margins; a multidimensional array of [2][3][4], - * with the first dimension being the OS version (Tiger or Leopard), - * the second being the control size (mini, small, regular), and the third - * being the 4 margin values (left, top, right, bottom). - * view - The NSView that we're drawing into. As far as I can tell, it doesn't - * matter if this is really the right view; it just has to return YES when - * asked for isFlipped. Otherwise we'll get drawing bugs on 10.4. - * mirrorHorizontal - whether to mirror the cell horizontally - */ -static void DrawCellWithScaling(NSCell *cell, - CGContextRef cgContext, - const HIRect& destRect, - NSControlSize controlSize, - NSSize naturalSize, - NSSize minimumSize, - const float marginSet[][3][4], - NSView* view, - BOOL mirrorHorizontal) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSRect drawRect = NSMakeRect(destRect.origin.x, destRect.origin.y, destRect.size.width, destRect.size.height); - - if (naturalSize.width != 0.0f) - drawRect.size.width = naturalSize.width; - if (naturalSize.height != 0.0f) - drawRect.size.height = naturalSize.height; - - // Keep aspect ratio when scaling if one dimension is free. - if (naturalSize.width == 0.0f && naturalSize.height != 0.0f) - drawRect.size.width = destRect.size.width * naturalSize.height / destRect.size.height; - if (naturalSize.height == 0.0f && naturalSize.width != 0.0f) - drawRect.size.height = destRect.size.height * naturalSize.width / destRect.size.width; - - // Honor minimum sizes. - if (drawRect.size.width < minimumSize.width) - drawRect.size.width = minimumSize.width; - if (drawRect.size.height < minimumSize.height) - drawRect.size.height = minimumSize.height; - - [NSGraphicsContext saveGraphicsState]; - - // Only skip the buffer if the area of our cell (in pixels^2) is too large. - if (drawRect.size.width * drawRect.size.height > BITMAP_MAX_AREA) { - // Inflate the rect Gecko gave us by the margin for the control. - InflateControlRect(&drawRect, controlSize, marginSet); - - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]]; - - DrawCellIncludingFocusRing(cell, drawRect, view); - - [NSGraphicsContext setCurrentContext:savedContext]; - } - else { - float w = ceil(drawRect.size.width); - float h = ceil(drawRect.size.height); - NSRect tmpRect = NSMakeRect(kMaxFocusRingWidth, kMaxFocusRingWidth, w, h); - - // inflate to figure out the frame we need to tell NSCell to draw in, to get something that's 0,0,w,h - InflateControlRect(&tmpRect, controlSize, marginSet); - - // and then, expand by kMaxFocusRingWidth size to make sure we can capture any focus ring - w += kMaxFocusRingWidth * 2.0; - h += kMaxFocusRingWidth * 2.0; - - int backingScaleFactor = GetBackingScaleFactorForRendering(cgContext); - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGContextRef ctx = CGBitmapContextCreate(NULL, - (int) w * backingScaleFactor, (int) h * backingScaleFactor, - 8, (int) w * backingScaleFactor * 4, - rgb, kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(rgb); - - // We need to flip the image twice in order to avoid drawing bugs on 10.4, see bug 465069. - // This is the first flip transform, applied to cgContext. - CGContextScaleCTM(cgContext, 1.0f, -1.0f); - CGContextTranslateCTM(cgContext, 0.0f, -(2.0 * destRect.origin.y + destRect.size.height)); - if (mirrorHorizontal) { - CGContextScaleCTM(cgContext, -1.0f, 1.0f); - CGContextTranslateCTM(cgContext, -(2.0 * destRect.origin.x + destRect.size.width), 0.0f); - } - - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:ctx flipped:YES]]; - - CGContextScaleCTM(ctx, backingScaleFactor, backingScaleFactor); - - // Set the context's "base transform" to in order to get correctly-sized focus rings. - CGContextSetBaseCTM(ctx, CGAffineTransformMakeScale(backingScaleFactor, backingScaleFactor)); - - // This is the second flip transform, applied to ctx. - CGContextScaleCTM(ctx, 1.0f, -1.0f); - CGContextTranslateCTM(ctx, 0.0f, -(2.0 * tmpRect.origin.y + tmpRect.size.height)); - - DrawCellIncludingFocusRing(cell, tmpRect, view); - - [NSGraphicsContext setCurrentContext:savedContext]; - - CGImageRef img = CGBitmapContextCreateImage(ctx); - - // Drop the image into the original destination rectangle, scaling to fit - // Only scale kMaxFocusRingWidth by xscale/yscale when the resulting rect - // doesn't extend beyond the overflow rect - float xscale = destRect.size.width / drawRect.size.width; - float yscale = destRect.size.height / drawRect.size.height; - float scaledFocusRingX = xscale < 1.0f ? kMaxFocusRingWidth * xscale : kMaxFocusRingWidth; - float scaledFocusRingY = yscale < 1.0f ? kMaxFocusRingWidth * yscale : kMaxFocusRingWidth; - CGContextDrawImage(cgContext, CGRectMake(destRect.origin.x - scaledFocusRingX, - destRect.origin.y - scaledFocusRingY, - destRect.size.width + scaledFocusRingX * 2, - destRect.size.height + scaledFocusRingY * 2), - img); - - CGImageRelease(img); - CGContextRelease(ctx); - } - - [NSGraphicsContext restoreGraphicsState]; - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, destRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -struct CellRenderSettings { - // The natural dimensions of the control. - // If a control has no natural dimensions in either/both axes, set to 0.0f. - NSSize naturalSizes[3]; - - // The minimum dimensions of the control. - // If a control has no minimum dimensions in either/both axes, set to 0.0f. - NSSize minimumSizes[3]; - - // A three-dimensional array, - // with the first dimension being the OS version ([0] 10.6-10.9, [1] 10.10 and above), - // the second being the control size (mini, small, regular), and the third - // being the 4 margin values (left, top, right, bottom). - float margins[2][3][4]; -}; - -/* - * This is a helper method that returns the required NSControlSize given a size - * and the size of the three controls plus a tolerance. - * size - The width or the height of the element to draw. - * sizes - An array with the all the width/height of the element for its - * different sizes. - * tolerance - The tolerance as passed to DrawCellWithSnapping. - * NOTE: returns NSRegularControlSize if all values in 'sizes' are zero. - */ -static NSControlSize FindControlSize(CGFloat size, const CGFloat* sizes, CGFloat tolerance) -{ - for (uint32_t i = miniControlSize; i <= regularControlSize; ++i) { - if (sizes[i] == 0) { - continue; - } - - CGFloat next = 0; - // Find next value. - for (uint32_t j = i+1; j <= regularControlSize; ++j) { - if (sizes[j] != 0) { - next = sizes[j]; - break; - } - } - - // If it's the latest value, we pick it. - if (next == 0) { - return CocoaSizeForEnum(i); - } - - if (size <= sizes[i] + tolerance && size < next) { - return CocoaSizeForEnum(i); - } - } - - // If we are here, that means sizes[] was an array with only empty values - // or the algorithm above is wrong. - // The former can happen but the later would be wrong. - NS_ASSERTION(sizes[0] == 0 && sizes[1] == 0 && sizes[2] == 0, - "We found no control! We shouldn't be there!"); - return CocoaSizeForEnum(regularControlSize); -} - -/* - * Draw the given NSCell into the given cgContext with a nice control size. - * - * This function is similar to DrawCellWithScaling, but it decides what - * control size to use based on the destRect's size. - * Scaling is only applied when the difference between the destRect's size - * and the next smaller natural size is greater than snapTolerance. Otherwise - * it snaps to the next smaller control size without scaling because unscaled - * controls look nicer. - */ -static void DrawCellWithSnapping(NSCell *cell, - CGContextRef cgContext, - const HIRect& destRect, - const CellRenderSettings settings, - float verticalAlignFactor, - NSView* view, - BOOL mirrorHorizontal, - float snapTolerance = 2.0f) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - const float rectWidth = destRect.size.width, rectHeight = destRect.size.height; - const NSSize *sizes = settings.naturalSizes; - const NSSize miniSize = sizes[EnumSizeForCocoaSize(NSMiniControlSize)]; - const NSSize smallSize = sizes[EnumSizeForCocoaSize(NSSmallControlSize)]; - const NSSize regularSize = sizes[EnumSizeForCocoaSize(NSRegularControlSize)]; - - HIRect drawRect = destRect; - - CGFloat controlWidths[3] = { miniSize.width, smallSize.width, regularSize.width }; - NSControlSize controlSizeX = FindControlSize(rectWidth, controlWidths, snapTolerance); - CGFloat controlHeights[3] = { miniSize.height, smallSize.height, regularSize.height }; - NSControlSize controlSizeY = FindControlSize(rectHeight, controlHeights, snapTolerance); - - NSControlSize controlSize = NSRegularControlSize; - size_t sizeIndex = 0; - - // At some sizes, don't scale but snap. - const NSControlSize smallerControlSize = - EnumSizeForCocoaSize(controlSizeX) < EnumSizeForCocoaSize(controlSizeY) ? - controlSizeX : controlSizeY; - const size_t smallerControlSizeIndex = EnumSizeForCocoaSize(smallerControlSize); - const NSSize size = sizes[smallerControlSizeIndex]; - float diffWidth = size.width ? rectWidth - size.width : 0.0f; - float diffHeight = size.height ? rectHeight - size.height : 0.0f; - if (diffWidth >= 0.0f && diffHeight >= 0.0f && - diffWidth <= snapTolerance && diffHeight <= snapTolerance) { - // Snap to the smaller control size. - controlSize = smallerControlSize; - sizeIndex = smallerControlSizeIndex; - MOZ_ASSERT(sizeIndex < ArrayLength(settings.naturalSizes)); - - // Resize and center the drawRect. - if (sizes[sizeIndex].width) { - drawRect.origin.x += ceil((destRect.size.width - sizes[sizeIndex].width) / 2); - drawRect.size.width = sizes[sizeIndex].width; - } - if (sizes[sizeIndex].height) { - drawRect.origin.y += floor((destRect.size.height - sizes[sizeIndex].height) * verticalAlignFactor); - drawRect.size.height = sizes[sizeIndex].height; - } - } else { - // Use the larger control size. - controlSize = EnumSizeForCocoaSize(controlSizeX) > EnumSizeForCocoaSize(controlSizeY) ? - controlSizeX : controlSizeY; - sizeIndex = EnumSizeForCocoaSize(controlSize); - } - - [cell setControlSize:controlSize]; - - MOZ_ASSERT(sizeIndex < ArrayLength(settings.minimumSizes)); - const NSSize minimumSize = settings.minimumSizes[sizeIndex]; - DrawCellWithScaling(cell, cgContext, drawRect, controlSize, sizes[sizeIndex], - minimumSize, settings.margins, view, mirrorHorizontal); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@interface NSWindow(CoreUIRendererPrivate) -+ (CUIRendererRef)coreUIRenderer; -@end - -static id -GetAquaAppearance() -{ - // We only need NSAppearance on 10.10 and up. - if (nsCocoaFeatures::OnYosemiteOrLater()) { - Class NSAppearanceClass = NSClassFromString(@"NSAppearance"); - if (NSAppearanceClass && - [NSAppearanceClass respondsToSelector:@selector(appearanceNamed:)]) { - return [NSAppearanceClass performSelector:@selector(appearanceNamed:) - withObject:@"NSAppearanceNameAqua"]; - } - } - return nil; -} - -@interface NSObject(NSAppearanceCoreUIRendering) -- (void)_drawInRect:(CGRect)rect context:(CGContextRef)cgContext options:(id)options; -@end - -static void -RenderWithCoreUI(CGRect aRect, CGContextRef cgContext, NSDictionary* aOptions, bool aSkipAreaCheck = false) -{ - id appearance = GetAquaAppearance(); - - if (!aSkipAreaCheck && aRect.size.width * aRect.size.height > BITMAP_MAX_AREA) { - return; - } - - if (appearance && [appearance respondsToSelector:@selector(_drawInRect:context:options:)]) { - // Render through NSAppearance on Mac OS 10.10 and up. This will call - // CUIDraw with a CoreUI renderer that will give us the correct 10.10 - // style. Calling CUIDraw directly with [NSWindow coreUIRenderer] still - // renders 10.9-style widgets on 10.10. - [appearance _drawInRect:aRect context:cgContext options:aOptions]; - } else { - // 10.9 and below - CUIRendererRef renderer = [NSWindow respondsToSelector:@selector(coreUIRenderer)] - ? [NSWindow coreUIRenderer] : nil; - CUIDraw(renderer, aRect, cgContext, (CFDictionaryRef)aOptions, NULL); - } -} - -static float VerticalAlignFactor(nsIFrame *aFrame) -{ - if (!aFrame) - return 0.5f; // default: center - - const nsStyleCoord& va = aFrame->StyleDisplay()->mVerticalAlign; - uint8_t intval = (va.GetUnit() == eStyleUnit_Enumerated) - ? va.GetIntValue() - : NS_STYLE_VERTICAL_ALIGN_MIDDLE; - switch (intval) { - case NS_STYLE_VERTICAL_ALIGN_TOP: - case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP: - return 0.0f; - - case NS_STYLE_VERTICAL_ALIGN_SUB: - case NS_STYLE_VERTICAL_ALIGN_SUPER: - case NS_STYLE_VERTICAL_ALIGN_MIDDLE: - case NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE: - return 0.5f; - - case NS_STYLE_VERTICAL_ALIGN_BASELINE: - case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM: - case NS_STYLE_VERTICAL_ALIGN_BOTTOM: - return 1.0f; - - default: - NS_NOTREACHED("invalid vertical-align"); - return 0.5f; - } -} - -// These are the sizes that Gecko needs to request to draw if it wants -// to get a standard-sized Aqua radio button drawn. Note that the rects -// that draw these are actually a little bigger. -static const CellRenderSettings radioSettings = { - { - NSMakeSize(11, 11), // mini - NSMakeSize(13, 13), // small - NSMakeSize(16, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {0, 1, 1, 1}, // small - {0, 0, 0, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 2}, // small - {0, 0, 0, 0} // regular - } - } -}; - -static const CellRenderSettings checkboxSettings = { - { - NSMakeSize(11, 11), // mini - NSMakeSize(13, 13), // small - NSMakeSize(16, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 1, 0, 0}, // mini - {0, 1, 0, 1}, // small - {0, 1, 0, 1} // regular - }, - { // Yosemite - {0, 1, 0, 0}, // mini - {0, 1, 0, 1}, // small - {0, 1, 0, 1} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, - const HIRect& inBoxRect, bool inSelected, - EventStates inState, nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSButtonCell *cell = inCheckbox ? mCheckboxCell : mRadioButtonCell; - NSCellStateValue state = inSelected ? NSOnState : NSOffState; - - // Check if we have an indeterminate checkbox - if (inCheckbox && GetIndeterminate(aFrame)) - state = NSMixedState; - - [cell setEnabled:!IsDisabled(aFrame, inState)]; - [cell setShowsFirstResponder:inState.HasState(NS_EVENT_STATE_FOCUS)]; - [cell setState:state]; - [cell setHighlighted:inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)]; - [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)]; - - // Ensure that the control is square. - float length = std::min(inBoxRect.size.width, inBoxRect.size.height); - HIRect drawRect = CGRectMake(inBoxRect.origin.x + (int)((inBoxRect.size.width - length) / 2.0f), - inBoxRect.origin.y + (int)((inBoxRect.size.height - length) / 2.0f), - length, length); - - DrawCellWithSnapping(cell, cgContext, drawRect, - inCheckbox ? checkboxSettings : radioSettings, - VerticalAlignFactor(aFrame), mCellDrawView, NO); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings searchFieldSettings = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 19), // small - NSMakeSize(0, 22) // regular - }, - { - NSMakeSize(32, 0), // mini - NSMakeSize(38, 0), // small - NSMakeSize(44, 0) // regular - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame, EventStates inState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - ContextAwareSearchFieldCell* cell = mSearchFieldCell; - [cell setContext:aFrame]; - [cell setEnabled:!IsDisabled(aFrame, inState)]; - // NOTE: this could probably use inState - [cell setShowsFirstResponder:IsFocused(aFrame)]; - - // When using the 10.11 SDK, the default string will be shown if we don't - // set the placeholder string. - [cell setPlaceholderString:@""]; - - DrawCellWithSnapping(cell, cgContext, inBoxRect, searchFieldSettings, - VerticalAlignFactor(aFrame), mCellDrawView, - IsFrameRTL(aFrame)); - - [cell setContext:nullptr]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const NSSize kCheckmarkSize = NSMakeSize(11, 11); -static const NSSize kMenuarrowSize = NSMakeSize(9, 10); -static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8); -static NSString* kCheckmarkImage = @"MenuOnState"; -static NSString* kMenuarrowRightImage = @"MenuSubmenu"; -static NSString* kMenuarrowLeftImage = @"MenuSubmenuLeft"; -static NSString* kMenuDownScrollArrowImage = @"MenuScrollDown"; -static NSString* kMenuUpScrollArrowImage = @"MenuScrollUp"; -static const CGFloat kMenuIconIndent = 6.0f; - -void -nsNativeThemeCocoa::DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect, - EventStates inState, nsIFrame* aFrame, - const NSSize& aIconSize, NSString* aImageName, - bool aCenterHorizontally) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // Adjust size and position of our drawRect. - CGFloat paddingX = std::max(CGFloat(0.0), aRect.size.width - aIconSize.width); - CGFloat paddingY = std::max(CGFloat(0.0), aRect.size.height - aIconSize.height); - CGFloat paddingStartX = std::min(paddingX, kMenuIconIndent); - CGFloat paddingEndX = std::max(CGFloat(0.0), paddingX - kMenuIconIndent); - CGRect drawRect = CGRectMake( - aRect.origin.x + (aCenterHorizontally ? ceil(paddingX / 2) : - IsFrameRTL(aFrame) ? paddingEndX : paddingStartX), - aRect.origin.y + ceil(paddingY / 2), - aIconSize.width, aIconSize.height); - - NSString* state = IsDisabled(aFrame, inState) ? @"disabled" : - (CheckBooleanAttr(aFrame, nsGkAtoms::menuactive) ? @"pressed" : @"normal"); - - NSString* imageName = aImageName; - if (!nsCocoaFeatures::OnElCapitanOrLater()) { - // Pre-10.11, image names are prefixed with "image." - imageName = [@"image." stringByAppendingString:aImageName]; - } - - RenderWithCoreUI(drawRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - @"kCUIBackgroundTypeMenu", @"backgroundTypeKey", - imageName, @"imageNameKey", - state, @"state", - @"image", @"widget", - [NSNumber numberWithBool:YES], @"is.flipped", - nil]); - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, drawRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const NSSize kHelpButtonSize = NSMakeSize(20, 20); -static const NSSize kDisclosureButtonSize = NSMakeSize(21, 21); - -static const CellRenderSettings pushButtonSettings = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 19), // small - NSMakeSize(0, 22) // regular - }, - { - NSMakeSize(18, 0), // mini - NSMakeSize(26, 0), // small - NSMakeSize(30, 0) // regular - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {4, 0, 4, 1}, // small - {5, 0, 5, 2} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {4, 0, 4, 1}, // small - {5, 0, 5, 2} // regular - } - } -}; - -// The height at which we start doing square buttons instead of rounded buttons -// Rounded buttons look bad if drawn at a height greater than 26, so at that point -// we switch over to doing square buttons which looks fine at any size. -#define DO_SQUARE_BUTTON_HEIGHT 26 - -void -nsNativeThemeCocoa::DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame, float aOriginalHeight) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - BOOL isActive = FrameIsInActiveWindow(aFrame); - BOOL isDisabled = IsDisabled(aFrame, inState); - - NSButtonCell* cell = (aWidgetType == NS_THEME_BUTTON) ? mPushButtonCell : - (aWidgetType == NS_THEME_MAC_HELP_BUTTON) ? mHelpButtonCell : mDisclosureButtonCell; - [cell setEnabled:!isDisabled]; - [cell setHighlighted:isActive && - inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)]; - [cell setShowsFirstResponder:inState.HasState(NS_EVENT_STATE_FOCUS) && !isDisabled && isActive]; - - if (aWidgetType != NS_THEME_BUTTON) { // Help button or disclosure button. - NSSize buttonSize = NSMakeSize(0, 0); - if (aWidgetType == NS_THEME_MAC_HELP_BUTTON) { - buttonSize = kHelpButtonSize; - } else { // Disclosure button. - buttonSize = kDisclosureButtonSize; - [cell setState:(aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED) ? NSOffState : NSOnState]; - } - - DrawCellWithScaling(cell, cgContext, inBoxRect, NSRegularControlSize, - NSZeroSize, buttonSize, NULL, mCellDrawView, - false); // Don't mirror icon in RTL. - } else { - // If the button is tall enough, draw the square button style so that - // buttons with non-standard content look good. Otherwise draw normal - // rounded aqua buttons. - // This comparison is done based on the height that is calculated without - // the top, because the snapped height can be affected by the top of the - // rect and that may result in different height depending on the top value. - if (aOriginalHeight > DO_SQUARE_BUTTON_HEIGHT) { - [cell setBezelStyle:NSShadowlessSquareBezelStyle]; - DrawCellWithScaling(cell, cgContext, inBoxRect, NSRegularControlSize, - NSZeroSize, NSMakeSize(14, 0), NULL, mCellDrawView, - IsFrameRTL(aFrame)); - } else { - [cell setBezelStyle:NSRoundedBezelStyle]; - DrawCellWithSnapping(cell, cgContext, inBoxRect, pushButtonSettings, 0.5f, - mCellDrawView, IsFrameRTL(aFrame), 1.0f); - } - } - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeFrameDrawInfo fdi; - fdi.version = 0; - fdi.kind = kHIThemeFrameTextFieldSquare; - fdi.state = kThemeStateActive; - fdi.isFocused = TRUE; - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - HIThemeDrawFrame(&inBoxRect, &fdi, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -typedef void (*RenderHIThemeControlFunction)(CGContextRef cgContext, const HIRect& aRenderRect, void* aData); - -static void -RenderTransformedHIThemeControl(CGContextRef aCGContext, const HIRect& aRect, - RenderHIThemeControlFunction aFunc, void* aData, - BOOL mirrorHorizontally = NO) -{ - CGAffineTransform savedCTM = CGContextGetCTM(aCGContext); - CGContextTranslateCTM(aCGContext, aRect.origin.x, aRect.origin.y); - - bool drawDirect; - HIRect drawRect = aRect; - drawRect.origin = CGPointZero; - - if (!mirrorHorizontally && savedCTM.a == 1.0f && savedCTM.b == 0.0f && - savedCTM.c == 0.0f && (savedCTM.d == 1.0f || savedCTM.d == -1.0f)) { - drawDirect = TRUE; - } else { - drawDirect = FALSE; - } - - // Fall back to no bitmap buffer if the area of our control (in pixels^2) - // is too large. - if (drawDirect || (aRect.size.width * aRect.size.height > BITMAP_MAX_AREA)) { - aFunc(aCGContext, drawRect, aData); - } else { - // Inflate the buffer to capture focus rings. - int w = ceil(drawRect.size.width) + 2 * kMaxFocusRingWidth; - int h = ceil(drawRect.size.height) + 2 * kMaxFocusRingWidth; - - int backingScaleFactor = GetBackingScaleFactorForRendering(aCGContext); - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef bitmapctx = CGBitmapContextCreate(NULL, - w * backingScaleFactor, - h * backingScaleFactor, - 8, - w * backingScaleFactor * 4, - colorSpace, - kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(colorSpace); - - CGContextScaleCTM(bitmapctx, backingScaleFactor, backingScaleFactor); - CGContextTranslateCTM(bitmapctx, kMaxFocusRingWidth, kMaxFocusRingWidth); - - // Set the context's "base transform" to in order to get correctly-sized focus rings. - CGContextSetBaseCTM(bitmapctx, CGAffineTransformMakeScale(backingScaleFactor, backingScaleFactor)); - - // HITheme always wants to draw into a flipped context, or things - // get confused. - CGContextTranslateCTM(bitmapctx, 0.0f, aRect.size.height); - CGContextScaleCTM(bitmapctx, 1.0f, -1.0f); - - aFunc(bitmapctx, drawRect, aData); - - CGImageRef bitmap = CGBitmapContextCreateImage(bitmapctx); - - CGAffineTransform ctm = CGContextGetCTM(aCGContext); - - // We need to unflip, so that we can do a DrawImage without getting a flipped image. - CGContextTranslateCTM(aCGContext, 0.0f, aRect.size.height); - CGContextScaleCTM(aCGContext, 1.0f, -1.0f); - - if (mirrorHorizontally) { - CGContextTranslateCTM(aCGContext, aRect.size.width, 0); - CGContextScaleCTM(aCGContext, -1.0f, 1.0f); - } - - HIRect inflatedDrawRect = CGRectMake(-kMaxFocusRingWidth, -kMaxFocusRingWidth, w, h); - CGContextDrawImage(aCGContext, inflatedDrawRect, bitmap); - - CGContextSetCTM(aCGContext, ctm); - - CGImageRelease(bitmap); - CGContextRelease(bitmapctx); - } - - CGContextSetCTM(aCGContext, savedCTM); -} - -static void -RenderButton(CGContextRef cgContext, const HIRect& aRenderRect, void* aData) -{ - HIThemeButtonDrawInfo* bdi = (HIThemeButtonDrawInfo*)aData; - HIThemeDrawButton(&aRenderRect, bdi, cgContext, kHIThemeOrientationNormal, NULL); -} - -void -nsNativeThemeCocoa::DrawButton(CGContextRef cgContext, ThemeButtonKind inKind, - const HIRect& inBoxRect, bool inIsDefault, - ThemeButtonValue inValue, ThemeButtonAdornment inAdornment, - EventStates inState, nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - BOOL isActive = FrameIsInActiveWindow(aFrame); - BOOL isDisabled = IsDisabled(aFrame, inState); - - HIThemeButtonDrawInfo bdi; - bdi.version = 0; - bdi.kind = inKind; - bdi.value = inValue; - bdi.adornment = inAdornment; - - if (isDisabled) { - bdi.state = kThemeStateUnavailable; - } - else if (inState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER)) { - bdi.state = kThemeStatePressed; - } - else { - if (inKind == kThemeArrowButton) - bdi.state = kThemeStateUnavailable; // these are always drawn as unavailable - else if (!isActive && inKind == kThemeListHeaderButton) - bdi.state = kThemeStateInactive; - else - bdi.state = kThemeStateActive; - } - - if (inState.HasState(NS_EVENT_STATE_FOCUS) && isActive) - bdi.adornment |= kThemeAdornmentFocus; - - if (inIsDefault && !isDisabled && - !inState.HasState(NS_EVENT_STATE_ACTIVE)) { - bdi.adornment |= kThemeAdornmentDefault; - bdi.animation.time.start = 0; - bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); - } - - HIRect drawFrame = inBoxRect; - - if (inKind == kThemePushButton) { - drawFrame.size.height -= 2; - if (inBoxRect.size.height < pushButtonSettings.naturalSizes[smallControlSize].height) { - bdi.kind = kThemePushButtonMini; - } - else if (inBoxRect.size.height < pushButtonSettings.naturalSizes[regularControlSize].height) { - bdi.kind = kThemePushButtonSmall; - drawFrame.origin.y -= 1; - drawFrame.origin.x += 1; - drawFrame.size.width -= 2; - } - } - else if (inKind == kThemeListHeaderButton) { - CGContextClipToRect(cgContext, inBoxRect); - // Always remove the top border. - drawFrame.origin.y -= 1; - drawFrame.size.height += 1; - // Remove the left border in LTR mode and the right border in RTL mode. - drawFrame.size.width += 1; - bool isLast = IsLastTreeHeaderCell(aFrame); - if (isLast) - drawFrame.size.width += 1; // Also remove the other border. - if (!IsFrameRTL(aFrame) || isLast) - drawFrame.origin.x -= 1; - } - - RenderTransformedHIThemeControl(cgContext, drawFrame, RenderButton, &bdi, - IsFrameRTL(aFrame)); - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings dropdownSettings = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 19), // small - NSMakeSize(0, 22) // regular - }, - { - NSMakeSize(18, 0), // mini - NSMakeSize(38, 0), // small - NSMakeSize(44, 0) // regular - }, - { - { // Leopard - {1, 1, 2, 1}, // mini - {3, 0, 3, 1}, // small - {3, 0, 3, 0} // regular - }, - { // Yosemite - {1, 1, 2, 1}, // mini - {3, 0, 3, 1}, // small - {3, 0, 3, 0} // regular - } - } -}; - -static const CellRenderSettings editableMenulistSettings = { - { - NSMakeSize(0, 15), // mini - NSMakeSize(0, 18), // small - NSMakeSize(0, 21) // regular - }, - { - NSMakeSize(18, 0), // mini - NSMakeSize(38, 0), // small - NSMakeSize(44, 0) // regular - }, - { - { // Leopard - {0, 0, 2, 2}, // mini - {0, 0, 3, 2}, // small - {0, 1, 3, 3} // regular - }, - { // Yosemite - {0, 0, 2, 2}, // mini - {0, 0, 3, 2}, // small - {0, 1, 3, 3} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawDropdown(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, uint8_t aWidgetType, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mDropdownCell setPullsDown:(aWidgetType == NS_THEME_BUTTON)]; - - BOOL isEditable = (aWidgetType == NS_THEME_MENULIST_TEXTFIELD); - NSCell* cell = isEditable ? (NSCell*)mComboBoxCell : (NSCell*)mDropdownCell; - - [cell setEnabled:!IsDisabled(aFrame, inState)]; - [cell setShowsFirstResponder:(IsFocused(aFrame) || inState.HasState(NS_EVENT_STATE_FOCUS))]; - [cell setHighlighted:IsOpenButton(aFrame)]; - [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] : NSClearControlTint)]; - - const CellRenderSettings& settings = isEditable ? editableMenulistSettings : dropdownSettings; - DrawCellWithSnapping(cell, cgContext, inBoxRect, settings, - 0.5f, mCellDrawView, IsFrameRTL(aFrame)); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings spinnerSettings = { - { - NSMakeSize(11, 16), // mini (width trimmed by 2px to reduce blank border) - NSMakeSize(15, 22), // small - NSMakeSize(19, 27) // regular - }, - { - NSMakeSize(11, 16), // mini (width trimmed by 2px to reduce blank border) - NSMakeSize(15, 22), // small - NSMakeSize(19, 27) // regular - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {0, 0, 0, 0}, // small - {0, 0, 0, 0} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawSpinButtons(CGContextRef cgContext, ThemeButtonKind inKind, - const HIRect& inBoxRect, ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - EventStates inState, nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeButtonDrawInfo bdi; - bdi.version = 0; - bdi.kind = inKind; - bdi.value = kThemeButtonOff; - bdi.adornment = inAdornment; - - if (IsDisabled(aFrame, inState)) - bdi.state = kThemeStateUnavailable; - else - bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive; - - HIThemeDrawButton(&inBoxRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawSpinButton(CGContextRef cgContext, - ThemeButtonKind inKind, - const HIRect& inBoxRect, - ThemeDrawState inDrawState, - ThemeButtonAdornment inAdornment, - EventStates inState, - nsIFrame* aFrame, - uint8_t aWidgetType) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - MOZ_ASSERT(aWidgetType == NS_THEME_SPINNER_UPBUTTON || - aWidgetType == NS_THEME_SPINNER_DOWNBUTTON); - - HIThemeButtonDrawInfo bdi; - bdi.version = 0; - bdi.kind = inKind; - bdi.value = kThemeButtonOff; - bdi.adornment = inAdornment; - - if (IsDisabled(aFrame, inState)) - bdi.state = kThemeStateUnavailable; - else - bdi.state = FrameIsInActiveWindow(aFrame) ? inDrawState : kThemeStateActive; - - // Cocoa only allows kThemeIncDecButton to paint the up and down spin buttons - // together as a single unit (presumably because when one button is active, - // the appearance of both changes (in different ways)). Here we have to paint - // both buttons, using clip to hide the one we don't want to paint. - HIRect drawRect = inBoxRect; - drawRect.size.height *= 2; - if (aWidgetType == NS_THEME_SPINNER_DOWNBUTTON) { - drawRect.origin.y -= inBoxRect.size.height; - } - - // Shift the drawing a little to the left, since cocoa paints with more - // blank space around the visual buttons than we'd like: - drawRect.origin.x -= 1; - - CGContextSaveGState(cgContext); - CGContextClipToRect(cgContext, inBoxRect); - - HIThemeDrawButton(&drawRect, &bdi, cgContext, HITHEME_ORIENTATION, NULL); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawFrame(CGContextRef cgContext, HIThemeFrameKind inKind, - const HIRect& inBoxRect, bool inDisabled, - EventStates inState) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeFrameDrawInfo fdi; - fdi.version = 0; - fdi.kind = inKind; - - // We don't ever set an inactive state for this because it doesn't - // look right (see other apps). - fdi.state = inDisabled ? kThemeStateUnavailable : kThemeStateActive; - - // for some reason focus rings on listboxes draw incorrectly - if (inKind == kHIThemeFrameListBox) - fdi.isFocused = 0; - else - fdi.isFocused = inState.HasState(NS_EVENT_STATE_FOCUS); - - // HIThemeDrawFrame takes the rect for the content area of the frame, not - // the bounding rect for the frame. Here we reduce the size of the rect we - // will pass to make it the size of the content. - HIRect drawRect = inBoxRect; - if (inKind == kHIThemeFrameTextFieldSquare) { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset); - drawRect.origin.x += frameOutset; - drawRect.origin.y += frameOutset; - drawRect.size.width -= frameOutset * 2; - drawRect.size.height -= frameOutset * 2; - } - else if (inKind == kHIThemeFrameListBox) { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset); - drawRect.origin.x += frameOutset; - drawRect.origin.y += frameOutset; - drawRect.size.width -= frameOutset * 2; - drawRect.size.height -= frameOutset * 2; - } - -#if DRAW_IN_FRAME_DEBUG - CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25); - CGContextFillRect(cgContext, inBoxRect); -#endif - - HIThemeDrawFrame(&drawRect, &fdi, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings progressSettings[2][2] = { - // Vertical progress bar. - { - // Determined settings. - { - { - NSZeroSize, // mini - NSMakeSize(10, 0), // small - NSMakeSize(16, 0) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - } - } - }, - // There is no horizontal margin in regular undetermined size. - { - { - NSZeroSize, // mini - NSMakeSize(10, 0), // small - NSMakeSize(16, 0) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 0, 1, 0} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 0, 1, 0} // regular - } - } - } - }, - // Horizontal progress bar. - { - // Determined settings. - { - { - NSZeroSize, // mini - NSMakeSize(0, 10), // small - NSMakeSize(0, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - } - } - }, - // There is no horizontal margin in regular undetermined size. - { - { - NSZeroSize, // mini - NSMakeSize(0, 10), // small - NSMakeSize(0, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {0, 1, 0, 1} // regular - }, - { // Yosemite - {0, 0, 0, 0}, // mini - {1, 1, 1, 1}, // small - {0, 1, 0, 1} // regular - } - } - } - } -}; - -void -nsNativeThemeCocoa::DrawProgress(CGContextRef cgContext, const HIRect& inBoxRect, - bool inIsIndeterminate, bool inIsHorizontal, - double inValue, double inMaxValue, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - NSProgressBarCell* cell = mProgressBarCell; - - [cell setValue:inValue]; - [cell setMax:inMaxValue]; - [cell setIndeterminate:inIsIndeterminate]; - [cell setHorizontal:inIsHorizontal]; - [cell setControlTint:(FrameIsInActiveWindow(aFrame) ? [NSColor currentControlTint] - : NSClearControlTint)]; - - DrawCellWithSnapping(cell, cgContext, inBoxRect, - progressSettings[inIsHorizontal][inIsIndeterminate], - VerticalAlignFactor(aFrame), mCellDrawView, - IsFrameRTL(aFrame)); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static const CellRenderSettings meterSetting = { - { - NSMakeSize(0, 16), // mini - NSMakeSize(0, 16), // small - NSMakeSize(0, 16) // regular - }, - { - NSZeroSize, NSZeroSize, NSZeroSize - }, - { - { // Leopard - {1, 1, 1, 1}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - }, - { // Yosemite - {1, 1, 1, 1}, // mini - {1, 1, 1, 1}, // small - {1, 1, 1, 1} // regular - } - } -}; - -void -nsNativeThemeCocoa::DrawMeter(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK - - NS_PRECONDITION(aFrame, "aFrame should not be null here!"); - - // When using -moz-meterbar on an non meter element, we will not be able to - // get all the needed information so we just draw an empty meter. - nsIContent* content = aFrame->GetContent(); - if (!(content && content->IsHTMLElement(nsGkAtoms::meter))) { - DrawCellWithSnapping(mMeterBarCell, cgContext, inBoxRect, - meterSetting, VerticalAlignFactor(aFrame), - mCellDrawView, IsFrameRTL(aFrame)); - return; - } - - HTMLMeterElement* meterElement = static_cast(content); - double value = meterElement->Value(); - double min = meterElement->Min(); - double max = meterElement->Max(); - - NSLevelIndicatorCell* cell = mMeterBarCell; - - [cell setMinValue:min]; - [cell setMaxValue:max]; - [cell setDoubleValue:value]; - - /** - * The way HTML and Cocoa defines the meter/indicator widget are different. - * So, we are going to use a trick to get the Cocoa widget showing what we - * are expecting: we set the warningValue or criticalValue to the current - * value when we want to have the widget to be in the warning or critical - * state. - */ - EventStates states = aFrame->GetContent()->AsElement()->State(); - - // Reset previously set warning and critical values. - [cell setWarningValue:max+1]; - [cell setCriticalValue:max+1]; - - if (states.HasState(NS_EVENT_STATE_SUB_OPTIMUM)) { - [cell setWarningValue:value]; - } else if (states.HasState(NS_EVENT_STATE_SUB_SUB_OPTIMUM)) { - [cell setCriticalValue:value]; - } - - HIRect rect = CGRectStandardize(inBoxRect); - BOOL vertical = IsVerticalMeter(aFrame); - - CGContextSaveGState(cgContext); - - if (vertical) { - /** - * Cocoa doesn't provide a vertical meter bar so to show one, we have to - * show a rotated horizontal meter bar. - * Given that we want to show a vertical meter bar, we assume that the rect - * has vertical dimensions but we can't correctly draw a meter widget inside - * such a rectangle so we need to inverse width and height (and re-position) - * to get a rectangle with horizontal dimensions. - * Finally, we want to show a vertical meter so we want to rotate the result - * so it is vertical. We do that by changing the context. - */ - CGFloat tmp = rect.size.width; - rect.size.width = rect.size.height; - rect.size.height = tmp; - rect.origin.x += rect.size.height / 2.f - rect.size.width / 2.f; - rect.origin.y += rect.size.width / 2.f - rect.size.height / 2.f; - - CGContextTranslateCTM(cgContext, CGRectGetMidX(rect), CGRectGetMidY(rect)); - CGContextRotateCTM(cgContext, -M_PI / 2.f); - CGContextTranslateCTM(cgContext, -CGRectGetMidX(rect), -CGRectGetMidY(rect)); - } - - DrawCellWithSnapping(cell, cgContext, rect, - meterSetting, VerticalAlignFactor(aFrame), - mCellDrawView, !vertical && IsFrameRTL(aFrame)); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK -} - -void -nsNativeThemeCocoa::DrawTabPanel(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeTabPaneDrawInfo tpdi; - - tpdi.version = 1; - tpdi.state = FrameIsInActiveWindow(aFrame) ? kThemeStateActive : kThemeStateInactive; - tpdi.direction = kThemeTabNorth; - tpdi.size = kHIThemeTabSizeNormal; - tpdi.kind = kHIThemeTabKindNormal; - - HIThemeDrawTabPane(&inBoxRect, &tpdi, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawScale(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, bool inIsVertical, - bool inIsReverse, int32_t inCurrentValue, - int32_t inMinValue, int32_t inMaxValue, - nsIFrame* aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeTrackDrawInfo tdi; - - tdi.version = 0; - tdi.kind = kThemeMediumSlider; - tdi.bounds = inBoxRect; - tdi.min = inMinValue; - tdi.max = inMaxValue; - tdi.value = inCurrentValue; - tdi.attributes = kThemeTrackShowThumb; - if (!inIsVertical) - tdi.attributes |= kThemeTrackHorizontal; - if (inIsReverse) - tdi.attributes |= kThemeTrackRightToLeft; - if (inState.HasState(NS_EVENT_STATE_FOCUS)) - tdi.attributes |= kThemeTrackHasFocus; - if (IsDisabled(aFrame, inState)) - tdi.enableState = kThemeTrackDisabled; - else - tdi.enableState = FrameIsInActiveWindow(aFrame) ? kThemeTrackActive : kThemeTrackInactive; - tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; - tdi.trackInfo.slider.pressState = 0; - - HIThemeDrawTrack(&tdi, NULL, cgContext, HITHEME_ORIENTATION); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsIFrame* -nsNativeThemeCocoa::SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter) -{ - // Usually a separator is drawn by the segment to the right of the - // separator, but pressed and selected segments have higher priority. - if (!aBefore || !aAfter) - return nullptr; - if (IsSelectedButton(aAfter)) - return aAfter; - if (IsSelectedButton(aBefore) || IsPressedButton(aBefore)) - return aBefore; - return aAfter; -} - -CGRect -nsNativeThemeCocoa::SeparatorAdjustedRect(CGRect aRect, nsIFrame* aLeft, - nsIFrame* aCurrent, nsIFrame* aRight) -{ - // A separator between two segments should always be located in the leftmost - // pixel column of the segment to the right of the separator, regardless of - // who ends up drawing it. - // CoreUI draws the separators inside the drawing rect. - if (aLeft && SeparatorResponsibility(aLeft, aCurrent) == aLeft) { - // The left button draws the separator, so we need to make room for it. - aRect.origin.x += 1; - aRect.size.width -= 1; - } - if (SeparatorResponsibility(aCurrent, aRight) == aCurrent) { - // We draw the right separator, so we need to extend the draw rect into the - // segment to our right. - aRect.size.width += 1; - } - return aRect; -} - -static NSString* ToolbarButtonPosition(BOOL aIsFirst, BOOL aIsLast) -{ - if (aIsFirst) { - if (aIsLast) - return @"kCUISegmentPositionOnly"; - return @"kCUISegmentPositionFirst"; - } - if (aIsLast) - return @"kCUISegmentPositionLast"; - return @"kCUISegmentPositionMiddle"; -} - -struct SegmentedControlRenderSettings { - const CGFloat* heights; - const NSString* widgetName; - const BOOL ignoresPressedWhenSelected; - const BOOL isToolbarControl; -}; - -static const CGFloat tabHeights[3] = { 17, 20, 23 }; - -static const SegmentedControlRenderSettings tabRenderSettings = { - tabHeights, @"tab", YES, NO -}; - -static const CGFloat toolbarButtonHeights[3] = { 15, 18, 22 }; - -static const SegmentedControlRenderSettings toolbarButtonRenderSettings = { - toolbarButtonHeights, @"kCUIWidgetButtonSegmentedSCurve", NO, YES -}; - -void -nsNativeThemeCocoa::DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, - EventStates inState, nsIFrame* aFrame, - const SegmentedControlRenderSettings& aSettings) -{ - BOOL isActive = IsActive(aFrame, aSettings.isToolbarControl); - BOOL isFocused = inState.HasState(NS_EVENT_STATE_FOCUS); - BOOL isSelected = IsSelectedButton(aFrame); - BOOL isPressed = IsPressedButton(aFrame); - if (isSelected && aSettings.ignoresPressedWhenSelected) { - isPressed = NO; - } - - BOOL isRTL = IsFrameRTL(aFrame); - nsIFrame* left = GetAdjacentSiblingFrameWithSameAppearance(aFrame, isRTL); - nsIFrame* right = GetAdjacentSiblingFrameWithSameAppearance(aFrame, !isRTL); - CGRect drawRect = SeparatorAdjustedRect(inBoxRect, left, aFrame, right); - BOOL drawLeftSeparator = SeparatorResponsibility(left, aFrame) == aFrame; - BOOL drawRightSeparator = SeparatorResponsibility(aFrame, right) == aFrame; - NSControlSize controlSize = FindControlSize(drawRect.size.height, aSettings.heights, 4.0f); - - RenderWithCoreUI(drawRect, cgContext, [NSDictionary dictionaryWithObjectsAndKeys: - aSettings.widgetName, @"widget", - (isActive ? @"kCUIPresentationStateActiveKey" : @"kCUIPresentationStateInactive"), @"kCUIPresentationStateKey", - ToolbarButtonPosition(!left, !right), @"kCUIPositionKey", - [NSNumber numberWithBool:drawLeftSeparator], @"kCUISegmentLeadingSeparatorKey", - [NSNumber numberWithBool:drawRightSeparator], @"kCUISegmentTrailingSeparatorKey", - [NSNumber numberWithBool:isSelected], @"value", - (isPressed ? @"pressed" : (isActive ? @"normal" : @"inactive")), @"state", - [NSNumber numberWithBool:isFocused], @"focus", - CUIControlSizeForCocoaSize(controlSize), @"size", - [NSNumber numberWithBool:YES], @"is.flipped", - @"up", @"direction", - nil]); -} - -void -nsNativeThemeCocoa::GetScrollbarPressStates(nsIFrame* aFrame, - EventStates aButtonStates[]) -{ - static nsIContent::AttrValuesArray attributeValues[] = { - &nsGkAtoms::scrollbarUpTop, - &nsGkAtoms::scrollbarDownTop, - &nsGkAtoms::scrollbarUpBottom, - &nsGkAtoms::scrollbarDownBottom, - nullptr - }; - - // Get the state of any scrollbar buttons in our child frames - for (nsIFrame *childFrame : aFrame->PrincipalChildList()) { - nsIContent *childContent = childFrame->GetContent(); - if (!childContent) continue; - int32_t attrIndex = childContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::sbattr, - attributeValues, eCaseMatters); - if (attrIndex < 0) continue; - - aButtonStates[attrIndex] = GetContentState(childFrame, NS_THEME_BUTTON); - } -} - -nsIFrame* -nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame) -{ - // Walk our parents to find a scrollbar frame - nsIFrame *scrollbarFrame = aFrame; - do { - if (scrollbarFrame->GetType() == nsGkAtoms::scrollbarFrame) break; - } while ((scrollbarFrame = scrollbarFrame->GetParent())); - - // We return null if we can't find a parent scrollbar frame - return scrollbarFrame; -} - -static bool -ToolbarCanBeUnified(CGContextRef cgContext, const HIRect& inBoxRect, NSWindow* aWindow) -{ - if (![aWindow isKindOfClass:[ToolbarWindow class]]) - return false; - - ToolbarWindow* win = (ToolbarWindow*)aWindow; - float unifiedToolbarHeight = [win unifiedToolbarHeight]; - return inBoxRect.origin.x == 0 && - inBoxRect.size.width >= [win frame].size.width && - CGRectGetMaxY(inBoxRect) <= unifiedToolbarHeight; -} - -// By default, kCUIWidgetWindowFrame drawing draws rounded corners in the -// upper corners. Depending on the context type, it fills the background in -// the corners with black or leaves it transparent. Unfortunately, this corner -// rounding interacts poorly with the window corner masking we apply during -// titlebar drawing and results in small remnants of the corner background -// appearing at the rounded edge. -// So we draw square corners. -static void -DrawNativeTitlebarToolbarWithSquareCorners(CGContextRef aContext, const CGRect& aRect, - CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped) -{ - // We extend the draw rect horizontally and clip away the rounded corners. - const CGFloat extendHorizontal = 10; - CGRect drawRect = CGRectInset(aRect, -extendHorizontal, 0); - CGContextSaveGState(aContext); - CGContextClipToRect(aContext, aRect); - - RenderWithCoreUI(drawRect, aContext, - [NSDictionary dictionaryWithObjectsAndKeys: - @"kCUIWidgetWindowFrame", @"widget", - @"regularwin", @"windowtype", - (aIsMain ? @"normal" : @"inactive"), @"state", - [NSNumber numberWithDouble:aUnifiedHeight], @"kCUIWindowFrameUnifiedTitleBarHeightKey", - [NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawTitleSeparatorKey", - [NSNumber numberWithBool:aIsFlipped], @"is.flipped", - nil]); - - CGContextRestoreGState(aContext); -} - -void -nsNativeThemeCocoa::DrawUnifiedToolbar(CGContextRef cgContext, const HIRect& inBoxRect, - NSWindow* aWindow) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - CGContextSaveGState(cgContext); - CGContextClipToRect(cgContext, inBoxRect); - - CGFloat unifiedHeight = std::max([(ToolbarWindow*)aWindow unifiedToolbarHeight], - inBoxRect.size.height); - BOOL isMain = [aWindow isMainWindow]; - CGFloat titlebarHeight = unifiedHeight - inBoxRect.size.height; - CGRect drawRect = CGRectMake(inBoxRect.origin.x, inBoxRect.origin.y - titlebarHeight, - inBoxRect.size.width, inBoxRect.size.height + titlebarHeight); - DrawNativeTitlebarToolbarWithSquareCorners(cgContext, drawRect, unifiedHeight, isMain, YES); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect, - nsIFrame *aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (inBoxRect.size.height < 2.0f) - return; - - CGContextSaveGState(cgContext); - CGContextClipToRect(cgContext, inBoxRect); - - // kCUIWidgetWindowFrame draws a complete window frame with both title bar - // and bottom bar. We only want the bottom bar, so we extend the draw rect - // upwards to make space for the title bar, and then we clip it away. - CGRect drawRect = inBoxRect; - const int extendUpwards = 40; - drawRect.origin.y -= extendUpwards; - drawRect.size.height += extendUpwards; - RenderWithCoreUI(drawRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - @"kCUIWidgetWindowFrame", @"widget", - @"regularwin", @"windowtype", - (IsActive(aFrame, YES) ? @"normal" : @"inactive"), @"state", - [NSNumber numberWithInt:inBoxRect.size.height], @"kCUIWindowFrameBottomBarHeightKey", - [NSNumber numberWithBool:YES], @"kCUIWindowFrameDrawBottomBarSeparatorKey", - [NSNumber numberWithBool:YES], @"is.flipped", - nil]); - - CGContextRestoreGState(cgContext); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsNativeThemeCocoa::DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect, - CGFloat aUnifiedHeight, BOOL aIsMain, BOOL aIsFlipped) -{ - CGFloat unifiedHeight = std::max(aUnifiedHeight, aTitlebarRect.size.height); - DrawNativeTitlebarToolbarWithSquareCorners(aContext, aTitlebarRect, unifiedHeight, aIsMain, aIsFlipped); -} - -static void -RenderResizer(CGContextRef cgContext, const HIRect& aRenderRect, void* aData) -{ - HIThemeGrowBoxDrawInfo* drawInfo = (HIThemeGrowBoxDrawInfo*)aData; - HIThemeDrawGrowBox(&CGPointZero, drawInfo, cgContext, kHIThemeOrientationNormal); -} - -void -nsNativeThemeCocoa::DrawResizer(CGContextRef cgContext, const HIRect& aRect, - nsIFrame *aFrame) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - HIThemeGrowBoxDrawInfo drawInfo; - drawInfo.version = 0; - drawInfo.state = kThemeStateActive; - drawInfo.kind = kHIThemeGrowBoxKindNormal; - drawInfo.direction = kThemeGrowRight | kThemeGrowDown; - drawInfo.size = kHIThemeGrowBoxSizeNormal; - - RenderTransformedHIThemeControl(cgContext, aRect, RenderResizer, &drawInfo, - IsFrameRTL(aFrame)); - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -static void -DrawVibrancyBackground(CGContextRef cgContext, CGRect inBoxRect, - nsIFrame* aFrame, nsITheme::ThemeGeometryType aThemeGeometryType, - int aCornerRadiusIfOpaque = 0) -{ - ChildView* childView = ChildViewForFrame(aFrame); - if (childView) { - NSRect rect = NSRectFromCGRect(inBoxRect); - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]]; - [NSGraphicsContext saveGraphicsState]; - - NSColor* fillColor = [childView vibrancyFillColorForThemeGeometryType:aThemeGeometryType]; - if ([fillColor alphaComponent] == 1.0 && aCornerRadiusIfOpaque > 0) { - // The fillColor being opaque means that the system-wide pref "reduce - // transparency" is set. In that scenario, we still go through all the - // vibrancy rendering paths (VibrancyManager::SystemSupportsVibrancy() - // will still return true), but the result just won't look "vibrant". - // However, there's one unfortunate change of behavior that this pref - // has: It stops the window server from applying window masks. We use - // a window mask to get rounded corners on menus. So since the mask - // doesn't work in "reduce vibrancy" mode, we need to do our own rounded - // corner clipping here. - [[NSBezierPath bezierPathWithRoundedRect:rect - xRadius:aCornerRadiusIfOpaque - yRadius:aCornerRadiusIfOpaque] addClip]; - } - - [fillColor set]; - NSRectFill(rect); - - [NSGraphicsContext restoreGraphicsState]; - [NSGraphicsContext setCurrentContext:savedContext]; - } -} - -bool -nsNativeThemeCocoa::IsParentScrollbarRolledOver(nsIFrame* aFrame) -{ - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - return nsLookAndFeel::UseOverlayScrollbars() - ? CheckBooleanAttr(scrollbarFrame, nsGkAtoms::hover) - : GetContentState(scrollbarFrame, NS_THEME_NONE).HasState(NS_EVENT_STATE_HOVER); -} - -static bool -IsHiDPIContext(nsPresContext* aContext) -{ - return nsPresContext::AppUnitsPerCSSPixel() >= - 2 * aContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); -} - -static bool -IsScrollbarWidthThin(nsIFrame* aFrame) -{ - return aFrame->StyleUserInterface()->mScrollbarWidth == StyleScrollbarWidth::Thin; -} - -NS_IMETHODIMP -nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - const nsRect& aRect, - const nsRect& aDirtyRect) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - - // setup to draw into the correct port - int32_t p2a = aFrame->PresContext()->AppUnitsPerDevPixel(); - - gfx::Rect nativeDirtyRect = NSRectToRect(aDirtyRect, p2a); - gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height); - nativeWidgetRect.ScaleInverse(gfxFloat(p2a)); - float nativeWidgetHeight = round(nativeWidgetRect.Height()); - nativeWidgetRect.Round(); - if (nativeWidgetRect.IsEmpty()) - return NS_OK; // Don't attempt to draw invisible widgets. - - AutoRestoreTransform autoRestoreTransform(&aDrawTarget); - - bool hidpi = IsHiDPIContext(aFrame->PresContext()); - if (hidpi) { - // Use high-resolution drawing. - nativeWidgetRect.Scale(0.5f); - nativeWidgetHeight *= 0.5f; - nativeDirtyRect.Scale(0.5f); - aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(2.0f, 2.0f)); - } - - gfxQuartzNativeDrawing nativeDrawing(aDrawTarget, nativeDirtyRect); - - CGContextRef cgContext = nativeDrawing.BeginNativeDrawing(); - if (cgContext == nullptr) { - // The Quartz surface handles 0x0 surfaces by internally - // making all operations no-ops; there's no cgcontext created for them. - // Unfortunately, this means that callers that want to render - // directly to the CGContext need to be aware of this quirk. - return NS_OK; - } - - if (hidpi) { - // Set the context's "base transform" to in order to get correctly-sized focus rings. - CGContextSetBaseCTM(cgContext, CGAffineTransformMakeScale(2, 2)); - } - -#if 0 - if (1 /*aWidgetType == NS_THEME_TEXTFIELD*/) { - fprintf(stderr, "Native theme drawing widget %d [%p] dis:%d in rect [%d %d %d %d]\n", - aWidgetType, aFrame, IsDisabled(aFrame), aRect.x, aRect.y, aRect.width, aRect.height); - fprintf(stderr, "Cairo matrix: [%f %f %f %f %f %f]\n", - mat._11, mat._12, mat._21, mat._22, mat._31, mat._32); - fprintf(stderr, "Native theme xform[0]: [%f %f %f %f %f %f]\n", - mm0.a, mm0.b, mm0.c, mm0.d, mm0.tx, mm0.ty); - CGAffineTransform mm = CGContextGetCTM(cgContext); - fprintf(stderr, "Native theme xform[1]: [%f %f %f %f %f %f]\n", - mm.a, mm.b, mm.c, mm.d, mm.tx, mm.ty); - } -#endif - - CGRect macRect = CGRectMake(nativeWidgetRect.X(), nativeWidgetRect.Y(), - nativeWidgetRect.Width(), nativeWidgetRect.Height()); - -#if 0 - fprintf(stderr, " --> macRect %f %f %f %f\n", - macRect.origin.x, macRect.origin.y, macRect.size.width, macRect.size.height); - CGRect bounds = CGContextGetClipBoundingBox(cgContext); - fprintf(stderr, " --> clip bounds: %f %f %f %f\n", - bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); - - //CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 1.0, 0.1); - //CGContextFillRect(cgContext, bounds); -#endif - - EventStates eventState = GetContentState(aFrame, aWidgetType); - - switch (aWidgetType) { - case NS_THEME_DIALOG: { - if (IsWindowSheet(aFrame)) { - if (VibrancyManager::SystemSupportsVibrancy()) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - HIThemeSetFill(kThemeBrushSheetBackgroundTransparent, NULL, cgContext, HITHEME_ORIENTATION); - CGContextFillRect(cgContext, macRect); - } - } else { - HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION); - CGContextFillRect(cgContext, macRect); - } - - } - break; - - case NS_THEME_MENUPOPUP: - if (VibrancyManager::SystemSupportsVibrancy()) { - DrawVibrancyBackground(cgContext, macRect, aFrame, eThemeGeometryTypeMenu, 4); - } else { - HIThemeMenuDrawInfo mdi; - memset(&mdi, 0, sizeof(mdi)); - mdi.version = 0; - mdi.menuType = IsDisabled(aFrame, eventState) ? - static_cast(kThemeMenuTypeInactive) : - static_cast(kThemeMenuTypePopUp); - - bool isLeftOfParent = false; - if (IsSubmenu(aFrame, &isLeftOfParent) && !isLeftOfParent) { - mdi.menuType = kThemeMenuTypeHierarchical; - } - - // The rounded corners draw outside the frame. - CGRect deflatedRect = CGRectMake(macRect.origin.x, macRect.origin.y + 4, - macRect.size.width, macRect.size.height - 8); - HIThemeDrawMenuBackground(&deflatedRect, &mdi, cgContext, HITHEME_ORIENTATION); - } - break; - - case NS_THEME_MENUARROW: { - bool isRTL = IsFrameRTL(aFrame); - DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuarrowSize, - isRTL ? kMenuarrowLeftImage : kMenuarrowRightImage, true); - } - break; - - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: { - if (VibrancyManager::SystemSupportsVibrancy()) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - bool isDisabled = IsDisabled(aFrame, eventState); - bool isSelected = !isDisabled && CheckBooleanAttr(aFrame, nsGkAtoms::menuactive); - // maybe use kThemeMenuItemHierBackground or PopUpBackground instead of just Plain? - HIThemeMenuItemDrawInfo drawInfo; - memset(&drawInfo, 0, sizeof(drawInfo)); - drawInfo.version = 0; - drawInfo.itemType = kThemeMenuItemPlain; - drawInfo.state = (isDisabled ? - static_cast(kThemeMenuDisabled) : - isSelected ? - static_cast(kThemeMenuSelected) : - static_cast(kThemeMenuActive)); - - // XXX pass in the menu rect instead of always using the item rect - HIRect ignored; - HIThemeDrawMenuItem(&macRect, &macRect, &drawInfo, cgContext, HITHEME_ORIENTATION, &ignored); - } - - if (aWidgetType == NS_THEME_CHECKMENUITEM) { - DrawMenuIcon(cgContext, macRect, eventState, aFrame, kCheckmarkSize, kCheckmarkImage, false); - } - } - break; - - case NS_THEME_MENUSEPARATOR: { - // Workaround for visual artifacts issues with - // HIThemeDrawMenuSeparator on macOS Big Sur. - if (nsCocoaFeatures::OnBigSurOrLater()) { - CGRect separatorRect = macRect; - separatorRect.size.height = 1; - separatorRect.size.width -= 42; - separatorRect.origin.x += 21; - // Use a gray color similar to the native separator - CGContextSetRGBFillColor(cgContext, 0.816, 0.816, 0.816, 1.0); - CGContextFillRect(cgContext, separatorRect); - } - else - { - ThemeMenuState menuState; - if (IsDisabled(aFrame, eventState)) { - menuState = kThemeMenuDisabled; - } - else { - menuState = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive) ? - kThemeMenuSelected : kThemeMenuActive; - } - HIThemeMenuItemDrawInfo midi = { 0, kThemeMenuItemPlain, menuState }; - HIThemeDrawMenuSeparator(&macRect, &macRect, &midi, cgContext, HITHEME_ORIENTATION); - } - } - break; - - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - DrawMenuIcon(cgContext, macRect, eventState, aFrame, kMenuScrollArrowSize, - aWidgetType == NS_THEME_BUTTON_ARROW_UP ? - kMenuUpScrollArrowImage : kMenuDownScrollArrowImage, true); - break; - - case NS_THEME_TOOLTIP: - if (VibrancyManager::SystemSupportsVibrancy()) { - DrawVibrancyBackground(cgContext, macRect, aFrame, ThemeGeometryTypeForWidget(aFrame, aWidgetType)); - } else { - CGContextSetRGBFillColor(cgContext, 0.996, 1.000, 0.792, 0.950); - CGContextFillRect(cgContext, macRect); - } - break; - - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: { - bool isCheckbox = (aWidgetType == NS_THEME_CHECKBOX); - DrawCheckboxOrRadio(cgContext, isCheckbox, macRect, GetCheckedOrSelected(aFrame, !isCheckbox), - eventState, aFrame); - } - break; - - case NS_THEME_BUTTON: - if (IsDefaultButton(aFrame)) { - // Check whether the default button is in a document that does not - // match the :-moz-window-inactive pseudoclass. This activeness check - // is different from the other "active window" checks in this file - // because we absolutely need the button's default button appearance to - // be in sync with its text color, and the text color is changed by - // such a :-moz-window-inactive rule. (That's because on 10.10 and up, - // default buttons in active windows have blue background and white - // text, and default buttons in inactive windows have white background - // and black text.) - EventStates docState = aFrame->GetContent()->OwnerDoc()->GetDocumentState(); - bool isInActiveWindow = !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE); - if (!IsDisabled(aFrame, eventState) && isInActiveWindow && - !QueueAnimatedContentForRefresh(aFrame->GetContent(), 10)) { - NS_WARNING("Unable to animate button!"); - } - DrawButton(cgContext, kThemePushButton, macRect, isInActiveWindow, - kThemeButtonOff, kThemeAdornmentNone, eventState, aFrame); - } else if (IsButtonTypeMenu(aFrame)) { - DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame); - } else { - DrawPushButton(cgContext, macRect, eventState, aWidgetType, aFrame, - nativeWidgetHeight); - } - break; - - case NS_THEME_FOCUS_OUTLINE: - DrawFocusOutline(cgContext, macRect, eventState, aWidgetType, aFrame); - break; - - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - DrawPushButton(cgContext, macRect, eventState, aWidgetType, aFrame, - nativeWidgetHeight); - break; - - case NS_THEME_BUTTON_BEVEL: - DrawButton(cgContext, kThemeMediumBevelButton, macRect, - IsDefaultButton(aFrame), kThemeButtonOff, kThemeAdornmentNone, - eventState, aFrame); - break; - - case NS_THEME_SPINNER: { - nsIContent* content = aFrame->GetContent(); - if (content->IsHTMLElement()) { - // In HTML the theming for the spin buttons is drawn individually into - // their own backgrounds instead of being drawn into the background of - // their spinner parent as it is for XUL. - break; - } - ThemeDrawState state = kThemeStateActive; - if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state, - NS_LITERAL_STRING("up"), eCaseMatters)) { - state = kThemeStatePressedUp; - } - else if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::state, - NS_LITERAL_STRING("down"), eCaseMatters)) { - state = kThemeStatePressedDown; - } - - DrawSpinButtons(cgContext, kThemeIncDecButton, macRect, state, - kThemeAdornmentNone, eventState, aFrame); - } - break; - - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: { - nsNumberControlFrame* numberControlFrame = - nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame); - if (numberControlFrame) { - ThemeDrawState state = kThemeStateActive; - if (numberControlFrame->SpinnerUpButtonIsDepressed()) { - state = kThemeStatePressedUp; - } else if (numberControlFrame->SpinnerDownButtonIsDepressed()) { - state = kThemeStatePressedDown; - } - DrawSpinButton(cgContext, kThemeIncDecButtonMini, macRect, state, - kThemeAdornmentNone, eventState, aFrame, aWidgetType); - } - } - break; - - case NS_THEME_TOOLBARBUTTON: - DrawSegment(cgContext, macRect, eventState, aFrame, toolbarButtonRenderSettings); - break; - - case NS_THEME_SEPARATOR: { - HIThemeSeparatorDrawInfo sdi = { 0, kThemeStateActive }; - HIThemeDrawSeparator(&macRect, &sdi, cgContext, HITHEME_ORIENTATION); - } - break; - - case NS_THEME_TOOLBAR: { - NSWindow* win = NativeWindowForFrame(aFrame); - if (ToolbarCanBeUnified(cgContext, macRect, win)) { - DrawUnifiedToolbar(cgContext, macRect, win); - break; - } - BOOL isMain = [win isMainWindow]; - CGRect drawRect = macRect; - - // top border - drawRect.size.height = 1.0f; - DrawNativeGreyColorInRect(cgContext, toolbarTopBorderGrey, drawRect, isMain); - - // background - drawRect.origin.y += drawRect.size.height; - drawRect.size.height = macRect.size.height - 2.0f; - DrawNativeGreyColorInRect(cgContext, toolbarFillGrey, drawRect, isMain); - - // bottom border - drawRect.origin.y += drawRect.size.height; - drawRect.size.height = 1.0f; - DrawNativeGreyColorInRect(cgContext, toolbarBottomBorderGrey, drawRect, isMain); - } - break; - - case NS_THEME_WINDOW_TITLEBAR: { - NSWindow* win = NativeWindowForFrame(aFrame); - BOOL isMain = [win isMainWindow]; - float unifiedToolbarHeight = [win isKindOfClass:[ToolbarWindow class]] ? - [(ToolbarWindow*)win unifiedToolbarHeight] : macRect.size.height; - DrawNativeTitlebar(cgContext, macRect, unifiedToolbarHeight, isMain, YES); - } - break; - - case NS_THEME_STATUSBAR: - DrawStatusBar(cgContext, macRect, aFrame); - break; - - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_TEXTFIELD: - DrawDropdown(cgContext, macRect, eventState, aWidgetType, aFrame); - break; - - case NS_THEME_MENULIST_BUTTON: - DrawButton(cgContext, kThemeArrowButton, macRect, false, kThemeButtonOn, - kThemeAdornmentArrowDownArrow, eventState, aFrame); - break; - - case NS_THEME_GROUPBOX: { - HIThemeGroupBoxDrawInfo gdi = { 0, kThemeStateActive, kHIThemeGroupBoxKindPrimary }; - HIThemeDrawGroupBox(&macRect, &gdi, cgContext, HITHEME_ORIENTATION); - break; - } - - case NS_THEME_TEXTFIELD: - case NS_THEME_NUMBER_INPUT: - // HIThemeSetFill is not available on 10.3 - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextFillRect(cgContext, macRect); - - // XUL textboxes set the native appearance on the containing box, while - // concrete focus is set on the html:input element within it. We can - // though, check the focused attribute of xul textboxes in this case. - // On Mac, focus rings are always shown for textboxes, so we do not need - // to check the window's focus ring state here - if (aFrame->GetContent()->IsXULElement() && IsFocused(aFrame)) { - eventState |= NS_EVENT_STATE_FOCUS; - } - - DrawFrame(cgContext, kHIThemeFrameTextFieldSquare, macRect, - IsDisabled(aFrame, eventState) || IsReadOnly(aFrame), eventState); - break; - - case NS_THEME_SEARCHFIELD: - DrawSearchField(cgContext, macRect, aFrame, eventState); - break; - - case NS_THEME_PROGRESSBAR: - { - double value = GetProgressValue(aFrame); - double maxValue = GetProgressMaxValue(aFrame); - // Don't request repaints for scrollbars at 100% because those don't animate. - if (value < maxValue) { - if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) { - NS_WARNING("Unable to animate progressbar!"); - } - } - DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame, eventState), - !IsVerticalProgress(aFrame), - value, maxValue, aFrame); - break; - } - - case NS_THEME_PROGRESSBAR_VERTICAL: - DrawProgress(cgContext, macRect, IsIndeterminateProgress(aFrame, eventState), - false, GetProgressValue(aFrame), - GetProgressMaxValue(aFrame), aFrame); - break; - - case NS_THEME_METERBAR: - DrawMeter(cgContext, macRect, aFrame); - break; - - case NS_THEME_PROGRESSCHUNK: - case NS_THEME_PROGRESSCHUNK_VERTICAL: - case NS_THEME_METERCHUNK: - // Do nothing: progress and meter bars cases will draw chunks. - break; - - case NS_THEME_TREETWISTY: - DrawButton(cgContext, kThemeDisclosureButton, macRect, false, - kThemeDisclosureRight, kThemeAdornmentNone, eventState, aFrame); - break; - - case NS_THEME_TREETWISTYOPEN: - DrawButton(cgContext, kThemeDisclosureButton, macRect, false, - kThemeDisclosureDown, kThemeAdornmentNone, eventState, aFrame); - break; - - case NS_THEME_TREEHEADERCELL: { - TreeSortDirection sortDirection = GetTreeSortDirection(aFrame); - DrawButton(cgContext, kThemeListHeaderButton, macRect, false, - sortDirection == eTreeSortDirection_Natural ? kThemeButtonOff : kThemeButtonOn, - sortDirection == eTreeSortDirection_Ascending ? - kThemeAdornmentHeaderButtonSortUp : kThemeAdornmentNone, eventState, aFrame); - } - break; - - case NS_THEME_TREEITEM: - case NS_THEME_TREEVIEW: - // HIThemeSetFill is not available on 10.3 - // HIThemeSetFill(kThemeBrushWhite, NULL, cgContext, HITHEME_ORIENTATION); - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextFillRect(cgContext, macRect); - break; - - case NS_THEME_TREEHEADER: - // do nothing, taken care of by individual header cells - case NS_THEME_TREEHEADERSORTARROW: - // do nothing, taken care of by treeview header - case NS_THEME_TREELINE: - // do nothing, these lines don't exist on macos - break; - - case NS_THEME_SCALE_HORIZONTAL: - case NS_THEME_SCALE_VERTICAL: { - int32_t curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0); - int32_t minpos = CheckIntAttr(aFrame, nsGkAtoms::minpos, 0); - int32_t maxpos = CheckIntAttr(aFrame, nsGkAtoms::maxpos, 100); - if (!maxpos) - maxpos = 100; - - bool reverse = aFrame->GetContent()-> - AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir, - NS_LITERAL_STRING("reverse"), eCaseMatters); - DrawScale(cgContext, macRect, eventState, - (aWidgetType == NS_THEME_SCALE_VERTICAL), reverse, - curpos, minpos, maxpos, aFrame); - } - break; - - case NS_THEME_SCALETHUMB_HORIZONTAL: - case NS_THEME_SCALETHUMB_VERTICAL: - // do nothing, drawn by scale - break; - - case NS_THEME_RANGE: { - nsRangeFrame *rangeFrame = do_QueryFrame(aFrame); - if (!rangeFrame) { - break; - } - // DrawScale requires integer min, max and value. This is purely for - // drawing, so we normalize to a range 0-1000 here. - int32_t value = int32_t(rangeFrame->GetValueAsFractionOfRange() * 1000); - int32_t min = 0; - int32_t max = 1000; - bool isVertical = !IsRangeHorizontal(aFrame); - bool reverseDir = isVertical || rangeFrame->IsRightToLeft(); - DrawScale(cgContext, macRect, eventState, isVertical, reverseDir, - value, min, max, aFrame); - break; - } - - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBAR: - break; - case NS_THEME_SCROLLBARTHUMB_VERTICAL: - case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: { - BOOL isOverlay = nsLookAndFeel::UseOverlayScrollbars(); - BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL); - BOOL isRolledOver = IsParentScrollbarRolledOver(aFrame); - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - bool isSmall = (scrollbarFrame && scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL); - if (isOverlay && !isRolledOver) { - if (isHorizontal) { - macRect.origin.y += 4; - macRect.size.height -= 4; - } else { - if (aFrame->StyleVisibility()->mDirection != - NS_STYLE_DIRECTION_RTL) { - macRect.origin.x += 4; - } - macRect.size.width -= 4; - } - } - const BOOL isOnTopOfDarkBackground = IsDarkBackground(aFrame); - NSMutableDictionary* options = [NSMutableDictionary dictionaryWithObjectsAndKeys: - (isOverlay ? @"kCUIWidgetOverlayScrollBar" : @"scrollbar"), @"widget", - (isSmall ? @"small" : @"regular"), @"size", - (isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey", - (isOverlay && isOnTopOfDarkBackground ? @"kCUIVariantWhite" : @""), @"kCUIVariantKey", - [NSNumber numberWithBool:YES], @"indiconly", - [NSNumber numberWithBool:YES], @"kCUIThumbProportionKey", - [NSNumber numberWithBool:YES], @"is.flipped", - nil]; - if (isRolledOver) { - [options setObject:@"rollover" forKey:@"state"]; - } - RenderWithCoreUI(macRect, cgContext, options, true); - } - break; - - case NS_THEME_SCROLLBARBUTTON_UP: - case NS_THEME_SCROLLBARBUTTON_LEFT: -#if SCROLLBARS_VISUAL_DEBUG - CGContextSetRGBFillColor(cgContext, 1.0, 0, 0, 0.6); - CGContextFillRect(cgContext, macRect); -#endif - break; - case NS_THEME_SCROLLBARBUTTON_DOWN: - case NS_THEME_SCROLLBARBUTTON_RIGHT: -#if SCROLLBARS_VISUAL_DEBUG - CGContextSetRGBFillColor(cgContext, 0, 1.0, 0, 0.6); - CGContextFillRect(cgContext, macRect); -#endif - break; - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: { - BOOL isOverlay = nsLookAndFeel::UseOverlayScrollbars(); - if (!isOverlay || IsParentScrollbarRolledOver(aFrame)) { - BOOL isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL); - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - bool isSmall = (scrollbarFrame && scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL); - const BOOL isOnTopOfDarkBackground = IsDarkBackground(aFrame); - RenderWithCoreUI(macRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - (isOverlay ? @"kCUIWidgetOverlayScrollBar" : @"scrollbar"), @"widget", - (isSmall ? @"small" : @"regular"), @"size", - (isHorizontal ? @"kCUIOrientHorizontal" : @"kCUIOrientVertical"), @"kCUIOrientationKey", - (isOnTopOfDarkBackground ? @"kCUIVariantWhite" : @""), @"kCUIVariantKey", - [NSNumber numberWithBool:YES], @"noindicator", - [NSNumber numberWithBool:YES], @"kCUIThumbProportionKey", - [NSNumber numberWithBool:YES], @"is.flipped", - nil], - true); - } - } - break; - - case NS_THEME_TEXTFIELD_MULTILINE: { - // we have to draw this by hand because there is no HITheme value for it - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - - CGContextFillRect(cgContext, macRect); - - // #737373 for the top border, #999999 for the rest. - float x = macRect.origin.x, y = macRect.origin.y; - float w = macRect.size.width, h = macRect.size.height; - CGContextSetRGBFillColor(cgContext, 0.4510, 0.4510, 0.4510, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y, w, 1)); - CGContextSetRGBFillColor(cgContext, 0.6, 0.6, 0.6, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1)); - - // draw a focus ring - if (eventState.HasState(NS_EVENT_STATE_FOCUS)) { - NSGraphicsContext* savedContext = [NSGraphicsContext currentContext]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]]; - CGContextSaveGState(cgContext); - NSSetFocusRingStyle(NSFocusRingOnly); - NSRectFill(NSRectFromCGRect(macRect)); - CGContextRestoreGState(cgContext); - [NSGraphicsContext setCurrentContext:savedContext]; - } - } - break; - - case NS_THEME_LISTBOX: { - // We have to draw this by hand because kHIThemeFrameListBox drawing - // is buggy on 10.5, see bug 579259. - CGContextSetRGBFillColor(cgContext, 1.0, 1.0, 1.0, 1.0); - CGContextFillRect(cgContext, macRect); - - // #8E8E8E for the top border, #BEBEBE for the rest. - float x = macRect.origin.x, y = macRect.origin.y; - float w = macRect.size.width, h = macRect.size.height; - CGContextSetRGBFillColor(cgContext, 0.557, 0.557, 0.557, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y, w, 1)); - CGContextSetRGBFillColor(cgContext, 0.745, 0.745, 0.745, 1.0); - CGContextFillRect(cgContext, CGRectMake(x, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + w - 1, y + 1, 1, h - 1)); - CGContextFillRect(cgContext, CGRectMake(x + 1, y + h - 1, w - 2, 1)); - } - break; - - case NS_THEME_MAC_SOURCE_LIST: { - if (VibrancyManager::SystemSupportsVibrancy()) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - CGGradientRef backgroundGradient; - CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - CGFloat activeGradientColors[8] = { 0.9137, 0.9294, 0.9490, 1.0, - 0.8196, 0.8471, 0.8784, 1.0 }; - CGFloat inactiveGradientColors[8] = { 0.9686, 0.9686, 0.9686, 1.0, - 0.9216, 0.9216, 0.9216, 1.0 }; - CGPoint start = macRect.origin; - CGPoint end = CGPointMake(macRect.origin.x, - macRect.origin.y + macRect.size.height); - BOOL isActive = FrameIsInActiveWindow(aFrame); - backgroundGradient = - CGGradientCreateWithColorComponents(rgb, isActive ? activeGradientColors - : inactiveGradientColors, NULL, 2); - CGContextDrawLinearGradient(cgContext, backgroundGradient, start, end, 0); - CGGradientRelease(backgroundGradient); - CGColorSpaceRelease(rgb); - } - } - break; - - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: { - // If we're in XUL tree, we need to rely on the source list's clear - // background display item. If we cleared the background behind the - // selections, the source list would not pick up the right font - // smoothing background. So, to simplify a bit, we only support vibrancy - // if we're in a source list. - if (VibrancyManager::SystemSupportsVibrancy() && IsInSourceList(aFrame)) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - } else { - BOOL isActiveSelection = - aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION; - RenderWithCoreUI(macRect, cgContext, - [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:isActiveSelection], @"focus", - [NSNumber numberWithBool:YES], @"is.flipped", - @"kCUIVariantGradientSideBarSelection", @"kCUIVariantKey", - (FrameIsInActiveWindow(aFrame) ? @"normal" : @"inactive"), @"state", - @"gradient", @"widget", - nil]); - } - } - break; - - case NS_THEME_TAB: - DrawSegment(cgContext, macRect, eventState, aFrame, tabRenderSettings); - break; - - case NS_THEME_TABPANELS: - DrawTabPanel(cgContext, macRect, aFrame); - break; - - case NS_THEME_RESIZER: - DrawResizer(cgContext, macRect, aFrame); - break; - - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - DrawVibrancyBackground(cgContext, macRect, aFrame, type); - break; - } - } - - if (hidpi) { - // Reset the base CTM. - CGContextSetBaseCTM(cgContext, CGAffineTransformIdentity); - } - - nativeDrawing.EndNativeDrawing(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsIntMargin -nsNativeThemeCocoa::DirectionAwareMargin(const nsIntMargin& aMargin, - nsIFrame* aFrame) -{ - // Assuming aMargin was originally specified for a horizontal LTR context, - // reinterpret the values as logical, and then map to physical coords - // according to aFrame's actual writing mode. - WritingMode wm = aFrame->GetWritingMode(); - nsMargin m = LogicalMargin(wm, aMargin.top, aMargin.right, aMargin.bottom, - aMargin.left).GetPhysicalMargin(wm); - return nsIntMargin(m.top, m.right, m.bottom, m.left); -} - -static const nsIntMargin kAquaDropdownBorder(1, 22, 2, 5); -static const nsIntMargin kAquaComboboxBorder(3, 20, 3, 4); -static const nsIntMargin kAquaSearchfieldBorder(3, 5, 2, 19); - -NS_IMETHODIMP -nsNativeThemeCocoa::GetWidgetBorder(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - aResult->SizeTo(0, 0, 0, 0); - - switch (aWidgetType) { - case NS_THEME_BUTTON: - { - if (IsButtonTypeMenu(aFrame)) { - *aResult = DirectionAwareMargin(kAquaDropdownBorder, aFrame); - } else { - *aResult = DirectionAwareMargin(nsIntMargin(1, 7, 3, 7), aFrame); - } - break; - } - - case NS_THEME_TOOLBARBUTTON: - { - *aResult = DirectionAwareMargin(nsIntMargin(1, 4, 1, 4), aFrame); - break; - } - - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: - { - // nsFormControlFrame::GetIntrinsicWidth and nsFormControlFrame::GetIntrinsicHeight - // assume a border width of 2px. - aResult->SizeTo(2, 2, 2, 2); - break; - } - - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - *aResult = DirectionAwareMargin(kAquaDropdownBorder, aFrame); - break; - - case NS_THEME_MENULIST_TEXTFIELD: - *aResult = DirectionAwareMargin(kAquaComboboxBorder, aFrame); - break; - - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricEditTextFrameOutset, &frameOutset); - - SInt32 textPadding = 0; - ::GetThemeMetric(kThemeMetricEditTextWhitespace, &textPadding); - - frameOutset += textPadding; - - aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset); - break; - } - - case NS_THEME_TEXTFIELD_MULTILINE: - aResult->SizeTo(1, 1, 1, 1); - break; - - case NS_THEME_SEARCHFIELD: - *aResult = DirectionAwareMargin(kAquaSearchfieldBorder, aFrame); - break; - - case NS_THEME_LISTBOX: - { - SInt32 frameOutset = 0; - ::GetThemeMetric(kThemeMetricListBoxFrameOutset, &frameOutset); - aResult->SizeTo(frameOutset, frameOutset, frameOutset, frameOutset); - break; - } - - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: - { - bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL); - if (nsLookAndFeel::UseOverlayScrollbars()) { - if (!nsCocoaFeatures::OnYosemiteOrLater()) { - // Pre-10.10, we have to center the thumb rect in the middle of the - // scrollbar. Starting with 10.10, the expected rect for thumb - // rendering is the full width of the scrollbar. - if (isHorizontal) { - aResult->top = 2; - aResult->bottom = 1; - } else { - aResult->left = 2; - aResult->right = 1; - } - } - // Leave a bit of space at the start and the end on all OS X versions. - if (isHorizontal) { - aResult->left = 1; - aResult->right = 1; - } else { - aResult->top = 1; - aResult->bottom = 1; - } - } - - break; - } - - case NS_THEME_STATUSBAR: - aResult->SizeTo(1, 0, 0, 0); - break; - } - - if (IsHiDPIContext(aFrame->PresContext())) { - *aResult = *aResult + *aResult; // doubled - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Return false here to indicate that CSS padding values should be used. There is -// no reason to make a distinction between padding and border values, just specify -// whatever values you want in GetWidgetBorder and only use this to return true -// if you want to override CSS padding values. -bool -nsNativeThemeCocoa::GetWidgetPadding(nsDeviceContext* aContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - nsIntMargin* aResult) -{ - // We don't want CSS padding being used for certain widgets. - // See bug 381639 for an example of why. - switch (aWidgetType) { - // Radios and checkboxes return a fixed size in GetMinimumWidgetSize - // and have a meaningful baseline, so they can't have - // author-specified padding. - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: - aResult->SizeTo(0, 0, 0, 0); - return true; - } - return false; -} - -bool -nsNativeThemeCocoa::GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame, - uint8_t aWidgetType, nsRect* aOverflowRect) -{ - int32_t p2a = aFrame->PresContext()->AppUnitsPerDevPixel(); - switch (aWidgetType) { - case NS_THEME_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_TOOLBARBUTTON: - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_SEARCHFIELD: - case NS_THEME_LISTBOX: - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - case NS_THEME_MENULIST_TEXTFIELD: - case NS_THEME_CHECKBOX: - case NS_THEME_RADIO: - case NS_THEME_TAB: - { - // We assume that the above widgets can draw a focus ring that will be less than - // or equal to 4 pixels thick. - nsIntMargin extraSize = nsIntMargin(kMaxFocusRingWidth, - kMaxFocusRingWidth, - kMaxFocusRingWidth, - kMaxFocusRingWidth); - nsMargin m(NSIntPixelsToAppUnits(extraSize.top, p2a), - NSIntPixelsToAppUnits(extraSize.right, p2a), - NSIntPixelsToAppUnits(extraSize.bottom, p2a), - NSIntPixelsToAppUnits(extraSize.left, p2a)); - aOverflowRect->Inflate(m); - return true; - } - case NS_THEME_PROGRESSBAR: - { - // Progress bars draw a 2 pixel white shadow under their progress indicators - nsMargin m(0, 0, NSIntPixelsToAppUnits(2, p2a), 0); - aOverflowRect->Inflate(m); - return true; - } - case NS_THEME_FOCUS_OUTLINE: - { - aOverflowRect->Inflate(NSIntPixelsToAppUnits(2, p2a)); - return true; - } - } - - return false; -} - -static const int32_t kRegularScrollbarThumbMinSize = 26; -static const int32_t kSmallScrollbarThumbMinSize = 26; - -NS_IMETHODIMP -nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext, - nsIFrame* aFrame, - uint8_t aWidgetType, - LayoutDeviceIntSize* aResult, - bool* aIsOverridable) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - aResult->SizeTo(0,0); - *aIsOverridable = true; - - switch (aWidgetType) { - case NS_THEME_BUTTON: - { - aResult->SizeTo(pushButtonSettings.minimumSizes[miniControlSize].width, - pushButtonSettings.naturalSizes[miniControlSize].height); - break; - } - - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - { - aResult->SizeTo(kMenuScrollArrowSize.width, kMenuScrollArrowSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MENUARROW: - { - aResult->SizeTo(kMenuarrowSize.width, kMenuarrowSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - { - aResult->SizeTo(kDisclosureButtonSize.width, kDisclosureButtonSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MAC_HELP_BUTTON: - { - aResult->SizeTo(kHelpButtonSize.width, kHelpButtonSize.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_TOOLBARBUTTON: - { - aResult->SizeTo(0, toolbarButtonHeights[miniControlSize]); - break; - } - - case NS_THEME_SPINNER: - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: - { - SInt32 buttonHeight = 0, buttonWidth = 0; - if (aFrame->GetContent()->IsXULElement()) { - ::GetThemeMetric(kThemeMetricLittleArrowsWidth, &buttonWidth); - ::GetThemeMetric(kThemeMetricLittleArrowsHeight, &buttonHeight); - } else { - NSSize size = - spinnerSettings.minimumSizes[EnumSizeForCocoaSize(NSMiniControlSize)]; - buttonWidth = size.width; - buttonHeight = size.height; - if (aWidgetType != NS_THEME_SPINNER) { - // the buttons are half the height of the spinner - buttonHeight /= 2; - } - } - aResult->SizeTo(buttonWidth, buttonHeight); - *aIsOverridable = true; - break; - } - - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - { - SInt32 popupHeight = 0; - ::GetThemeMetric(kThemeMetricPopupButtonHeight, &popupHeight); - aResult->SizeTo(0, popupHeight); - break; - } - - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_SEARCHFIELD: - { - // at minimum, we should be tall enough for 9pt text. - // I'm using hardcoded values here because the appearance manager - // values for the frame size are incorrect. - aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */); - break; - } - - case NS_THEME_WINDOW_BUTTON_BOX: { - NSSize size = WindowButtonsSize(aFrame); - aResult->SizeTo(size.width, size.height); - *aIsOverridable = false; - break; - } - - case NS_THEME_MAC_FULLSCREEN_BUTTON: { - if ([NativeWindowForFrame(aFrame) respondsToSelector:@selector(toggleFullScreen:)] && - !nsCocoaFeatures::OnYosemiteOrLater()) { - // This value is hardcoded because it's needed before we can measure the - // position and size of the fullscreen button. - aResult->SizeTo(16, 17); - } - *aIsOverridable = false; - break; - } - - case NS_THEME_PROGRESSBAR: - { - SInt32 barHeight = 0; - ::GetThemeMetric(kThemeMetricNormalProgressBarThickness, &barHeight); - aResult->SizeTo(0, barHeight); - break; - } - - case NS_THEME_TREETWISTY: - case NS_THEME_TREETWISTYOPEN: - { - SInt32 twistyHeight = 0, twistyWidth = 0; - ::GetThemeMetric(kThemeMetricDisclosureButtonWidth, &twistyWidth); - ::GetThemeMetric(kThemeMetricDisclosureButtonHeight, &twistyHeight); - aResult->SizeTo(twistyWidth, twistyHeight); - *aIsOverridable = false; - break; - } - - case NS_THEME_TREEHEADER: - case NS_THEME_TREEHEADERCELL: - { - SInt32 headerHeight = 0; - ::GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight); - aResult->SizeTo(0, headerHeight - 1); // We don't need the top border. - break; - } - - case NS_THEME_TAB: - { - aResult->SizeTo(0, tabHeights[miniControlSize]); - break; - } - - case NS_THEME_RANGE: - { - // The Mac Appearance Manager API (the old API we're currently using) - // doesn't define constants to obtain a minimum size for sliders. We use - // the "thickness" of a slider that has default dimensions for both the - // minimum width and height to get something sane and so that paint - // invalidation works. - SInt32 size = 0; - if (IsRangeHorizontal(aFrame)) { - ::GetThemeMetric(kThemeMetricHSliderHeight, &size); - } else { - ::GetThemeMetric(kThemeMetricVSliderWidth, &size); - } - aResult->SizeTo(size, size); - *aIsOverridable = true; - break; - } - - case NS_THEME_RANGE_THUMB: - { - SInt32 width = 0; - SInt32 height = 0; - ::GetThemeMetric(kThemeMetricSliderMinThumbWidth, &width); - ::GetThemeMetric(kThemeMetricSliderMinThumbHeight, &height); - aResult->SizeTo(width, height); - *aIsOverridable = false; - break; - } - - case NS_THEME_SCALE_HORIZONTAL: - { - SInt32 scaleHeight = 0; - ::GetThemeMetric(kThemeMetricHSliderHeight, &scaleHeight); - aResult->SizeTo(scaleHeight, scaleHeight); - *aIsOverridable = false; - break; - } - - case NS_THEME_SCALE_VERTICAL: - { - SInt32 scaleWidth = 0; - ::GetThemeMetric(kThemeMetricVSliderWidth, &scaleWidth); - aResult->SizeTo(scaleWidth, scaleWidth); - *aIsOverridable = false; - break; - } - - case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: - case NS_THEME_SCROLLBARTHUMB_VERTICAL: - { - // Find our parent scrollbar frame in order to find out whether we're in - // a small or a large scrollbar. - nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (!scrollbarFrame) { - return NS_ERROR_FAILURE; - } - - bool isSmall = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL); - bool isHorizontal = (aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL); - int32_t& minSize = isHorizontal ? aResult->width : aResult->height; - minSize = isSmall ? kSmallScrollbarThumbMinSize : kRegularScrollbarThumbMinSize; - break; - } - - case NS_THEME_SCROLLBAR: - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - { - *aIsOverridable = false; - - if (nsLookAndFeel::UseOverlayScrollbars()) { - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (scrollbarFrame && - scrollbarFrame->StyleDisplay()->mAppearance == - NS_THEME_SCROLLBAR_SMALL) { - aResult->SizeTo(14, 14); - } - else { - aResult->SizeTo(16, 16); - } - if (IsScrollbarWidthThin(aFrame)) { - aResult->SizeTo(8, 8); - } - break; - } - - // yeah, i know i'm cheating a little here, but i figure that it - // really doesn't matter if the scrollbar is vertical or horizontal - // and the width metric is a really good metric for every piece - // of the scrollbar. - - nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (!scrollbarFrame) return NS_ERROR_FAILURE; - - int32_t themeMetric = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? - kThemeMetricSmallScrollBarWidth : - kThemeMetricScrollBarWidth; - SInt32 scrollbarWidth = 0; - ::GetThemeMetric(themeMetric, &scrollbarWidth); - if (IsScrollbarWidthThin(aFrame)) { - scrollbarWidth /= 2; - } - aResult->SizeTo(scrollbarWidth, scrollbarWidth); - break; - } - - case NS_THEME_SCROLLBAR_NON_DISAPPEARING: - { - int32_t themeMetric = kThemeMetricScrollBarWidth; - - if (aFrame) { - nsIFrame* scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (scrollbarFrame && - scrollbarFrame->StyleDisplay()->mAppearance == - NS_THEME_SCROLLBAR_SMALL) { - // XXX We're interested in the width of non-disappearing scrollbars - // to leave enough space for a dropmarker in non-native styled - // comboboxes (bug 869314). It isn't clear to me if comboboxes can - // ever have small scrollbars. - themeMetric = kThemeMetricSmallScrollBarWidth; - } - } - - SInt32 scrollbarWidth = 0; - ::GetThemeMetric(themeMetric, &scrollbarWidth); - aResult->SizeTo(scrollbarWidth, scrollbarWidth); - break; - } - - case NS_THEME_SCROLLBARBUTTON_UP: - case NS_THEME_SCROLLBARBUTTON_DOWN: - case NS_THEME_SCROLLBARBUTTON_LEFT: - case NS_THEME_SCROLLBARBUTTON_RIGHT: - { - if (!IsScrollbarWidthThin(aFrame)) { - // Get scrollbar button metrics from the system, except in the case of - // thin scrollbars, where we leave them at 0 (collapse) - - nsIFrame *scrollbarFrame = GetParentScrollbarFrame(aFrame); - if (!scrollbarFrame) return NS_ERROR_FAILURE; - - // Since there is no NS_THEME_SCROLLBARBUTTON_UP_SMALL we need to ask the parent what appearance style it has. - int32_t themeMetric = (scrollbarFrame->StyleDisplay()->mAppearance == NS_THEME_SCROLLBAR_SMALL) ? - kThemeMetricSmallScrollBarWidth : - kThemeMetricScrollBarWidth; - SInt32 scrollbarWidth = 0; - ::GetThemeMetric(themeMetric, &scrollbarWidth); - - // It seems that for both sizes of scrollbar, the buttons are one pixel "longer". - if (aWidgetType == NS_THEME_SCROLLBARBUTTON_LEFT || aWidgetType == NS_THEME_SCROLLBARBUTTON_RIGHT) - aResult->SizeTo(scrollbarWidth+1, scrollbarWidth); - else - aResult->SizeTo(scrollbarWidth, scrollbarWidth+1); - } - *aIsOverridable = false; - break; - } - case NS_THEME_RESIZER: - { - HIThemeGrowBoxDrawInfo drawInfo; - drawInfo.version = 0; - drawInfo.state = kThemeStateActive; - drawInfo.kind = kHIThemeGrowBoxKindNormal; - drawInfo.direction = kThemeGrowRight | kThemeGrowDown; - drawInfo.size = kHIThemeGrowBoxSizeNormal; - HIPoint pnt = { 0, 0 }; - HIRect bounds; - HIThemeGetGrowBoxBounds(&pnt, &drawInfo, &bounds); - aResult->SizeTo(bounds.size.width, bounds.size.height); - *aIsOverridable = false; - } - } - - if (IsHiDPIContext(aPresContext)) { - *aResult = *aResult * 2; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsNativeThemeCocoa::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, - nsIAtom* aAttribute, bool* aShouldRepaint, - const nsAttrValue* aOldValue) -{ - // Some widget types just never change state. - switch (aWidgetType) { - case NS_THEME_WINDOW_TITLEBAR: - case NS_THEME_TOOLBOX: - case NS_THEME_TOOLBAR: - case NS_THEME_STATUSBAR: - case NS_THEME_STATUSBARPANEL: - case NS_THEME_RESIZERPANEL: - case NS_THEME_TOOLTIP: - case NS_THEME_TABPANELS: - case NS_THEME_TABPANEL: - case NS_THEME_DIALOG: - case NS_THEME_MENUPOPUP: - case NS_THEME_GROUPBOX: - case NS_THEME_PROGRESSCHUNK: - case NS_THEME_PROGRESSCHUNK_VERTICAL: - case NS_THEME_PROGRESSBAR: - case NS_THEME_PROGRESSBAR_VERTICAL: - case NS_THEME_METERBAR: - case NS_THEME_METERCHUNK: - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - *aShouldRepaint = false; - return NS_OK; - } - - // XXXdwh Not sure what can really be done here. Can at least guess for - // specific widgets that they're highly unlikely to have certain states. - // For example, a toolbar doesn't care about any states. - if (!aAttribute) { - // Hover/focus/active changed. Always repaint. - *aShouldRepaint = true; - } else { - // Check the attribute to see if it's relevant. - // disabled, checked, dlgtype, default, etc. - *aShouldRepaint = false; - if (aAttribute == nsGkAtoms::disabled || - aAttribute == nsGkAtoms::checked || - aAttribute == nsGkAtoms::selected || - aAttribute == nsGkAtoms::visuallyselected || - aAttribute == nsGkAtoms::menuactive || - aAttribute == nsGkAtoms::sortDirection || - aAttribute == nsGkAtoms::focused || - aAttribute == nsGkAtoms::_default || - aAttribute == nsGkAtoms::open || - aAttribute == nsGkAtoms::hover) - *aShouldRepaint = true; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsNativeThemeCocoa::ThemeChanged() -{ - // This is unimplemented because we don't care if gecko changes its theme - // and Mac OS X doesn't have themes. - return NS_OK; -} - -bool -nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, - uint8_t aWidgetType) -{ - // We don't have CSS set up to render non-native scrollbars on Mac OS X so we - // render natively even if native theme support is disabled. - if (aWidgetType != NS_THEME_SCROLLBAR && - aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled()) - return false; - - // if this is a dropdown button in a combobox the answer is always no - if (aWidgetType == NS_THEME_MENULIST_BUTTON) { - nsIFrame* parentFrame = aFrame->GetParent(); - if (parentFrame && (parentFrame->GetType() == nsGkAtoms::comboboxControlFrame)) - return false; - } - - switch (aWidgetType) { - // Combobox dropdowns don't support native theming in vertical mode. - case NS_THEME_MENULIST: - case NS_THEME_MENULIST_BUTTON: - case NS_THEME_MENULIST_TEXT: - case NS_THEME_MENULIST_TEXTFIELD: - if (aFrame && aFrame->GetWritingMode().IsVertical()) { - return false; - } - MOZ_FALLTHROUGH; - - case NS_THEME_LISTBOX: - - case NS_THEME_DIALOG: - case NS_THEME_WINDOW: - case NS_THEME_WINDOW_BUTTON_BOX: - case NS_THEME_WINDOW_TITLEBAR: - case NS_THEME_CHECKMENUITEM: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUARROW: - case NS_THEME_MENUITEM: - case NS_THEME_MENUSEPARATOR: - case NS_THEME_MAC_FULLSCREEN_BUTTON: - case NS_THEME_TOOLTIP: - - case NS_THEME_CHECKBOX: - case NS_THEME_CHECKBOX_CONTAINER: - case NS_THEME_RADIO: - case NS_THEME_RADIO_CONTAINER: - case NS_THEME_GROUPBOX: - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - case NS_THEME_BUTTON: - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - case NS_THEME_BUTTON_BEVEL: - case NS_THEME_TOOLBARBUTTON: - case NS_THEME_SPINNER: - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: - case NS_THEME_TOOLBAR: - case NS_THEME_STATUSBAR: - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_SEARCHFIELD: - case NS_THEME_TOOLBOX: - //case NS_THEME_TOOLBARBUTTON: - case NS_THEME_PROGRESSBAR: - case NS_THEME_PROGRESSBAR_VERTICAL: - case NS_THEME_PROGRESSCHUNK: - case NS_THEME_PROGRESSCHUNK_VERTICAL: - case NS_THEME_METERBAR: - case NS_THEME_METERCHUNK: - case NS_THEME_SEPARATOR: - - case NS_THEME_TABPANELS: - case NS_THEME_TAB: - - case NS_THEME_TREETWISTY: - case NS_THEME_TREETWISTYOPEN: - case NS_THEME_TREEVIEW: - case NS_THEME_TREEHEADER: - case NS_THEME_TREEHEADERCELL: - case NS_THEME_TREEHEADERSORTARROW: - case NS_THEME_TREEITEM: - case NS_THEME_TREELINE: - case NS_THEME_MAC_SOURCE_LIST: - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - - case NS_THEME_RANGE: - - case NS_THEME_SCALE_HORIZONTAL: - case NS_THEME_SCALETHUMB_HORIZONTAL: - case NS_THEME_SCALE_VERTICAL: - case NS_THEME_SCALETHUMB_VERTICAL: - - case NS_THEME_SCROLLBAR: - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBARBUTTON_UP: - case NS_THEME_SCROLLBARBUTTON_DOWN: - case NS_THEME_SCROLLBARBUTTON_LEFT: - case NS_THEME_SCROLLBARBUTTON_RIGHT: - case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: - case NS_THEME_SCROLLBARTHUMB_VERTICAL: - case NS_THEME_SCROLLBARTRACK_VERTICAL: - case NS_THEME_SCROLLBARTRACK_HORIZONTAL: - case NS_THEME_SCROLLBAR_NON_DISAPPEARING: - return !IsWidgetStyled(aPresContext, aFrame, aWidgetType); - - case NS_THEME_RESIZER: - { - nsIFrame* parentFrame = aFrame->GetParent(); - if (!parentFrame || parentFrame->GetType() != nsGkAtoms::scrollFrame) - return true; - - // Note that IsWidgetStyled is not called for resizers on Mac. This is - // because for scrollable containers, the native resizer looks better - // when (non-overlay) scrollbars are present even when the style is - // overriden, and the custom transparent resizer looks better when - // scrollbars are not present. - nsIScrollableFrame* scrollFrame = do_QueryFrame(parentFrame); - return (!nsLookAndFeel::UseOverlayScrollbars() && - scrollFrame && scrollFrame->GetScrollbarVisibility()); - } - - case NS_THEME_FOCUS_OUTLINE: - return true; - - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - return VibrancyManager::SystemSupportsVibrancy(); - } - - return false; -} - -bool -nsNativeThemeCocoa::WidgetIsContainer(uint8_t aWidgetType) -{ - // flesh this out at some point - switch (aWidgetType) { - case NS_THEME_MENULIST_BUTTON: - case NS_THEME_RADIO: - case NS_THEME_CHECKBOX: - case NS_THEME_PROGRESSBAR: - case NS_THEME_METERBAR: - case NS_THEME_RANGE: - case NS_THEME_MAC_HELP_BUTTON: - case NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN: - case NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED: - return false; - } - return true; -} - -bool -nsNativeThemeCocoa::ThemeDrawsFocusForWidget(uint8_t aWidgetType) -{ - if (aWidgetType == NS_THEME_MENULIST || - aWidgetType == NS_THEME_MENULIST_TEXTFIELD || - aWidgetType == NS_THEME_BUTTON || - aWidgetType == NS_THEME_MAC_HELP_BUTTON || - aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_OPEN || - aWidgetType == NS_THEME_MAC_DISCLOSURE_BUTTON_CLOSED || - aWidgetType == NS_THEME_RADIO || - aWidgetType == NS_THEME_RANGE || - aWidgetType == NS_THEME_CHECKBOX) - return true; - - return false; -} - -bool -nsNativeThemeCocoa::ThemeNeedsComboboxDropmarker() -{ - return false; -} - -bool -nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_DIALOG: - case NS_THEME_GROUPBOX: - case NS_THEME_TABPANELS: - case NS_THEME_BUTTON_ARROW_UP: - case NS_THEME_BUTTON_ARROW_DOWN: - case NS_THEME_CHECKMENUITEM: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUARROW: - case NS_THEME_MENUITEM: - case NS_THEME_MENUSEPARATOR: - case NS_THEME_TOOLTIP: - case NS_THEME_SPINNER: - case NS_THEME_SPINNER_UPBUTTON: - case NS_THEME_SPINNER_DOWNBUTTON: - case NS_THEME_SEPARATOR: - case NS_THEME_TOOLBOX: - case NS_THEME_NUMBER_INPUT: - case NS_THEME_TEXTFIELD: - case NS_THEME_TREEVIEW: - case NS_THEME_TREELINE: - case NS_THEME_TEXTFIELD_MULTILINE: - case NS_THEME_LISTBOX: - case NS_THEME_RESIZER: - return false; - default: - return true; - } -} - -bool -nsNativeThemeCocoa::IsWindowSheet(nsIFrame* aFrame) -{ - NSWindow* win = NativeWindowForFrame(aFrame); - id winDelegate = [win delegate]; - nsIWidget* widget = [(WindowDelegate *)winDelegate geckoWidget]; - if (!widget) { - return false; - } - return (widget->WindowType() == eWindowType_sheet); -} - -bool -nsNativeThemeCocoa::NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, - uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_MAC_SOURCE_LIST: - // If we're in a XUL tree, we don't want to clear the background behind the - // selections below, since that would make our source list to not pick up - // the right font smoothing background. But since we don't call this method - // in nsTreeBodyFrame::BuildDisplayList, we never get here. - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - case NS_THEME_TOOLTIP: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: - return true; - case NS_THEME_DIALOG: - return IsWindowSheet(aFrame); - default: - return false; - } -} - -static nscolor ConvertNSColor(NSColor* aColor) -{ - NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - return NS_RGBA((unsigned int)([deviceColor redComponent] * 255.0), - (unsigned int)([deviceColor greenComponent] * 255.0), - (unsigned int)([deviceColor blueComponent] * 255.0), - (unsigned int)([deviceColor alphaComponent] * 255.0)); -} - -bool -nsNativeThemeCocoa::WidgetProvidesFontSmoothingBackgroundColor(nsIFrame* aFrame, - uint8_t aWidgetType, - nscolor* aColor) -{ - switch (aWidgetType) { - case NS_THEME_MAC_SOURCE_LIST: - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - case NS_THEME_MAC_VIBRANCY_LIGHT: - case NS_THEME_MAC_VIBRANCY_DARK: - case NS_THEME_TOOLTIP: - case NS_THEME_MENUPOPUP: - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: - case NS_THEME_DIALOG: - { - if ((aWidgetType == NS_THEME_DIALOG && !IsWindowSheet(aFrame)) || - ((aWidgetType == NS_THEME_MAC_SOURCE_LIST_SELECTION || - aWidgetType == NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION) && - !IsInSourceList(aFrame))) { - return false; - } - ChildView* childView = ChildViewForFrame(aFrame); - if (childView) { - ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); - NSColor* color = [childView vibrancyFontSmoothingBackgroundColorForThemeGeometryType:type]; - *aColor = ConvertNSColor(color); - return true; - } - return false; - } - default: - return false; - } -} - -nsITheme::ThemeGeometryType -nsNativeThemeCocoa::ThemeGeometryTypeForWidget(nsIFrame* aFrame, uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_WINDOW_TITLEBAR: - return eThemeGeometryTypeTitlebar; - case NS_THEME_TOOLBAR: - return eThemeGeometryTypeToolbar; - case NS_THEME_TOOLBOX: - return eThemeGeometryTypeToolbox; - case NS_THEME_WINDOW_BUTTON_BOX: - return eThemeGeometryTypeWindowButtons; - case NS_THEME_MAC_FULLSCREEN_BUTTON: - return eThemeGeometryTypeFullscreenButton; - case NS_THEME_MAC_VIBRANCY_LIGHT: - return eThemeGeometryTypeVibrancyLight; - case NS_THEME_MAC_VIBRANCY_DARK: - return eThemeGeometryTypeVibrancyDark; - case NS_THEME_TOOLTIP: - return eThemeGeometryTypeTooltip; - case NS_THEME_MENUPOPUP: - return eThemeGeometryTypeMenu; - case NS_THEME_MENUITEM: - case NS_THEME_CHECKMENUITEM: { - EventStates eventState = GetContentState(aFrame, aWidgetType); - bool isDisabled = IsDisabled(aFrame, eventState); - bool isSelected = !isDisabled && CheckBooleanAttr(aFrame, nsGkAtoms::menuactive); - return isSelected ? eThemeGeometryTypeHighlightedMenuItem : eThemeGeometryTypeMenu; - } - case NS_THEME_DIALOG: - return IsWindowSheet(aFrame) ? eThemeGeometryTypeSheet : eThemeGeometryTypeUnknown; - case NS_THEME_MAC_SOURCE_LIST: - return eThemeGeometryTypeSourceList; - case NS_THEME_MAC_SOURCE_LIST_SELECTION: - return IsInSourceList(aFrame) ? eThemeGeometryTypeSourceListSelection - : eThemeGeometryTypeUnknown; - case NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION: - return IsInSourceList(aFrame) ? eThemeGeometryTypeActiveSourceListSelection - : eThemeGeometryTypeUnknown; - default: - return eThemeGeometryTypeUnknown; - } -} - -nsITheme::Transparency -nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) -{ - switch (aWidgetType) { - case NS_THEME_MENUPOPUP: - case NS_THEME_TOOLTIP: - return eTransparent; - - case NS_THEME_DIALOG: - return IsWindowSheet(aFrame) ? eTransparent : eOpaque; - - case NS_THEME_SCROLLBAR_SMALL: - case NS_THEME_SCROLLBAR: - return nsLookAndFeel::UseOverlayScrollbars() ? eTransparent : eOpaque; - - case NS_THEME_STATUSBAR: - // Knowing that scrollbars and statusbars are opaque improves - // performance, because we create layers for them. - return eOpaque; - - case NS_THEME_TOOLBAR: - return eOpaque; - - default: - return eUnknownTransparency; - } -} diff --git a/widget/cocoa/nsNativeThemeColors.h b/widget/cocoa/nsNativeThemeColors.h deleted file mode 100644 index b1691b5163..0000000000 --- a/widget/cocoa/nsNativeThemeColors.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 nsNativeThemeColors_h_ -#define nsNativeThemeColors_h_ - -#include "nsCocoaFeatures.h" -#import - -enum ColorName { - toolbarTopBorderGrey, - toolbarFillGrey, - toolbarBottomBorderGrey, -}; - -static const int sLionThemeColors[][2] = { - /* { active window, inactive window } */ - // toolbar: - { 0xD0, 0xF0 }, // top separator line - { 0xB2, 0xE1 }, // fill color - { 0x59, 0x87 }, // bottom separator line -}; - -static const int sYosemiteThemeColors[][2] = { - /* { active window, inactive window } */ - // toolbar: - { 0xBD, 0xDF }, // top separator line - { 0xD3, 0xF6 }, // fill color - { 0xB3, 0xD1 }, // bottom separator line -}; - -__attribute__((unused)) -static int NativeGreyColorAsInt(ColorName name, BOOL isMain) -{ - if (nsCocoaFeatures::OnYosemiteOrLater()) - return sYosemiteThemeColors[name][isMain ? 0 : 1]; - return sLionThemeColors[name][isMain ? 0 : 1]; -} - -__attribute__((unused)) -static float NativeGreyColorAsFloat(ColorName name, BOOL isMain) -{ - return NativeGreyColorAsInt(name, isMain) / 255.0f; -} - -__attribute__((unused)) -static void DrawNativeGreyColorInRect(CGContextRef context, ColorName name, - CGRect rect, BOOL isMain) -{ - float grey = NativeGreyColorAsFloat(name, isMain); - CGContextSetRGBFillColor(context, grey, grey, grey, 1.0f); - CGContextFillRect(context, rect); -} - -#endif // nsNativeThemeColors_h_ diff --git a/widget/cocoa/nsPIWidgetCocoa.idl b/widget/cocoa/nsPIWidgetCocoa.idl deleted file mode 100644 index a8fd8149ce..0000000000 --- a/widget/cocoa/nsPIWidgetCocoa.idl +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsISupports.idl" - -interface nsIWidget; - -[ptr] native NSWindowPtr(NSWindow); - -// -// nsPIWidgetCocoa -// -// A private interface (unfrozen, private to the widget implementation) that -// gives us access to some extra features on a widget/window. -// -[uuid(f75ff69e-3a51-419e-bd29-042f804bc2ed)] -interface nsPIWidgetCocoa : nsISupports -{ - void SendSetZLevelEvent(); - - // Find the displayed child sheet (if aShown) or a child sheet that - // wants to be displayed (if !aShown) - nsIWidget GetChildSheet(in boolean aShown); - - // Get the parent widget (if any) StandardCreate() was called with. - nsIWidget GetRealParent(); - - // If the object implementing this interface is a sheet, this will return the - // native NSWindow it is attached to - readonly attribute NSWindowPtr sheetWindowParent; - - // True if window is a sheet - readonly attribute boolean isSheet; - -}; // nsPIWidgetCocoa diff --git a/widget/cocoa/nsPrintDialogX.h b/widget/cocoa/nsPrintDialogX.h deleted file mode 100644 index 470f17d99d..0000000000 --- a/widget/cocoa/nsPrintDialogX.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsPrintDialog_h_ -#define nsPrintDialog_h_ - -#include "nsIPrintDialogService.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" - -#import - -class nsIPrintSettings; -class nsIStringBundle; - -class nsPrintDialogServiceX : public nsIPrintDialogService -{ -public: - nsPrintDialogServiceX(); - - NS_DECL_ISUPPORTS - - NS_IMETHOD Init() override; - NS_IMETHOD Show(nsPIDOMWindowOuter *aParent, nsIPrintSettings *aSettings, - nsIWebBrowserPrint *aWebBrowserPrint) override; - NS_IMETHOD ShowPageSetup(nsPIDOMWindowOuter *aParent, - nsIPrintSettings *aSettings) override; - -protected: - virtual ~nsPrintDialogServiceX(); -}; - -@interface PrintPanelAccessoryView : NSView -{ - nsIPrintSettings* mSettings; - nsIStringBundle* mPrintBundle; - NSButton* mPrintSelectionOnlyCheckbox; - NSButton* mShrinkToFitCheckbox; - NSButton* mPrintBGColorsCheckbox; - NSButton* mPrintBGImagesCheckbox; - NSButtonCell* mAsLaidOutRadio; - NSButtonCell* mSelectedFrameRadio; - NSButtonCell* mSeparateFramesRadio; - NSPopUpButton* mHeaderLeftList; - NSPopUpButton* mHeaderCenterList; - NSPopUpButton* mHeaderRightList; - NSPopUpButton* mFooterLeftList; - NSPopUpButton* mFooterCenterList; - NSPopUpButton* mFooterRightList; -} - -- (id)initWithSettings:(nsIPrintSettings*)aSettings; - -- (void)exportSettings; - -@end - -@interface PrintPanelAccessoryController : NSViewController - -- (id)initWithSettings:(nsIPrintSettings*)aSettings; - -- (void)exportSettings; - -@end - -#endif // nsPrintDialog_h_ diff --git a/widget/cocoa/nsPrintDialogX.mm b/widget/cocoa/nsPrintDialogX.mm deleted file mode 100644 index a6d58d5bfb..0000000000 --- a/widget/cocoa/nsPrintDialogX.mm +++ /dev/null @@ -1,682 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/ArrayUtils.h" - -#include "nsPrintDialogX.h" -#include "nsIPrintSettings.h" -#include "nsIPrintSettingsService.h" -#include "nsPrintSettingsX.h" -#include "nsCOMPtr.h" -#include "nsQueryObject.h" -#include "nsServiceManagerUtils.h" -#include "nsIWebProgressListener.h" -#include "nsIStringBundle.h" -#include "nsIWebBrowserPrint.h" -#include "nsCRT.h" - -#import -#include "nsObjCExceptions.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsPrintDialogServiceX, nsIPrintDialogService) - -nsPrintDialogServiceX::nsPrintDialogServiceX() -{ -} - -nsPrintDialogServiceX::~nsPrintDialogServiceX() -{ -} - -NS_IMETHODIMP -nsPrintDialogServiceX::Init() -{ - return NS_OK; -} - -NS_IMETHODIMP -nsPrintDialogServiceX::Show(nsPIDOMWindowOuter *aParent, nsIPrintSettings *aSettings, - nsIWebBrowserPrint *aWebBrowserPrint) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NS_PRECONDITION(aSettings, "aSettings must not be null"); - - RefPtr settingsX(do_QueryObject(aSettings)); - if (!settingsX) - return NS_ERROR_FAILURE; - - nsCOMPtr printSettingsSvc - = do_GetService("@mozilla.org/gfx/printsettings-service;1"); - - // Set the print job title - char16_t** docTitles; - uint32_t titleCount; - nsresult rv = aWebBrowserPrint->EnumerateDocumentNames(&titleCount, &docTitles); - if (NS_SUCCEEDED(rv) && titleCount > 0) { - CFStringRef cfTitleString = CFStringCreateWithCharacters(NULL, reinterpret_cast(docTitles[0]), - NS_strlen(docTitles[0])); - if (cfTitleString) { - ::PMPrintSettingsSetJobName(settingsX->GetPMPrintSettings(), cfTitleString); - CFRelease(cfTitleString); - } - for (int32_t i = titleCount - 1; i >= 0; i--) { - free(docTitles[i]); - } - free(docTitles); - docTitles = NULL; - titleCount = 0; - } - - // Read default print settings from prefs - printSettingsSvc->InitPrintSettingsFromPrefs(settingsX, true, - nsIPrintSettings::kInitSaveNativeData); - NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); - - // Put the print info into the current print operation, since that's where - // [panel runModal] will look for it. We create the view because otherwise - // we'll get unrelated warnings printed to the console. - NSView* tmpView = [[NSView alloc] init]; - NSPrintOperation* printOperation = [NSPrintOperation printOperationWithView:tmpView printInfo:printInfo]; - [NSPrintOperation setCurrentOperation:printOperation]; - - NSPrintPanel* panel = [NSPrintPanel printPanel]; - [panel setOptions:NSPrintPanelShowsCopies - | NSPrintPanelShowsPageRange - | NSPrintPanelShowsPaperSize - | NSPrintPanelShowsOrientation - | NSPrintPanelShowsScaling ]; - PrintPanelAccessoryController* viewController = - [[PrintPanelAccessoryController alloc] initWithSettings:aSettings]; - [panel addAccessoryController:viewController]; - [viewController release]; - - // Show the dialog. - nsCocoaUtils::PrepareForNativeAppModalDialog(); - int button = [panel runModal]; - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - - NSPrintInfo* copy = [[[NSPrintOperation currentOperation] printInfo] copy]; - if (!copy) { - return NS_ERROR_OUT_OF_MEMORY; - } - - [NSPrintOperation setCurrentOperation:nil]; - [tmpView release]; - - if (button != NSFileHandlingPanelOKButton) - return NS_ERROR_ABORT; - - settingsX->SetCocoaPrintInfo(copy); - settingsX->InitUnwriteableMargin(); - - // Save settings unless saving is pref'd off - if (Preferences::GetBool("print.save_print_settings", false)) { - printSettingsSvc->SavePrintSettingsToPrefs(settingsX, true, - nsIPrintSettings::kInitSaveNativeData); - } - - // Get coordinate space resolution for converting paper size units to inches - NSWindow *win = [[NSApplication sharedApplication] mainWindow]; - if (win) { - NSDictionary *devDesc = [win deviceDescription]; - if (devDesc) { - NSSize res = [[devDesc objectForKey: NSDeviceResolution] sizeValue]; - float scale = [win backingScaleFactor]; - if (scale > 0) { - settingsX->SetInchesScale(res.width / scale, res.height / scale); - } - } - } - - // Export settings. - [viewController exportSettings]; - - // If "ignore scaling" is checked, overwrite scaling factor with 1. - bool isShrinkToFitChecked; - settingsX->GetShrinkToFit(&isShrinkToFitChecked); - if (isShrinkToFitChecked) { - NSMutableDictionary* dict = [copy dictionary]; - if (dict) { - [dict setObject: [NSNumber numberWithFloat: 1] - forKey: NSPrintScalingFactor]; - } - // Set the scaling factor to 100% in the NSPrintInfo - // object so that it will not affect the paper size - // retrieved from the PMPageFormat routines. - [copy setScalingFactor:1.0]; - } else { - aSettings->SetScaling([copy scalingFactor]); - } - - // Set the adjusted paper size now that we've updated - // the scaling factor. - settingsX->InitAdjustedPaperSize(); - - [copy release]; - - int16_t pageRange; - aSettings->GetPrintRange(&pageRange); - if (pageRange != nsIPrintSettings::kRangeSelection) { - PMPrintSettings nativePrintSettings = settingsX->GetPMPrintSettings(); - UInt32 firstPage, lastPage; - OSStatus status = ::PMGetFirstPage(nativePrintSettings, &firstPage); - if (status == noErr) { - status = ::PMGetLastPage(nativePrintSettings, &lastPage); - if (status == noErr && lastPage != UINT32_MAX) { - aSettings->SetPrintRange(nsIPrintSettings::kRangeSpecifiedPageRange); - aSettings->SetStartPageRange(firstPage); - aSettings->SetEndPageRange(lastPage); - } - } - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsPrintDialogServiceX::ShowPageSetup(nsPIDOMWindowOuter *aParent, - nsIPrintSettings *aNSSettings) -{ - NS_PRECONDITION(aParent, "aParent must not be null"); - NS_PRECONDITION(aNSSettings, "aSettings must not be null"); - NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); - - RefPtr settingsX(do_QueryObject(aNSSettings)); - if (!settingsX) - return NS_ERROR_FAILURE; - - NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); - NSPageLayout *pageLayout = [NSPageLayout pageLayout]; - nsCocoaUtils::PrepareForNativeAppModalDialog(); - int button = [pageLayout runModalWithPrintInfo:printInfo]; - nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); - - return button == NSFileHandlingPanelOKButton ? NS_OK : NS_ERROR_ABORT; -} - -// Accessory view - -@interface PrintPanelAccessoryView (Private) - -- (NSString*)localizedString:(const char*)aKey; - -- (int16_t)chosenFrameSetting; - -- (const char*)headerFooterStringForList:(NSPopUpButton*)aList; - -- (void)exportHeaderFooterSettings; - -- (void)initBundle; - -- (NSTextField*)label:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment; - -- (void)addLabel:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment; - -- (void)addLabel:(const char*)aLabel withFrame:(NSRect)aRect; - -- (void)addCenteredLabel:(const char*)aLabel withFrame:(NSRect)aRect; - -- (NSButton*)checkboxWithLabel:(const char*)aLabel andFrame:(NSRect)aRect; - -- (NSPopUpButton*)headerFooterItemListWithFrame:(NSRect)aRect - selectedItem:(const char16_t*)aCurrentString; - -- (void)addOptionsSection; - -- (void)addAppearanceSection; - -- (void)addFramesSection; - -- (void)addHeaderFooterSection; - -- (NSString*)summaryValueForCheckbox:(NSButton*)aCheckbox; - -- (NSString*)framesSummaryValue; - -- (NSString*)headerSummaryValue; - -- (NSString*)footerSummaryValue; - -@end - -static const char sHeaderFooterTags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"}; - -@implementation PrintPanelAccessoryView - -// Public methods - -- (id)initWithSettings:(nsIPrintSettings*)aSettings -{ - [super initWithFrame:NSMakeRect(0, 0, 540, 270)]; - - mSettings = aSettings; - [self initBundle]; - [self addOptionsSection]; - [self addAppearanceSection]; - [self addFramesSection]; - [self addHeaderFooterSection]; - - return self; -} - -- (void)exportSettings -{ - mSettings->SetPrintRange([mPrintSelectionOnlyCheckbox state] == NSOnState ? - (int16_t)nsIPrintSettings::kRangeSelection : - (int16_t)nsIPrintSettings::kRangeAllPages); - mSettings->SetShrinkToFit([mShrinkToFitCheckbox state] == NSOnState); - mSettings->SetPrintBGColors([mPrintBGColorsCheckbox state] == NSOnState); - mSettings->SetPrintBGImages([mPrintBGImagesCheckbox state] == NSOnState); - mSettings->SetPrintFrameType([self chosenFrameSetting]); - - [self exportHeaderFooterSettings]; -} - -- (void)dealloc -{ - NS_IF_RELEASE(mPrintBundle); - [super dealloc]; -} - -// Localization - -- (void)initBundle -{ - nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); - bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", &mPrintBundle); -} - -- (NSString*)localizedString:(const char*)aKey -{ - if (!mPrintBundle) - return @""; - - nsXPIDLString intlString; - mPrintBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aKey).get(), getter_Copies(intlString)); - NSMutableString* s = [NSMutableString stringWithUTF8String:NS_ConvertUTF16toUTF8(intlString).get()]; - - // Remove all underscores (they're used in the GTK dialog for accesskeys). - [s replaceOccurrencesOfString:@"_" withString:@"" options:0 range:NSMakeRange(0, [s length])]; - return s; -} - -// Widget helpers - -- (NSTextField*)label:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment -{ - NSTextField* label = [[[NSTextField alloc] initWithFrame:aRect] autorelease]; - [label setStringValue:[self localizedString:aLabel]]; - [label setEditable:NO]; - [label setSelectable:NO]; - [label setBezeled:NO]; - [label setBordered:NO]; - [label setDrawsBackground:NO]; - [label setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; - [label setAlignment:aAlignment]; - return label; -} - -- (void)addLabel:(const char*)aLabel - withFrame:(NSRect)aRect - alignment:(NSTextAlignment)aAlignment -{ - NSTextField* label = [self label:aLabel withFrame:aRect alignment:aAlignment]; - [self addSubview:label]; -} - -- (void)addLabel:(const char*)aLabel withFrame:(NSRect)aRect -{ - [self addLabel:aLabel withFrame:aRect alignment:NSRightTextAlignment]; -} - -- (void)addCenteredLabel:(const char*)aLabel withFrame:(NSRect)aRect -{ - [self addLabel:aLabel withFrame:aRect alignment:NSCenterTextAlignment]; -} - -- (NSButton*)checkboxWithLabel:(const char*)aLabel andFrame:(NSRect)aRect -{ - aRect.origin.y += 4.0f; - NSButton* checkbox = [[[NSButton alloc] initWithFrame:aRect] autorelease]; - [checkbox setButtonType:NSSwitchButton]; - [checkbox setTitle:[self localizedString:aLabel]]; - [checkbox setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; - [checkbox sizeToFit]; - return checkbox; -} - -- (NSPopUpButton*)headerFooterItemListWithFrame:(NSRect)aRect - selectedItem:(const char16_t*)aCurrentString -{ - NSPopUpButton* list = [[[NSPopUpButton alloc] initWithFrame:aRect pullsDown:NO] autorelease]; - [list setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - [[list cell] setControlSize:NSSmallControlSize]; - NSArray* items = - [NSArray arrayWithObjects:[self localizedString:"headerFooterBlank"], - [self localizedString:"headerFooterTitle"], - [self localizedString:"headerFooterURL"], - [self localizedString:"headerFooterDate"], - [self localizedString:"headerFooterPage"], - [self localizedString:"headerFooterPageTotal"], - nil]; - [list addItemsWithTitles:items]; - - NS_ConvertUTF16toUTF8 currentStringUTF8(aCurrentString); - for (unsigned int i = 0; i < ArrayLength(sHeaderFooterTags); i++) { - if (!strcmp(currentStringUTF8.get(), sHeaderFooterTags[i])) { - [list selectItemAtIndex:i]; - break; - } - } - - return list; -} - -// Build sections - -- (void)addOptionsSection -{ - // Title - [self addLabel:"optionsTitleMac" withFrame:NSMakeRect(0, 240, 151, 22)]; - - // "Print Selection Only" - mPrintSelectionOnlyCheckbox = [self checkboxWithLabel:"selectionOnly" - andFrame:NSMakeRect(156, 240, 0, 0)]; - - bool canPrintSelection; - mSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, - &canPrintSelection); - [mPrintSelectionOnlyCheckbox setEnabled:canPrintSelection]; - - int16_t printRange; - mSettings->GetPrintRange(&printRange); - if (printRange == nsIPrintSettings::kRangeSelection) { - [mPrintSelectionOnlyCheckbox setState:NSOnState]; - } - - [self addSubview:mPrintSelectionOnlyCheckbox]; - - // "Shrink To Fit" - mShrinkToFitCheckbox = [self checkboxWithLabel:"shrinkToFit" - andFrame:NSMakeRect(156, 218, 0, 0)]; - - bool shrinkToFit; - mSettings->GetShrinkToFit(&shrinkToFit); - [mShrinkToFitCheckbox setState:(shrinkToFit ? NSOnState : NSOffState)]; - - [self addSubview:mShrinkToFitCheckbox]; -} - -- (void)addAppearanceSection -{ - // Title - [self addLabel:"appearanceTitleMac" withFrame:NSMakeRect(0, 188, 151, 22)]; - - // "Print Background Colors" - mPrintBGColorsCheckbox = [self checkboxWithLabel:"printBGColors" - andFrame:NSMakeRect(156, 188, 0, 0)]; - - bool geckoBool; - mSettings->GetPrintBGColors(&geckoBool); - [mPrintBGColorsCheckbox setState:(geckoBool ? NSOnState : NSOffState)]; - - [self addSubview:mPrintBGColorsCheckbox]; - - // "Print Background Images" - mPrintBGImagesCheckbox = [self checkboxWithLabel:"printBGImages" - andFrame:NSMakeRect(156, 166, 0, 0)]; - - mSettings->GetPrintBGImages(&geckoBool); - [mPrintBGImagesCheckbox setState:(geckoBool ? NSOnState : NSOffState)]; - - [self addSubview:mPrintBGImagesCheckbox]; -} - -- (void)addFramesSection -{ - // Title - [self addLabel:"framesTitleMac" withFrame:NSMakeRect(0, 124, 151, 22)]; - - // Radio matrix - NSButtonCell *radio = [[NSButtonCell alloc] init]; - [radio setButtonType:NSRadioButton]; - [radio setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]]; - NSMatrix *matrix = [[NSMatrix alloc] initWithFrame:NSMakeRect(156, 81, 400, 66) - mode:NSRadioModeMatrix - prototype:(NSCell*)radio - numberOfRows:3 - numberOfColumns:1]; - [radio release]; - [matrix setCellSize:NSMakeSize(400, 21)]; - [self addSubview:matrix]; - [matrix release]; - NSArray *cellArray = [matrix cells]; - mAsLaidOutRadio = [cellArray objectAtIndex:0]; - mSelectedFrameRadio = [cellArray objectAtIndex:1]; - mSeparateFramesRadio = [cellArray objectAtIndex:2]; - [mAsLaidOutRadio setTitle:[self localizedString:"asLaidOut"]]; - [mSelectedFrameRadio setTitle:[self localizedString:"selectedFrame"]]; - [mSeparateFramesRadio setTitle:[self localizedString:"separateFrames"]]; - - // Radio enabled state - int16_t frameUIFlag; - mSettings->GetHowToEnableFrameUI(&frameUIFlag); - if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) { - [mAsLaidOutRadio setEnabled:NO]; - [mSelectedFrameRadio setEnabled:NO]; - [mSeparateFramesRadio setEnabled:NO]; - } else if (frameUIFlag == nsIPrintSettings::kFrameEnableAsIsAndEach) { - [mSelectedFrameRadio setEnabled:NO]; - } - - // Radio values - int16_t printFrameType; - mSettings->GetPrintFrameType(&printFrameType); - switch (printFrameType) { - case nsIPrintSettings::kFramesAsIs: - [mAsLaidOutRadio setState:NSOnState]; - break; - case nsIPrintSettings::kSelectedFrame: - [mSelectedFrameRadio setState:NSOnState]; - break; - case nsIPrintSettings::kEachFrameSep: - [mSeparateFramesRadio setState:NSOnState]; - break; - } -} - -- (void)addHeaderFooterSection -{ - // Labels - [self addLabel:"pageHeadersTitleMac" withFrame:NSMakeRect(0, 44, 151, 22)]; - [self addLabel:"pageFootersTitleMac" withFrame:NSMakeRect(0, 0, 151, 22)]; - [self addCenteredLabel:"left" withFrame:NSMakeRect(156, 22, 100, 22)]; - [self addCenteredLabel:"center" withFrame:NSMakeRect(256, 22, 100, 22)]; - [self addCenteredLabel:"right" withFrame:NSMakeRect(356, 22, 100, 22)]; - - // Lists - nsXPIDLString sel; - - mSettings->GetHeaderStrLeft(getter_Copies(sel)); - mHeaderLeftList = [self headerFooterItemListWithFrame:NSMakeRect(156, 44, 100, 22) - selectedItem:sel]; - [self addSubview:mHeaderLeftList]; - - mSettings->GetHeaderStrCenter(getter_Copies(sel)); - mHeaderCenterList = [self headerFooterItemListWithFrame:NSMakeRect(256, 44, 100, 22) - selectedItem:sel]; - [self addSubview:mHeaderCenterList]; - - mSettings->GetHeaderStrRight(getter_Copies(sel)); - mHeaderRightList = [self headerFooterItemListWithFrame:NSMakeRect(356, 44, 100, 22) - selectedItem:sel]; - [self addSubview:mHeaderRightList]; - - mSettings->GetFooterStrLeft(getter_Copies(sel)); - mFooterLeftList = [self headerFooterItemListWithFrame:NSMakeRect(156, 0, 100, 22) - selectedItem:sel]; - [self addSubview:mFooterLeftList]; - - mSettings->GetFooterStrCenter(getter_Copies(sel)); - mFooterCenterList = [self headerFooterItemListWithFrame:NSMakeRect(256, 0, 100, 22) - selectedItem:sel]; - [self addSubview:mFooterCenterList]; - - mSettings->GetFooterStrRight(getter_Copies(sel)); - mFooterRightList = [self headerFooterItemListWithFrame:NSMakeRect(356, 0, 100, 22) - selectedItem:sel]; - [self addSubview:mFooterRightList]; -} - -// Export settings - -- (int16_t)chosenFrameSetting -{ - if ([mAsLaidOutRadio state] == NSOnState) - return nsIPrintSettings::kFramesAsIs; - if ([mSelectedFrameRadio state] == NSOnState) - return nsIPrintSettings::kSelectedFrame; - if ([mSeparateFramesRadio state] == NSOnState) - return nsIPrintSettings::kEachFrameSep; - return nsIPrintSettings::kNoFrames; -} - -- (const char*)headerFooterStringForList:(NSPopUpButton*)aList -{ - NSInteger index = [aList indexOfSelectedItem]; - NS_ASSERTION(index < NSInteger(ArrayLength(sHeaderFooterTags)), "Index of dropdown is higher than expected!"); - return sHeaderFooterTags[index]; -} - -- (void)exportHeaderFooterSettings -{ - const char* headerFooterStr; - headerFooterStr = [self headerFooterStringForList:mHeaderLeftList]; - mSettings->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mHeaderCenterList]; - mSettings->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mHeaderRightList]; - mSettings->SetHeaderStrRight(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mFooterLeftList]; - mSettings->SetFooterStrLeft(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mFooterCenterList]; - mSettings->SetFooterStrCenter(NS_ConvertUTF8toUTF16(headerFooterStr).get()); - - headerFooterStr = [self headerFooterStringForList:mFooterRightList]; - mSettings->SetFooterStrRight(NS_ConvertUTF8toUTF16(headerFooterStr).get()); -} - -// Summary - -- (NSString*)summaryValueForCheckbox:(NSButton*)aCheckbox -{ - if (![aCheckbox isEnabled]) - return [self localizedString:"summaryNAValue"]; - - return [aCheckbox state] == NSOnState ? - [self localizedString:"summaryOnValue"] : - [self localizedString:"summaryOffValue"]; -} - -- (NSString*)framesSummaryValue -{ - switch([self chosenFrameSetting]) { - case nsIPrintSettings::kFramesAsIs: - return [self localizedString:"asLaidOut"]; - case nsIPrintSettings::kSelectedFrame: - return [self localizedString:"selectedFrame"]; - case nsIPrintSettings::kEachFrameSep: - return [self localizedString:"separateFrames"]; - } - return [self localizedString:"summaryNAValue"]; -} - -- (NSString*)headerSummaryValue -{ - return [[mHeaderLeftList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [[mHeaderCenterList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [mHeaderRightList titleOfSelectedItem]]]]]; -} - -- (NSString*)footerSummaryValue -{ - return [[mFooterLeftList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [[mFooterCenterList titleOfSelectedItem] stringByAppendingString: - [@", " stringByAppendingString: - [mFooterRightList titleOfSelectedItem]]]]]; -} - -- (NSArray*)localizedSummaryItems -{ - return [NSArray arrayWithObjects: - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryFramesTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self framesSummaryValue], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summarySelectionOnlyTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mPrintSelectionOnlyCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryShrinkToFitTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mShrinkToFitCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryPrintBGColorsTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mPrintBGColorsCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryPrintBGImagesTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self summaryValueForCheckbox:mPrintBGImagesCheckbox], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryHeaderTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self headerSummaryValue], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - [NSDictionary dictionaryWithObjectsAndKeys: - [self localizedString:"summaryFooterTitle"], NSPrintPanelAccessorySummaryItemNameKey, - [self footerSummaryValue], NSPrintPanelAccessorySummaryItemDescriptionKey, nil], - nil]; -} - -@end - -// Accessory controller - -@implementation PrintPanelAccessoryController - -- (id)initWithSettings:(nsIPrintSettings*)aSettings -{ - [super initWithNibName:nil bundle:nil]; - - NSView* accView = [[PrintPanelAccessoryView alloc] initWithSettings:aSettings]; - [self setView:accView]; - [accView release]; - return self; -} - -- (void)exportSettings -{ - return [(PrintPanelAccessoryView*)[self view] exportSettings]; -} - -- (NSArray *)localizedSummaryItems -{ - return [(PrintPanelAccessoryView*)[self view] localizedSummaryItems]; -} - -@end diff --git a/widget/cocoa/nsPrintOptionsX.h b/widget/cocoa/nsPrintOptionsX.h deleted file mode 100644 index e34e75059e..0000000000 --- a/widget/cocoa/nsPrintOptionsX.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsPrintOptionsX_h_ -#define nsPrintOptionsX_h_ - -#include "nsPrintOptionsImpl.h" - -namespace mozilla -{ -namespace embedding -{ - class PrintData; -} // namespace embedding -} // namespace mozilla - -class nsPrintOptionsX : public nsPrintOptions -{ -public: - nsPrintOptionsX(); - virtual ~nsPrintOptionsX(); - - /* - * These serialize and deserialize methods are not symmetrical in that - * printSettingsX != deserialize(serialize(printSettingsX)). This is because - * the native print settings stored in the nsPrintSettingsX's NSPrintInfo - * object are not fully serialized. Only the values needed for successful - * printing are. - */ - NS_IMETHODIMP SerializeToPrintData(nsIPrintSettings* aSettings, - nsIWebBrowserPrint* aWBP, - mozilla::embedding::PrintData* data); - NS_IMETHODIMP DeserializeToPrintSettings(const mozilla::embedding::PrintData& data, - nsIPrintSettings* settings); - -protected: - nsresult _CreatePrintSettings(nsIPrintSettings **_retval); - nsresult ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags); - nsresult WritePrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags); -}; - -#endif // nsPrintOptionsX_h_ diff --git a/widget/cocoa/nsPrintOptionsX.mm b/widget/cocoa/nsPrintOptionsX.mm deleted file mode 100644 index d9aa17b42e..0000000000 --- a/widget/cocoa/nsPrintOptionsX.mm +++ /dev/null @@ -1,349 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsCOMPtr.h" -#include "nsQueryObject.h" -#include "nsIServiceManager.h" -#include "nsPrintOptionsX.h" -#include "nsPrintSettingsX.h" - -// The constants for paper orientation were renamed in 10.9. __MAC_10_9 is -// defined on OS X 10.9 and later. Although 10.8 and earlier are not supported -// at this time, this allows for building on those older OS versions. The -// values are consistent across OS versions so the rename does not affect -// runtime, just compilation. -#ifdef __MAC_10_9 -#define NS_PAPER_ORIENTATION_PORTRAIT (NSPaperOrientationPortrait) -#define NS_PAPER_ORIENTATION_LANDSCAPE (NSPaperOrientationLandscape) -#else -#define NS_PAPER_ORIENTATION_PORTRAIT (NSPortraitOrientation) -#define NS_PAPER_ORIENTATION_LANDSCAPE (NSLandscapeOrientation) -#endif - -using namespace mozilla::embedding; - -nsPrintOptionsX::nsPrintOptionsX() -{ -} - -nsPrintOptionsX::~nsPrintOptionsX() -{ -} - -NS_IMETHODIMP -nsPrintOptionsX::SerializeToPrintData(nsIPrintSettings* aSettings, - nsIWebBrowserPrint* aWBP, - PrintData* data) -{ - nsresult rv = nsPrintOptions::SerializeToPrintData(aSettings, aWBP, data); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (aWBP) { - // When serializing an nsIWebBrowserPrint, we need to pass up the first - // document name. We could pass up the entire collection of document - // names, but the OS X printing prompt code only really cares about - // the first one, so we just send the first to save IPC traffic. - char16_t** docTitles; - uint32_t titleCount; - rv = aWBP->EnumerateDocumentNames(&titleCount, &docTitles); - if (NS_SUCCEEDED(rv) && titleCount > 0) { - data->printJobName().Assign(docTitles[0]); - } - - for (int32_t i = titleCount - 1; i >= 0; i--) { - free(docTitles[i]); - } - free(docTitles); - docTitles = nullptr; - } - - RefPtr settingsX(do_QueryObject(aSettings)); - if (NS_WARN_IF(!settingsX)) { - return NS_ERROR_FAILURE; - } - - NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); - if (NS_WARN_IF(!printInfo)) { - return NS_ERROR_FAILURE; - } - - double adjustedWidth, adjustedHeight; - settingsX->GetAdjustedPaperSize(&adjustedWidth, &adjustedHeight); - data->adjustedPaperWidth() = adjustedWidth; - data->adjustedPaperHeight() = adjustedHeight; - - NSDictionary* dict = [printInfo dictionary]; - if (NS_WARN_IF(!dict)) { - return NS_ERROR_FAILURE; - } - - NSString* printerName = [dict objectForKey: NSPrintPrinterName]; - if (printerName) { - nsCocoaUtils::GetStringForNSString(printerName, data->printerName()); - } - - NSString* faxNumber = [dict objectForKey: NSPrintFaxNumber]; - if (faxNumber) { - nsCocoaUtils::GetStringForNSString(faxNumber, data->faxNumber()); - } - - NSURL* printToFileURL = [dict objectForKey: NSPrintJobSavingURL]; - if (printToFileURL) { - nsCocoaUtils::GetStringForNSString([printToFileURL absoluteString], - data->toFileName()); - } - - NSDate* printTime = [dict objectForKey: NSPrintTime]; - if (printTime) { - NSTimeInterval timestamp = [printTime timeIntervalSinceReferenceDate]; - data->printTime() = timestamp; - } - - NSString* disposition = [dict objectForKey: NSPrintJobDisposition]; - if (disposition) { - nsCocoaUtils::GetStringForNSString(disposition, data->disposition()); - } - - NSString* paperName = [dict objectForKey: NSPrintPaperName]; - if (paperName) { - nsCocoaUtils::GetStringForNSString(paperName, data->paperName()); - } - - float scalingFactor = [[dict objectForKey: NSPrintScalingFactor] floatValue]; - data->scalingFactor() = scalingFactor; - - int32_t orientation; - if ([printInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) { - orientation = nsIPrintSettings::kPortraitOrientation; - } else { - orientation = nsIPrintSettings::kLandscapeOrientation; - } - data->orientation() = orientation; - - NSSize paperSize = [printInfo paperSize]; - float widthScale, heightScale; - settingsX->GetInchesScale(&widthScale, &heightScale); - if (orientation == nsIPrintSettings::kLandscapeOrientation) { - // switch widths and heights - data->widthScale() = heightScale; - data->heightScale() = widthScale; - data->paperWidth() = paperSize.height / heightScale; - data->paperHeight() = paperSize.width / widthScale; - } else { - data->widthScale() = widthScale; - data->heightScale() = heightScale; - data->paperWidth() = paperSize.width / widthScale; - data->paperHeight() = paperSize.height / heightScale; - } - - data->numCopies() = [[dict objectForKey: NSPrintCopies] intValue]; - data->printAllPages() = [[dict objectForKey: NSPrintAllPages] boolValue]; - data->startPageRange() = [[dict objectForKey: NSPrintFirstPage] intValue]; - data->endPageRange() = [[dict objectForKey: NSPrintLastPage] intValue]; - data->mustCollate() = [[dict objectForKey: NSPrintMustCollate] boolValue]; - data->printReversed() = [[dict objectForKey: NSPrintReversePageOrder] boolValue]; - data->pagesAcross() = [[dict objectForKey: NSPrintPagesAcross] unsignedShortValue]; - data->pagesDown() = [[dict objectForKey: NSPrintPagesDown] unsignedShortValue]; - data->detailedErrorReporting() = [[dict objectForKey: NSPrintDetailedErrorReporting] boolValue]; - data->addHeaderAndFooter() = [[dict objectForKey: NSPrintHeaderAndFooter] boolValue]; - data->fileNameExtensionHidden() = - [[dict objectForKey: NSPrintJobSavingFileNameExtensionHidden] boolValue]; - - bool printSelectionOnly = [[dict objectForKey: NSPrintSelectionOnly] boolValue]; - aSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, - printSelectionOnly); - aSettings->GetPrintOptionsBits(&data->optionFlags()); - - return NS_OK; -} - -NS_IMETHODIMP -nsPrintOptionsX::DeserializeToPrintSettings(const PrintData& data, - nsIPrintSettings* settings) -{ - nsresult rv = nsPrintOptions::DeserializeToPrintSettings(data, settings); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - RefPtr settingsX(do_QueryObject(settings)); - if (NS_WARN_IF(!settingsX)) { - return NS_ERROR_FAILURE; - } - - NSPrintInfo* sharedPrintInfo = [NSPrintInfo sharedPrintInfo]; - if (NS_WARN_IF(!sharedPrintInfo)) { - return NS_ERROR_FAILURE; - } - - NSDictionary* sharedDict = [sharedPrintInfo dictionary]; - if (NS_WARN_IF(!sharedDict)) { - return NS_ERROR_FAILURE; - } - - // We need to create a new NSMutableDictionary to pass to NSPrintInfo with - // the values that we got from the other process. - NSMutableDictionary* newPrintInfoDict = - [NSMutableDictionary dictionaryWithDictionary:sharedDict]; - if (NS_WARN_IF(!newPrintInfoDict)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - NSString* printerName = nsCocoaUtils::ToNSString(data.printerName()); - if (printerName) { - NSPrinter* printer = [NSPrinter printerWithName: printerName]; - if (printer) { - [newPrintInfoDict setObject: printer forKey: NSPrintPrinter]; - [newPrintInfoDict setObject: printerName forKey: NSPrintPrinterName]; - } - } - - [newPrintInfoDict setObject: [NSNumber numberWithInt: data.numCopies()] - forKey: NSPrintCopies]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printAllPages()] - forKey: NSPrintAllPages]; - [newPrintInfoDict setObject: [NSNumber numberWithInt: data.startPageRange()] - forKey: NSPrintFirstPage]; - [newPrintInfoDict setObject: [NSNumber numberWithInt: data.endPageRange()] - forKey: NSPrintLastPage]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.mustCollate()] - forKey: NSPrintMustCollate]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printReversed()] - forKey: NSPrintReversePageOrder]; - - [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.disposition()) - forKey: NSPrintJobDisposition]; - - [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.paperName()) - forKey: NSPrintPaperName]; - - [newPrintInfoDict setObject: [NSNumber numberWithFloat: data.scalingFactor()] - forKey: NSPrintScalingFactor]; - - CGFloat width = data.paperWidth() * data.widthScale(); - CGFloat height = data.paperHeight() * data.heightScale(); - [newPrintInfoDict setObject: [NSValue valueWithSize:NSMakeSize(width,height)] - forKey: NSPrintPaperSize]; - - int paperOrientation; - if (data.orientation() == nsIPrintSettings::kPortraitOrientation) { - paperOrientation = NS_PAPER_ORIENTATION_PORTRAIT; - settings->SetOrientation(nsIPrintSettings::kPortraitOrientation); - } else { - paperOrientation = NS_PAPER_ORIENTATION_LANDSCAPE; - settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation); - } - [newPrintInfoDict setObject: [NSNumber numberWithInt:paperOrientation] - forKey: NSPrintOrientation]; - - [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesAcross()] - forKey: NSPrintPagesAcross]; - [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesDown()] - forKey: NSPrintPagesDown]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.detailedErrorReporting()] - forKey: NSPrintDetailedErrorReporting]; - [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.faxNumber()) - forKey: NSPrintFaxNumber]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.addHeaderAndFooter()] - forKey: NSPrintHeaderAndFooter]; - [newPrintInfoDict setObject: [NSNumber numberWithBool: data.fileNameExtensionHidden()] - forKey: NSPrintJobSavingFileNameExtensionHidden]; - - // At this point, the base class should have properly deserialized the print - // options bitfield for nsIPrintSettings, so that it holds the correct value - // for kEnableSelectionRB, which we use to set NSPrintSelectionOnly. - - bool printSelectionOnly = false; - rv = settings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &printSelectionOnly); - if (NS_SUCCEEDED(rv)) { - [newPrintInfoDict setObject: [NSNumber numberWithBool: printSelectionOnly] - forKey: NSPrintSelectionOnly]; - } else { - [newPrintInfoDict setObject: [NSNumber numberWithBool: NO] - forKey: NSPrintSelectionOnly]; - } - - NSURL* jobSavingURL = - [NSURL URLWithString: nsCocoaUtils::ToNSString(data.toFileName())]; - if (jobSavingURL) { - [newPrintInfoDict setObject: jobSavingURL forKey: NSPrintJobSavingURL]; - } - - NSTimeInterval timestamp = data.printTime(); - NSDate* printTime = [NSDate dateWithTimeIntervalSinceReferenceDate: timestamp]; - if (printTime) { - [newPrintInfoDict setObject: printTime forKey: NSPrintTime]; - } - - // Next, we create a new NSPrintInfo with the values in our dictionary. - NSPrintInfo* newPrintInfo = - [[NSPrintInfo alloc] initWithDictionary: newPrintInfoDict]; - if (NS_WARN_IF(!newPrintInfo)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - // And now swap in the new NSPrintInfo we've just populated. - settingsX->SetCocoaPrintInfo(newPrintInfo); - [newPrintInfo release]; - - settingsX->SetAdjustedPaperSize(data.adjustedPaperWidth(), - data.adjustedPaperHeight()); - - return NS_OK; -} - -nsresult -nsPrintOptionsX::ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags) -{ - nsresult rv; - - rv = nsPrintOptions::ReadPrefs(aPS, aPrinterName, aFlags); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintOptions::ReadPrefs() failed"); - - RefPtr printSettingsX(do_QueryObject(aPS)); - if (!printSettingsX) - return NS_ERROR_NO_INTERFACE; - rv = printSettingsX->ReadPageFormatFromPrefs(); - - return NS_OK; -} - -nsresult nsPrintOptionsX::_CreatePrintSettings(nsIPrintSettings **_retval) -{ - nsresult rv; - *_retval = nullptr; - - nsPrintSettingsX* printSettings = new nsPrintSettingsX; // does not initially ref count - NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*_retval = printSettings); - - rv = printSettings->Init(); - if (NS_FAILED(rv)) { - NS_RELEASE(*_retval); - return rv; - } - - InitPrintSettingsFromPrefs(*_retval, false, nsIPrintSettings::kInitSaveAll); - return rv; -} - -nsresult -nsPrintOptionsX::WritePrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags) -{ - nsresult rv; - - rv = nsPrintOptions::WritePrefs(aPS, aPrinterName, aFlags); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintOptions::WritePrefs() failed"); - - RefPtr printSettingsX(do_QueryObject(aPS)); - if (!printSettingsX) - return NS_ERROR_NO_INTERFACE; - rv = printSettingsX->WritePageFormatToPrefs(); - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintSettingsX::WritePageFormatToPrefs() failed"); - - return NS_OK; -} diff --git a/widget/cocoa/nsPrintSettingsX.h b/widget/cocoa/nsPrintSettingsX.h deleted file mode 100644 index 1d755b2505..0000000000 --- a/widget/cocoa/nsPrintSettingsX.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsPrintSettingsX_h_ -#define nsPrintSettingsX_h_ - -#include "nsPrintSettingsImpl.h" -#import - -#define NS_PRINTSETTINGSX_IID \ -{ 0x0DF2FDBD, 0x906D, 0x4726, \ - { 0x9E, 0x4D, 0xCF, 0xE0, 0x87, 0x8D, 0x70, 0x7C } } - -class nsPrintSettingsX : public nsPrintSettings -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_PRINTSETTINGSX_IID) - NS_DECL_ISUPPORTS_INHERITED - - nsPrintSettingsX(); - nsresult Init(); - NSPrintInfo* GetCocoaPrintInfo() { return mPrintInfo; } - void SetCocoaPrintInfo(NSPrintInfo* aPrintInfo); - virtual nsresult ReadPageFormatFromPrefs(); - virtual nsresult WritePageFormatToPrefs(); - virtual nsresult GetEffectivePageSize(double *aWidth, - double *aHeight) override; - - // In addition to setting the paper width and height, these - // overrides set the adjusted width and height returned from - // GetEffectivePageSize. This is needed when a paper size is - // set manually without using a print dialog a la reftest-print. - virtual nsresult SetPaperWidth(double aPaperWidth) override; - virtual nsresult SetPaperHeight(double aPaperWidth) override; - - PMPrintSettings GetPMPrintSettings(); - PMPrintSession GetPMPrintSession(); - PMPageFormat GetPMPageFormat(); - void SetPMPageFormat(PMPageFormat aPageFormat); - - // Re-initialize mUnwriteableMargin with values from mPageFormat. - // Should be called whenever mPageFormat is initialized or overwritten. - nsresult InitUnwriteableMargin(); - - // Re-initialize mAdjustedPaper{Width,Height} with values from mPageFormat. - // Should be called whenever mPageFormat is initialized or overwritten. - nsresult InitAdjustedPaperSize(); - - void SetInchesScale(float aWidthScale, float aHeightScale); - void GetInchesScale(float *aWidthScale, float *aHeightScale); - - void SetAdjustedPaperSize(double aWidth, double aHeight); - void GetAdjustedPaperSize(double *aWidth, double *aHeight); - -protected: - virtual ~nsPrintSettingsX(); - - nsPrintSettingsX(const nsPrintSettingsX& src); - nsPrintSettingsX& operator=(const nsPrintSettingsX& rhs); - - nsresult _Clone(nsIPrintSettings **_retval) override; - nsresult _Assign(nsIPrintSettings *aPS) override; - - // The out param has a ref count of 1 on return so caller needs to PMRelase() when done. - OSStatus CreateDefaultPageFormat(PMPrintSession aSession, PMPageFormat& outFormat); - OSStatus CreateDefaultPrintSettings(PMPrintSession aSession, PMPrintSettings& outSettings); - - NSPrintInfo* mPrintInfo; - - // Scaling factors used to convert the NSPrintInfo - // paper size units to inches - float mWidthScale; - float mHeightScale; - double mAdjustedPaperWidth; - double mAdjustedPaperHeight; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsPrintSettingsX, NS_PRINTSETTINGSX_IID) - -#endif // nsPrintSettingsX_h_ diff --git a/widget/cocoa/nsPrintSettingsX.mm b/widget/cocoa/nsPrintSettingsX.mm deleted file mode 100644 index 73a8e78d2b..0000000000 --- a/widget/cocoa/nsPrintSettingsX.mm +++ /dev/null @@ -1,272 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsPrintSettingsX.h" -#include "nsObjCExceptions.h" - -#include "plbase64.h" -#include "plstr.h" - -#include "nsCocoaUtils.h" - -#include "mozilla/Preferences.h" - -using namespace mozilla; - -#define MAC_OS_X_PAGE_SETUP_PREFNAME "print.macosx.pagesetup-2" -#define COCOA_PAPER_UNITS_PER_INCH 72.0 - -NS_IMPL_ISUPPORTS_INHERITED(nsPrintSettingsX, nsPrintSettings, nsPrintSettingsX) - -nsPrintSettingsX::nsPrintSettingsX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mPrintInfo = [[NSPrintInfo sharedPrintInfo] copy]; - mWidthScale = COCOA_PAPER_UNITS_PER_INCH; - mHeightScale = COCOA_PAPER_UNITS_PER_INCH; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsPrintSettingsX::nsPrintSettingsX(const nsPrintSettingsX& src) -{ - *this = src; -} - -nsPrintSettingsX::~nsPrintSettingsX() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mPrintInfo release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsPrintSettingsX& nsPrintSettingsX::operator=(const nsPrintSettingsX& rhs) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (this == &rhs) { - return *this; - } - - nsPrintSettings::operator=(rhs); - - [mPrintInfo release]; - mPrintInfo = [rhs.mPrintInfo copy]; - - return *this; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(*this); -} - -nsresult nsPrintSettingsX::Init() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - InitUnwriteableMargin(); - InitAdjustedPaperSize(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -// Should be called whenever the page format changes. -NS_IMETHODIMP nsPrintSettingsX::InitUnwriteableMargin() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMPaper paper; - PMPaperMargins paperMargin; - PMPageFormat pageFormat = GetPMPageFormat(); - ::PMGetPageFormatPaper(pageFormat, &paper); - ::PMPaperGetMargins(paper, &paperMargin); - mUnwriteableMargin.top = NS_POINTS_TO_INT_TWIPS(paperMargin.top); - mUnwriteableMargin.left = NS_POINTS_TO_INT_TWIPS(paperMargin.left); - mUnwriteableMargin.bottom = NS_POINTS_TO_INT_TWIPS(paperMargin.bottom); - mUnwriteableMargin.right = NS_POINTS_TO_INT_TWIPS(paperMargin.right); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsPrintSettingsX::InitAdjustedPaperSize() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMPageFormat pageFormat = GetPMPageFormat(); - - PMRect paperRect; - ::PMGetAdjustedPaperRect(pageFormat, &paperRect); - - mAdjustedPaperWidth = paperRect.right - paperRect.left; - mAdjustedPaperHeight = paperRect.bottom - paperRect.top; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsPrintSettingsX::SetCocoaPrintInfo(NSPrintInfo* aPrintInfo) -{ - if (mPrintInfo != aPrintInfo) { - [mPrintInfo release]; - mPrintInfo = [aPrintInfo retain]; - } -} - -NS_IMETHODIMP nsPrintSettingsX::ReadPageFormatFromPrefs() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - nsAutoCString encodedData; - nsresult rv = - Preferences::GetCString(MAC_OS_X_PAGE_SETUP_PREFNAME, &encodedData); - if (NS_FAILED(rv)) { - return rv; - } - - // decode the base64 - char* decodedData = PL_Base64Decode(encodedData.get(), encodedData.Length(), nullptr); - NSData* data = [NSData dataWithBytes:decodedData length:strlen(decodedData)]; - if (!data) - return NS_ERROR_FAILURE; - - PMPageFormat newPageFormat; - OSStatus status = ::PMPageFormatCreateWithDataRepresentation((CFDataRef)data, &newPageFormat); - if (status == noErr) { - SetPMPageFormat(newPageFormat); - } - InitUnwriteableMargin(); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsPrintSettingsX::WritePageFormatToPrefs() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - PMPageFormat pageFormat = GetPMPageFormat(); - if (pageFormat == kPMNoPageFormat) - return NS_ERROR_NOT_INITIALIZED; - - NSData* data = nil; - OSStatus err = ::PMPageFormatCreateDataRepresentation(pageFormat, (CFDataRef*)&data, kPMDataFormatXMLDefault); - if (err != noErr) - return NS_ERROR_FAILURE; - - nsAutoCString encodedData; - encodedData.Adopt(PL_Base64Encode((char*)[data bytes], [data length], nullptr)); - if (!encodedData.get()) - return NS_ERROR_OUT_OF_MEMORY; - - return Preferences::SetCString(MAC_OS_X_PAGE_SETUP_PREFNAME, encodedData); - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsresult nsPrintSettingsX::_Clone(nsIPrintSettings **_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - *_retval = nullptr; - - nsPrintSettingsX *newSettings = new nsPrintSettingsX(*this); - if (!newSettings) - return NS_ERROR_FAILURE; - *_retval = newSettings; - NS_ADDREF(*_retval); - return NS_OK; -} - -NS_IMETHODIMP nsPrintSettingsX::_Assign(nsIPrintSettings *aPS) -{ - nsPrintSettingsX *printSettingsX = static_cast(aPS); - if (!printSettingsX) - return NS_ERROR_UNEXPECTED; - *this = *printSettingsX; - return NS_OK; -} - -PMPrintSettings -nsPrintSettingsX::GetPMPrintSettings() -{ - return static_cast([mPrintInfo PMPrintSettings]); -} - -PMPrintSession -nsPrintSettingsX::GetPMPrintSession() -{ - return static_cast([mPrintInfo PMPrintSession]); -} - -PMPageFormat -nsPrintSettingsX::GetPMPageFormat() -{ - return static_cast([mPrintInfo PMPageFormat]); -} - -void -nsPrintSettingsX::SetPMPageFormat(PMPageFormat aPageFormat) -{ - PMPageFormat oldPageFormat = GetPMPageFormat(); - ::PMCopyPageFormat(aPageFormat, oldPageFormat); - [mPrintInfo updateFromPMPageFormat]; -} - -void -nsPrintSettingsX::SetInchesScale(float aWidthScale, float aHeightScale) -{ - if (aWidthScale > 0 && aHeightScale > 0) { - mWidthScale = aWidthScale; - mHeightScale = aHeightScale; - } -} - -void -nsPrintSettingsX::GetInchesScale(float *aWidthScale, float *aHeightScale) -{ - *aWidthScale = mWidthScale; - *aHeightScale = mHeightScale; -} - -NS_IMETHODIMP nsPrintSettingsX::SetPaperWidth(double aPaperWidth) -{ - mPaperWidth = aPaperWidth; - mAdjustedPaperWidth = aPaperWidth * mWidthScale; - return NS_OK; -} - -NS_IMETHODIMP nsPrintSettingsX::SetPaperHeight(double aPaperHeight) -{ - mPaperHeight = aPaperHeight; - mAdjustedPaperHeight = aPaperHeight * mHeightScale; - return NS_OK; -} - -NS_IMETHODIMP -nsPrintSettingsX::GetEffectivePageSize(double *aWidth, double *aHeight) -{ - *aWidth = NS_INCHES_TO_TWIPS(mAdjustedPaperWidth / mWidthScale); - *aHeight = NS_INCHES_TO_TWIPS(mAdjustedPaperHeight / mHeightScale); - return NS_OK; -} - -void nsPrintSettingsX::SetAdjustedPaperSize(double aWidth, double aHeight) -{ - mAdjustedPaperWidth = aWidth; - mAdjustedPaperHeight = aHeight; -} - -void nsPrintSettingsX::GetAdjustedPaperSize(double *aWidth, double *aHeight) -{ - *aWidth = mAdjustedPaperWidth; - *aHeight = mAdjustedPaperHeight; -} diff --git a/widget/cocoa/nsSandboxViolationSink.h b/widget/cocoa/nsSandboxViolationSink.h deleted file mode 100644 index 35b5d89af5..0000000000 --- a/widget/cocoa/nsSandboxViolationSink.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsSandboxViolationSink_h_ -#define nsSandboxViolationSink_h_ - -#include - -// Class for tracking sandbox violations. Currently it just logs them to -// stdout and the system console. In the future it may do more. - -// What makes this possible is the fact that Apple' sandboxd calls -// notify_post("com.apple.sandbox.violation.*") whenever it's notified by the -// Sandbox kernel extension of a sandbox violation. We register to receive -// these notifications. But the notifications are empty, and are sent for -// every violation in every process. So we need to do more to get only "our" -// violations, and to find out what kind of violation they were. See the -// implementation of nsSandboxViolationSink::ViolationHandler(). - -#define SANDBOX_VIOLATION_QUEUE_NAME "org.mozilla.sandbox.violation.queue" -#define SANDBOX_VIOLATION_NOTIFICATION_NAME "com.apple.sandbox.violation.*" - -class nsSandboxViolationSink -{ -public: - static void Start(); - static void Stop(); -private: - static void ViolationHandler(); - static int mNotifyToken; - static uint64_t mLastMsgReceived; -}; - -#endif // nsSandboxViolationSink_h_ diff --git a/widget/cocoa/nsSandboxViolationSink.mm b/widget/cocoa/nsSandboxViolationSink.mm deleted file mode 100644 index 0572173344..0000000000 --- a/widget/cocoa/nsSandboxViolationSink.mm +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsSandboxViolationSink.h" - -#include -#include -#include -#include -#include -#include "nsCocoaDebugUtils.h" -#include "mozilla/Preferences.h" -#include "mozilla/Sprintf.h" - -int nsSandboxViolationSink::mNotifyToken = 0; -uint64_t nsSandboxViolationSink::mLastMsgReceived = 0; - -void -nsSandboxViolationSink::Start() -{ - if (mNotifyToken) { - return; - } - notify_register_dispatch(SANDBOX_VIOLATION_NOTIFICATION_NAME, - &mNotifyToken, - dispatch_queue_create(SANDBOX_VIOLATION_QUEUE_NAME, - DISPATCH_QUEUE_SERIAL), - ^(int token) { ViolationHandler(); }); -} - -void -nsSandboxViolationSink::Stop() -{ - if (!mNotifyToken) { - return; - } - notify_cancel(mNotifyToken); - mNotifyToken = 0; -} - -// We need to query syslogd to find out what violations occurred, and whether -// they were "ours". We can use the Apple System Log facility to do this. -// Besides calling notify_post("com.apple.sandbox.violation.*"), Apple's -// sandboxd also reports all sandbox violations (sent to it by the Sandbox -// kernel extension) to syslogd, which stores them and makes them viewable -// in the system console. This is the database we query. - -// ViolationHandler() is always called on its own secondary thread. This -// makes it unlikely it will interfere with other browser activity. - -void -nsSandboxViolationSink::ViolationHandler() -{ - aslmsg query = asl_new(ASL_TYPE_QUERY); - - asl_set_query(query, ASL_KEY_FACILITY, "com.apple.sandbox", - ASL_QUERY_OP_EQUAL); - - // Only get reports that were generated very recently. - char query_time[30] = {0}; - SprintfLiteral(query_time, "%li", time(NULL) - 2); - asl_set_query(query, ASL_KEY_TIME, query_time, - ASL_QUERY_OP_NUMERIC | ASL_QUERY_OP_GREATER_EQUAL); - - // This code is easier to test if we don't just track "our" violations, - // which are (normally) few and far between. For example (for the time - // being at least) four appleeventsd sandbox violations happen every time - // we start the browser in e10s mode. But it makes sense to default to - // only tracking "our" violations. - if (mozilla::Preferences::GetBool( - "security.sandbox.mac.track.violations.oursonly", true)) { - // This makes each of our processes log its own violations. It might - // be better to make the chrome process log all the other processes' - // violations. - char query_pid[20] = {0}; - SprintfLiteral(query_pid, "%u", getpid()); - asl_set_query(query, ASL_KEY_REF_PID, query_pid, ASL_QUERY_OP_EQUAL); - } - - aslresponse response = asl_search(nullptr, query); - - // Each time ViolationHandler() is called we grab as many messages as are - // available. Otherwise we might not get them all. - if (response) { - while (true) { - aslmsg hit = nullptr; - aslmsg found = nullptr; - const char* id_str; - - while ((hit = aslresponse_next(response))) { - // Record the message id to avoid logging the same violation more - // than once. - id_str = asl_get(hit, ASL_KEY_MSG_ID); - uint64_t id_val = atoll(id_str); - if (id_val <= mLastMsgReceived) { - continue; - } - mLastMsgReceived = id_val; - found = hit; - break; - } - if (!found) { - break; - } - - const char* pid_str = asl_get(found, ASL_KEY_REF_PID); - const char* message_str = asl_get(found, ASL_KEY_MSG); - nsCocoaDebugUtils::DebugLog("nsSandboxViolationSink::ViolationHandler(): id %s, pid %s, message %s", - id_str, pid_str, message_str); - } - aslresponse_free(response); - } -} diff --git a/widget/cocoa/nsScreenCocoa.h b/widget/cocoa/nsScreenCocoa.h deleted file mode 100644 index 268d5beb0a..0000000000 --- a/widget/cocoa/nsScreenCocoa.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 nsScreenCocoa_h_ -#define nsScreenCocoa_h_ - -#import - -#include "nsBaseScreen.h" - -class nsScreenCocoa : public nsBaseScreen -{ -public: - explicit nsScreenCocoa (NSScreen *screen); - ~nsScreenCocoa (); - - NS_IMETHOD GetId(uint32_t* outId); - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor); - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) - { - return GetContentsScaleFactor(aScaleFactor); - } - - NSScreen *CocoaScreen() { return mScreen; } - -private: - CGFloat BackingScaleFactor(); - - NSScreen *mScreen; - uint32_t mId; -}; - -#endif // nsScreenCocoa_h_ diff --git a/widget/cocoa/nsScreenCocoa.mm b/widget/cocoa/nsScreenCocoa.mm deleted file mode 100644 index 08905bf0ad..0000000000 --- a/widget/cocoa/nsScreenCocoa.mm +++ /dev/null @@ -1,147 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 "nsScreenCocoa.h" -#include "nsObjCExceptions.h" -#include "nsCocoaUtils.h" - -static uint32_t sScreenId = 0; - -nsScreenCocoa::nsScreenCocoa (NSScreen *screen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mScreen = [screen retain]; - mId = ++sScreenId; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsScreenCocoa::~nsScreenCocoa () -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mScreen release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetId(uint32_t *outId) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *outId = mId; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen frame]; - - mozilla::LayoutDeviceIntRect r = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetAvailRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen visibleFrame]; - - mozilla::LayoutDeviceIntRect r = - nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor()); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen frame]; - - mozilla::DesktopIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetAvailRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - NSRect frame = [mScreen visibleFrame]; - - mozilla::DesktopIntRect r = nsCocoaUtils::CocoaRectToGeckoRect(frame); - - *outX = r.x; - *outY = r.y; - *outWidth = r.width; - *outHeight = r.height; - - return NS_OK; -} - -NS_IMETHODIMP -nsScreenCocoa::GetPixelDepth(int32_t *aPixelDepth) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindowDepth depth = [mScreen depth]; - int bpp = NSBitsPerPixelFromDepth(depth); - - *aPixelDepth = bpp; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenCocoa::GetColorDepth(int32_t *aColorDepth) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindowDepth depth = [mScreen depth]; - int bpp = NSBitsPerPixelFromDepth (depth); - - *aColorDepth = bpp; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenCocoa::GetContentsScaleFactor(double *aContentsScaleFactor) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - *aContentsScaleFactor = (double) BackingScaleFactor(); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -CGFloat -nsScreenCocoa::BackingScaleFactor() -{ - return nsCocoaUtils::GetBackingScaleFactor(mScreen); -} diff --git a/widget/cocoa/nsScreenManagerCocoa.h b/widget/cocoa/nsScreenManagerCocoa.h deleted file mode 100644 index 61a059d977..0000000000 --- a/widget/cocoa/nsScreenManagerCocoa.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 nsScreenManagerCocoa_h_ -#define nsScreenManagerCocoa_h_ - -#import - -#include "mozilla/RefPtr.h" -#include "nsTArray.h" -#include "nsIScreenManager.h" -#include "nsScreenCocoa.h" - -class nsScreenManagerCocoa : public nsIScreenManager -{ -public: - nsScreenManagerCocoa(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISCREENMANAGER - -protected: - virtual ~nsScreenManagerCocoa(); - -private: - - nsScreenCocoa *ScreenForCocoaScreen(NSScreen *screen); - nsTArray< RefPtr > mScreenList; -}; - -#endif // nsScreenManagerCocoa_h_ diff --git a/widget/cocoa/nsScreenManagerCocoa.mm b/widget/cocoa/nsScreenManagerCocoa.mm deleted file mode 100644 index 9a0cbb9cc5..0000000000 --- a/widget/cocoa/nsScreenManagerCocoa.mm +++ /dev/null @@ -1,152 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 "nsScreenManagerCocoa.h" -#include "nsObjCExceptions.h" -#include "nsCOMPtr.h" -#include "nsCocoaUtils.h" - -using namespace mozilla; - -NS_IMPL_ISUPPORTS(nsScreenManagerCocoa, nsIScreenManager) - -nsScreenManagerCocoa::nsScreenManagerCocoa() -{ -} - -nsScreenManagerCocoa::~nsScreenManagerCocoa() -{ -} - -nsScreenCocoa* -nsScreenManagerCocoa::ScreenForCocoaScreen(NSScreen *screen) -{ - for (uint32_t i = 0; i < mScreenList.Length(); ++i) { - nsScreenCocoa* sc = mScreenList[i]; - if (sc->CocoaScreen() == screen) { - // doesn't addref - return sc; - } - } - - // didn't find it; create and insert - RefPtr sc = new nsScreenCocoa(screen); - mScreenList.AppendElement(sc); - return sc.get(); -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForId (uint32_t aId, nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT - - *outScreen = nullptr; - - for (uint32_t i = 0; i < mScreenList.Length(); ++i) { - nsScreenCocoa* sc = mScreenList[i]; - uint32_t id; - nsresult rv = sc->GetId(&id); - - if (NS_SUCCEEDED(rv) && id == aId) { - *outScreen = sc; - NS_ADDREF(*outScreen); - return NS_OK; - } - } - - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForRect (int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator]; - NSRect inRect = - nsCocoaUtils::GeckoRectToCocoaRect(DesktopIntRect(aX, aY, - aWidth, aHeight)); - NSScreen *screenWindowIsOn = [NSScreen mainScreen]; - float greatestArea = 0; - - while (NSScreen *screen = [screenEnum nextObject]) { - NSDictionary *desc = [screen deviceDescription]; - if ([desc objectForKey:NSDeviceIsScreen] == nil) - continue; - - NSRect r = NSIntersectionRect([screen frame], inRect); - float area = r.size.width * r.size.height; - if (area > greatestArea) { - greatestArea = area; - screenWindowIsOn = screen; - } - } - - *outScreen = ScreenForCocoaScreen(screenWindowIsOn); - NS_ADDREF(*outScreen); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetPrimaryScreen (nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - // the mainScreen is the screen with the "key window" (focus, I assume?) - NSScreen *sc = [[NSScreen screens] objectAtIndex:0]; - - *outScreen = ScreenForCocoaScreen(sc); - NS_ADDREF(*outScreen); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetNumberOfScreens (uint32_t *aNumberOfScreens) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSArray *ss = [NSScreen screens]; - - *aNumberOfScreens = [ss count]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::GetSystemDefaultScale(float *aDefaultScale) -{ - *aDefaultScale = 1.0f; - return NS_OK; -} - -NS_IMETHODIMP -nsScreenManagerCocoa::ScreenForNativeWidget (void *nativeWidget, nsIScreen **outScreen) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSWindow *window = static_cast(nativeWidget); - if (window) { - nsIScreen *screen = ScreenForCocoaScreen([window screen]); - *outScreen = screen; - NS_ADDREF(*outScreen); - return NS_OK; - } - - *outScreen = nullptr; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsSound.h b/widget/cocoa/nsSound.h deleted file mode 100644 index 0e0293ae28..0000000000 --- a/widget/cocoa/nsSound.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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 nsSound_h_ -#define nsSound_h_ - -#include "nsISound.h" -#include "nsIStreamLoader.h" - -class nsSound : public nsISound, - public nsIStreamLoaderObserver -{ -public: - nsSound(); - - NS_DECL_ISUPPORTS - NS_DECL_NSISOUND - NS_DECL_NSISTREAMLOADEROBSERVER - -protected: - virtual ~nsSound(); -}; - -#endif // nsSound_h_ diff --git a/widget/cocoa/nsSound.mm b/widget/cocoa/nsSound.mm deleted file mode 100644 index 04c6b4d764..0000000000 --- a/widget/cocoa/nsSound.mm +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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 "nsSound.h" -#include "nsContentUtils.h" -#include "nsObjCExceptions.h" -#include "nsNetUtil.h" -#include "nsCOMPtr.h" -#include "nsIURL.h" -#include "nsString.h" - -#import - -NS_IMPL_ISUPPORTS(nsSound, nsISound, nsIStreamLoaderObserver) - -nsSound::nsSound() -{ -} - -nsSound::~nsSound() -{ -} - -NS_IMETHODIMP -nsSound::Beep() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSBeep(); - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSound::OnStreamComplete(nsIStreamLoader *aLoader, - nsISupports *context, - nsresult aStatus, - uint32_t dataLen, - const uint8_t *data) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NSData *value = [NSData dataWithBytes:data length:dataLen]; - - NSSound *sound = [[NSSound alloc] initWithData:value]; - - [sound play]; - - [sound autorelease]; - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSound::Play(nsIURL *aURL) -{ - nsCOMPtr uri(do_QueryInterface(aURL)); - nsCOMPtr loader; - return NS_NewStreamLoader(getter_AddRefs(loader), - uri, - this, // aObserver - nsContentUtils::GetSystemPrincipal(), - nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, - nsIContentPolicy::TYPE_OTHER); -} - -NS_IMETHODIMP -nsSound::Init() -{ - return NS_OK; -} - -NS_IMETHODIMP -nsSound::PlaySystemSound(const nsAString &aSoundAlias) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (NS_IsMozAliasSound(aSoundAlias)) { - NS_WARNING("nsISound::playSystemSound is called with \"_moz_\" events, they are obsolete, use nsISound::playEventSound instead"); - // Mac doesn't have system sound settings for each user actions. - return NS_OK; - } - - NSString *name = [NSString stringWithCharacters:reinterpret_cast(aSoundAlias.BeginReading()) - length:aSoundAlias.Length()]; - NSSound *sound = [NSSound soundNamed:name]; - if (sound) { - [sound stop]; - [sound play]; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSound::PlayEventSound(uint32_t aEventId) -{ - // Mac doesn't have system sound settings for each user actions. - return NS_OK; -} diff --git a/widget/cocoa/nsStandaloneNativeMenu.h b/widget/cocoa/nsStandaloneNativeMenu.h deleted file mode 100644 index e03742b1e0..0000000000 --- a/widget/cocoa/nsStandaloneNativeMenu.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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 nsStandaloneNativeMenu_h_ -#define nsStandaloneNativeMenu_h_ - -#include "nsMenuGroupOwnerX.h" -#include "nsMenuX.h" -#include "nsIStandaloneNativeMenu.h" - -class nsStandaloneNativeMenu : public nsMenuGroupOwnerX, public nsIStandaloneNativeMenu -{ -public: - nsStandaloneNativeMenu(); - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSISTANDALONENATIVEMENU - - // nsMenuObjectX - nsMenuObjectTypeX MenuObjectType() override { return eStandaloneNativeMenuObjectType; } - void * NativeData() override { return mMenu != nullptr ? mMenu->NativeData() : nullptr; } - virtual void IconUpdated() override; - - nsMenuX * GetMenuXObject() { return mMenu; } - - // If this menu is the menu of a system status bar item (NSStatusItem), - // let the menu know about the status item so that it can propagate - // any icon changes to the status item. - void SetContainerStatusBarItem(NSStatusItem* aItem); - -protected: - virtual ~nsStandaloneNativeMenu(); - - nsMenuX * mMenu; - NSStatusItem* mContainerStatusBarItem; -}; - -#endif diff --git a/widget/cocoa/nsStandaloneNativeMenu.mm b/widget/cocoa/nsStandaloneNativeMenu.mm deleted file mode 100644 index 98a5fd8f6f..0000000000 --- a/widget/cocoa/nsStandaloneNativeMenu.mm +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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/. */ - -#import - -#include "nsStandaloneNativeMenu.h" -#include "nsMenuUtilsX.h" -#include "nsIDOMElement.h" -#include "nsIMutationObserver.h" -#include "nsGkAtoms.h" -#include "nsObjCExceptions.h" - - -NS_IMPL_ISUPPORTS_INHERITED(nsStandaloneNativeMenu, nsMenuGroupOwnerX, - nsIMutationObserver, nsIStandaloneNativeMenu) - -nsStandaloneNativeMenu::nsStandaloneNativeMenu() -: mMenu(nullptr) -, mContainerStatusBarItem(nil) -{ -} - -nsStandaloneNativeMenu::~nsStandaloneNativeMenu() -{ - if (mMenu) delete mMenu; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::Init(nsIDOMElement * aDOMElement) -{ - NS_ASSERTION(mMenu == nullptr, "nsNativeMenu::Init - mMenu not null!"); - - nsresult rv; - - nsCOMPtr content = do_QueryInterface(aDOMElement, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - if (!content->IsAnyOfXULElements(nsGkAtoms::menu, nsGkAtoms::menupopup)) - return NS_ERROR_FAILURE; - - rv = nsMenuGroupOwnerX::Create(content); - if (NS_FAILED(rv)) - return rv; - - mMenu = new nsMenuX(); - rv = mMenu->Create(this, this, content); - if (NS_FAILED(rv)) { - delete mMenu; - mMenu = nullptr; - return rv; - } - - mMenu->SetupIcon(); - - return NS_OK; -} - -static void -UpdateMenu(nsMenuX * aMenu) -{ - aMenu->MenuOpened(); - aMenu->MenuClosed(); - - uint32_t itemCount = aMenu->GetItemCount(); - for (uint32_t i = 0; i < itemCount; i++) { - nsMenuObjectX * menuObject = aMenu->GetItemAt(i); - if (menuObject->MenuObjectType() == eSubmenuObjectType) { - UpdateMenu(static_cast(menuObject)); - } - } -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::MenuWillOpen(bool * aResult) -{ - NS_ASSERTION(mMenu != nullptr, "nsStandaloneNativeMenu::OnOpen - mMenu is null!"); - - // Force an update on the mMenu by faking an open/close on all of - // its submenus. - UpdateMenu(mMenu); - - *aResult = true; - return NS_OK; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::GetNativeMenu(void ** aVoidPointer) -{ - if (mMenu) { - *aVoidPointer = mMenu->NativeData(); - [[(NSObject *)(*aVoidPointer) retain] autorelease]; - return NS_OK; - } else { - *aVoidPointer = nullptr; - return NS_ERROR_NOT_INITIALIZED; - } -} - -static NSMenuItem * -NativeMenuItemWithLocation(NSMenu * currentSubmenu, NSString * locationString) -{ - NSArray * indexes = [locationString componentsSeparatedByString:@"|"]; - NSUInteger indexCount = [indexes count]; - if (indexCount == 0) - return nil; - - for (NSUInteger i = 0; i < indexCount; i++) { - NSInteger targetIndex = [[indexes objectAtIndex:i] integerValue]; - NSInteger itemCount = [currentSubmenu numberOfItems]; - if (targetIndex < itemCount) { - NSMenuItem* menuItem = [currentSubmenu itemAtIndex:targetIndex]; - - // If this is the last index, just return the menu item. - if (i == (indexCount - 1)) - return menuItem; - - // If this is not the last index, find the submenu and keep going. - if ([menuItem hasSubmenu]) - currentSubmenu = [menuItem submenu]; - else - return nil; - } - } - - return nil; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::ActivateNativeMenuItemAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - if (!mMenu) - return NS_ERROR_NOT_INITIALIZED; - - NSString * locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSMenu * menu = static_cast (mMenu->NativeData()); - NSMenuItem * item = NativeMenuItemWithLocation(menu, locationString); - - // We can't perform an action on an item with a submenu, that will raise - // an obj-c exception. - if (item && ![item hasSubmenu]) { - NSMenu * parent = [item menu]; - if (parent) { - // NSLog(@"Performing action for native menu item titled: %@\n", - // [[currentSubmenu itemAtIndex:targetIndex] title]); - [parent performActionForItemAtIndex:[parent indexOfItem:item]]; - return NS_OK; - } - } - - return NS_ERROR_FAILURE; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsStandaloneNativeMenu::ForceUpdateNativeMenuAt(const nsAString& indexString) -{ - if (!mMenu) - return NS_ERROR_NOT_INITIALIZED; - - NSString* locationString = [NSString stringWithCharacters:reinterpret_cast(indexString.BeginReading()) - length:indexString.Length()]; - NSArray* indexes = [locationString componentsSeparatedByString:@"|"]; - unsigned int indexCount = [indexes count]; - if (indexCount == 0) - return NS_OK; - - nsMenuX* currentMenu = mMenu; - - // now find the correct submenu - for (unsigned int i = 1; currentMenu && i < indexCount; i++) { - int targetIndex = [[indexes objectAtIndex:i] intValue]; - int visible = 0; - uint32_t length = currentMenu->GetItemCount(); - for (unsigned int j = 0; j < length; j++) { - nsMenuObjectX* targetMenu = currentMenu->GetItemAt(j); - if (!targetMenu) - return NS_OK; - if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(targetMenu->Content())) { - visible++; - if (targetMenu->MenuObjectType() == eSubmenuObjectType && visible == (targetIndex + 1)) { - currentMenu = static_cast(targetMenu); - // fake open/close to cause lazy update to happen - currentMenu->MenuOpened(); - currentMenu->MenuClosed(); - break; - } - } - } - } - - return NS_OK; -} - -void -nsStandaloneNativeMenu::IconUpdated() -{ - if (mContainerStatusBarItem) { - [mContainerStatusBarItem setImage:[mMenu->NativeMenuItem() image]]; - } -} - -void -nsStandaloneNativeMenu::SetContainerStatusBarItem(NSStatusItem* aItem) -{ - mContainerStatusBarItem = aItem; - IconUpdated(); -} diff --git a/widget/cocoa/nsSystemStatusBarCocoa.h b/widget/cocoa/nsSystemStatusBarCocoa.h deleted file mode 100644 index 51aa4df00d..0000000000 --- a/widget/cocoa/nsSystemStatusBarCocoa.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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 nsSystemStatusBarCocoa_h_ -#define nsSystemStatusBarCocoa_h_ - -#include "mozilla/RefPtr.h" -#include "nsISystemStatusBar.h" -#include "nsClassHashtable.h" - -class nsStandaloneNativeMenu; -@class NSStatusItem; - -class nsSystemStatusBarCocoa : public nsISystemStatusBar -{ -public: - nsSystemStatusBarCocoa() {} - - NS_DECL_ISUPPORTS - NS_DECL_NSISYSTEMSTATUSBAR - -protected: - virtual ~nsSystemStatusBarCocoa() {} - - struct StatusItem - { - explicit StatusItem(nsStandaloneNativeMenu* aMenu); - ~StatusItem(); - - private: - RefPtr mMenu; - NSStatusItem* mStatusItem; - }; - - nsClassHashtable mItems; -}; - -#endif // nsSystemStatusBarCocoa_h_ diff --git a/widget/cocoa/nsSystemStatusBarCocoa.mm b/widget/cocoa/nsSystemStatusBarCocoa.mm deleted file mode 100644 index 522da71451..0000000000 --- a/widget/cocoa/nsSystemStatusBarCocoa.mm +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */ -/* 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/. */ - -#import - -#include "nsComponentManagerUtils.h" -#include "nsSystemStatusBarCocoa.h" -#include "nsStandaloneNativeMenu.h" -#include "nsObjCExceptions.h" -#include "nsIDOMElement.h" - -NS_IMPL_ISUPPORTS(nsSystemStatusBarCocoa, nsISystemStatusBar) - -NS_IMETHODIMP -nsSystemStatusBarCocoa::AddItem(nsIDOMElement* aDOMElement) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - RefPtr menu = new nsStandaloneNativeMenu(); - nsresult rv = menu->Init(aDOMElement); - if (NS_FAILED(rv)) { - return rv; - } - - nsCOMPtr keyPtr = aDOMElement; - mItems.Put(keyPtr, new StatusItem(menu)); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP -nsSystemStatusBarCocoa::RemoveItem(nsIDOMElement* aDOMElement) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - mItems.Remove(aDOMElement); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -nsSystemStatusBarCocoa::StatusItem::StatusItem(nsStandaloneNativeMenu* aMenu) - : mMenu(aMenu) -{ - MOZ_COUNT_CTOR(nsSystemStatusBarCocoa::StatusItem); - - NSMenu* nativeMenu = nil; - mMenu->GetNativeMenu(reinterpret_cast(&nativeMenu)); - - mStatusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; - [mStatusItem setMenu:nativeMenu]; - [mStatusItem setHighlightMode:YES]; - - // We want the status item to get its image from menu item that mMenu was - // initialized with. Icon loads are asynchronous, so we need to let the menu - // know about the item so that it can update its icon as soon as it has - // loaded. - mMenu->SetContainerStatusBarItem(mStatusItem); -} - -nsSystemStatusBarCocoa::StatusItem::~StatusItem() -{ - mMenu->SetContainerStatusBarItem(nil); - [[NSStatusBar systemStatusBar] removeStatusItem:mStatusItem]; - [mStatusItem release]; - mStatusItem = nil; - - MOZ_COUNT_DTOR(nsSystemStatusBarCocoa::StatusItem); -} diff --git a/widget/cocoa/nsToolkit.h b/widget/cocoa/nsToolkit.h deleted file mode 100644 index 1631a8ac24..0000000000 --- a/widget/cocoa/nsToolkit.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsToolkit_h_ -#define nsToolkit_h_ - -#include "nscore.h" - -#import -#import -#import -#import - -class nsToolkit -{ -public: - nsToolkit(); - virtual ~nsToolkit(); - - static nsToolkit* GetToolkit(); - - static void Shutdown() { - delete gToolkit; - gToolkit = nullptr; - } - - static void PostSleepWakeNotification(const char* aNotification); - - static nsresult SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod, - bool classMethods = false); - - void RegisterForAllProcessMouseEvents(); - void UnregisterAllProcessMouseEventHandlers(); - -protected: - - nsresult RegisterForSleepWakeNotifications(); - void RemoveSleepWakeNotifications(); - -protected: - - static nsToolkit* gToolkit; - - CFRunLoopSourceRef mSleepWakeNotificationRLS; - io_object_t mPowerNotifier; - - CFMachPortRef mEventTapPort; - CFRunLoopSourceRef mEventTapRLS; -}; - -#endif // nsToolkit_h_ diff --git a/widget/cocoa/nsToolkit.mm b/widget/cocoa/nsToolkit.mm deleted file mode 100644 index 4d0222d5d3..0000000000 --- a/widget/cocoa/nsToolkit.mm +++ /dev/null @@ -1,326 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsToolkit.h" - -#include -#include -#include - -#include -#include -#include - -extern "C" { -#include -} -#include -#include - -#import -#import -#import - -#include "nsCocoaUtils.h" -#include "nsObjCExceptions.h" - -#include "nsGkAtoms.h" -#include "nsIRollupListener.h" -#include "nsIWidget.h" -#include "nsBaseWidget.h" - -#include "nsIObserverService.h" -#include "nsIServiceManager.h" - -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" - -using namespace mozilla; - -static io_connect_t gRootPort = MACH_PORT_NULL; - -nsToolkit* nsToolkit::gToolkit = nullptr; - -nsToolkit::nsToolkit() -: mSleepWakeNotificationRLS(nullptr) -, mEventTapPort(nullptr) -, mEventTapRLS(nullptr) -{ - MOZ_COUNT_CTOR(nsToolkit); - RegisterForSleepWakeNotifications(); -} - -nsToolkit::~nsToolkit() -{ - MOZ_COUNT_DTOR(nsToolkit); - RemoveSleepWakeNotifications(); - UnregisterAllProcessMouseEventHandlers(); -} - -void -nsToolkit::PostSleepWakeNotification(const char* aNotification) -{ - nsCOMPtr observerService = services::GetObserverService(); - if (observerService) - observerService->NotifyObservers(nullptr, aNotification, nullptr); -} - -// http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/PowerMgmt/chapter_10_section_3.html -static void ToolkitSleepWakeCallback(void *refCon, io_service_t service, natural_t messageType, void * messageArgument) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - switch (messageType) - { - case kIOMessageSystemWillSleep: - // System is going to sleep now. - nsToolkit::PostSleepWakeNotification(NS_WIDGET_SLEEP_OBSERVER_TOPIC); - ::IOAllowPowerChange(gRootPort, (long)messageArgument); - break; - - case kIOMessageCanSystemSleep: - // In this case, the computer has been idle for several minutes - // and will sleep soon so you must either allow or cancel - // this notification. Important: if you don’t respond, there will - // be a 30-second timeout before the computer sleeps. - // In Mozilla's case, we always allow sleep. - ::IOAllowPowerChange(gRootPort,(long)messageArgument); - break; - - case kIOMessageSystemHasPoweredOn: - // Handle wakeup. - nsToolkit::PostSleepWakeNotification(NS_WIDGET_WAKE_OBSERVER_TOPIC); - break; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -nsresult -nsToolkit::RegisterForSleepWakeNotifications() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - IONotificationPortRef notifyPortRef; - - NS_ASSERTION(!mSleepWakeNotificationRLS, "Already registered for sleep/wake"); - - gRootPort = ::IORegisterForSystemPower(0, ¬ifyPortRef, ToolkitSleepWakeCallback, &mPowerNotifier); - if (gRootPort == MACH_PORT_NULL) { - NS_ERROR("IORegisterForSystemPower failed"); - return NS_ERROR_FAILURE; - } - - mSleepWakeNotificationRLS = ::IONotificationPortGetRunLoopSource(notifyPortRef); - ::CFRunLoopAddSource(::CFRunLoopGetCurrent(), - mSleepWakeNotificationRLS, - kCFRunLoopDefaultMode); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -void -nsToolkit::RemoveSleepWakeNotifications() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mSleepWakeNotificationRLS) { - ::IODeregisterForSystemPower(&mPowerNotifier); - ::CFRunLoopRemoveSource(::CFRunLoopGetCurrent(), - mSleepWakeNotificationRLS, - kCFRunLoopDefaultMode); - - mSleepWakeNotificationRLS = nullptr; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Converts aPoint from the CoreGraphics "global display coordinate" system -// (which includes all displays/screens and has a top-left origin) to its -// (presumed) Cocoa counterpart (assumed to be the same as the "screen -// coordinates" system), which has a bottom-left origin. -static NSPoint ConvertCGGlobalToCocoaScreen(CGPoint aPoint) -{ - NSPoint cocoaPoint; - cocoaPoint.x = aPoint.x; - cocoaPoint.y = nsCocoaUtils::FlippedScreenY(aPoint.y); - return cocoaPoint; -} - -// Since our event tap is "listen only", events arrive here a little after -// they've already been processed. -static CGEventRef EventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if ((type == kCGEventTapDisabledByUserInput) || - (type == kCGEventTapDisabledByTimeout)) - return event; - if ([NSApp isActive]) - return event; - - nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); - NS_ENSURE_TRUE(rollupListener, event); - nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); - if (!rollupWidget) - return event; - - // Don't bother with rightMouseDown events here -- because of the delay, - // we'll end up closing browser context menus that we just opened. Since - // these events usually raise a context menu, we'll handle them by hooking - // the @"com.apple.HIToolbox.beginMenuTrackingNotification" distributed - // notification (in nsAppShell.mm's AppShellDelegate). - if (type == kCGEventRightMouseDown) - return event; - NSWindow *ctxMenuWindow = (NSWindow*) rollupWidget->GetNativeData(NS_NATIVE_WINDOW); - if (!ctxMenuWindow) - return event; - NSPoint screenLocation = ConvertCGGlobalToCocoaScreen(CGEventGetLocation(event)); - // Don't roll up the rollup widget if our mouseDown happens over it (doing - // so would break the corresponding context menu). - if (NSPointInRect(screenLocation, [ctxMenuWindow frame])) - return event; - rollupListener->Rollup(0, false, nullptr, nullptr); - return event; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NULL); -} - -// Cocoa Firefox's use of custom context menus requires that we explicitly -// handle mouse events from other processes that the OS handles -// "automatically" for native context menus -- mouseMoved events so that -// right-click context menus work properly when our browser doesn't have the -// focus (bmo bug 368077), and mouseDown events so that our browser can -// dismiss a context menu when a mouseDown happens in another process (bmo -// bug 339945). -void -nsToolkit::RegisterForAllProcessMouseEvents() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (getenv("MOZ_DEBUG")) - return; - - // Don't do this for apps that use native context menus. -#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS - return; -#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */ - - if (!mEventTapRLS) { - // Using an event tap for mouseDown events (instead of installing a - // handler for them on the EventMonitor target) works around an Apple - // bug that causes OS menus (like the Clock menu) not to work properly - // on OS X 10.4.X and below (bmo bug 381448). - // We install our event tap "listen only" to get around yet another Apple - // bug -- when we install it as an event filter on any kind of mouseDown - // event, that kind of event stops working in the main menu, and usually - // mouse event processing stops working in all apps in the current login - // session (so the entire OS appears to be hung)! The downside of - // installing listen-only is that events arrive at our handler slightly - // after they've already been processed. - mEventTapPort = CGEventTapCreate(kCGSessionEventTap, - kCGHeadInsertEventTap, - kCGEventTapOptionListenOnly, - CGEventMaskBit(kCGEventLeftMouseDown) - | CGEventMaskBit(kCGEventRightMouseDown) - | CGEventMaskBit(kCGEventOtherMouseDown), - EventTapCallback, - nullptr); - if (!mEventTapPort) - return; - mEventTapRLS = CFMachPortCreateRunLoopSource(nullptr, mEventTapPort, 0); - if (!mEventTapRLS) { - CFRelease(mEventTapPort); - mEventTapPort = nullptr; - return; - } - CFRunLoopAddSource(CFRunLoopGetCurrent(), mEventTapRLS, kCFRunLoopDefaultMode); - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -void -nsToolkit::UnregisterAllProcessMouseEventHandlers() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mEventTapRLS) { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mEventTapRLS, - kCFRunLoopDefaultMode); - CFRelease(mEventTapRLS); - mEventTapRLS = nullptr; - } - if (mEventTapPort) { - // mEventTapPort must be invalidated as well as released. Otherwise the - // event tap doesn't get destroyed until the browser process ends (it - // keeps showing up in the list returned by CGGetEventTapList()). - CFMachPortInvalidate(mEventTapPort); - CFRelease(mEventTapPort); - mEventTapPort = nullptr; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// Return the nsToolkit instance. If a toolkit does not yet exist, then one -// will be created. -// static -nsToolkit* nsToolkit::GetToolkit() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (!gToolkit) { - gToolkit = new nsToolkit(); - } - - return gToolkit; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr); -} - -// An alternative to [NSObject poseAsClass:] that isn't deprecated on OS X -// Leopard and is available to 64-bit binaries on Leopard and above. Based on -// ideas and code from http://www.cocoadev.com/index.pl?MethodSwizzling. -// Since the Method type becomes an opaque type as of Objective-C 2.0, we'll -// have to switch to using accessor methods like method_exchangeImplementations() -// when we build 64-bit binaries that use Objective-C 2.0 (on and for Leopard -// and above). -// -// Be aware that, if aClass doesn't have an orgMethod selector but one of its -// superclasses does, the method substitution will (in effect) take place in -// that superclass (rather than in aClass itself). The substitution has -// effect on the class where it takes place and all of that class's -// subclasses. In order for method swizzling to work properly, posedMethod -// needs to be unique in the class where the substitution takes place and all -// of its subclasses. -nsresult nsToolkit::SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod, - bool classMethods) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - Method original = nil; - Method posed = nil; - - if (classMethods) { - original = class_getClassMethod(aClass, orgMethod); - posed = class_getClassMethod(aClass, posedMethod); - } else { - original = class_getInstanceMethod(aClass, orgMethod); - posed = class_getInstanceMethod(aClass, posedMethod); - } - - if (!original || !posed) - return NS_ERROR_FAILURE; - - method_exchangeImplementations(original, posed); - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} diff --git a/widget/cocoa/nsWidgetFactory.mm b/widget/cocoa/nsWidgetFactory.mm deleted file mode 100644 index 3bddaf95ce..0000000000 --- a/widget/cocoa/nsWidgetFactory.mm +++ /dev/null @@ -1,219 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsIFactory.h" -#include "nsISupports.h" -#include "nsIComponentManager.h" -#include "mozilla/ModuleUtils.h" -#include "mozilla/WidgetUtils.h" - -#include "nsWidgetsCID.h" - -#include "nsChildView.h" -#include "nsCocoaWindow.h" -#include "nsAppShell.h" -#include "nsAppShellSingleton.h" -#include "nsFilePicker.h" -#include "nsColorPicker.h" - -#include "nsClipboard.h" -#include "nsClipboardHelper.h" -#include "nsTransferable.h" -#include "nsHTMLFormatConverter.h" -#include "nsDragService.h" -#include "nsToolkit.h" - -#include "nsLookAndFeel.h" - -#include "nsSound.h" -#include "nsIdleServiceX.h" -#include "NativeKeyBindings.h" -#include "OSXNotificationCenter.h" - -#include "nsScreenManagerCocoa.h" -#include "nsDeviceContextSpecX.h" -#include "nsPrintOptionsX.h" -#include "nsPrintDialogX.h" -#include "nsPrintSession.h" -#include "nsToolkitCompsCID.h" - -using namespace mozilla; -using namespace mozilla::widget; - -NS_GENERIC_FACTORY_CONSTRUCTOR(nsCocoaWindow) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildView) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPicker) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerCocoa) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecX) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsX, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintDialogServiceX, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceX, nsIdleServiceX::GetInstance) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(OSXNotificationCenter, Init) - -#include "nsMenuBarX.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeMenuServiceX) - -#include "nsBidiKeyboard.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) - -#include "nsNativeThemeCocoa.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeCocoa) - -#include "nsMacDockSupport.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacDockSupport) - -#include "nsMacWebAppUtils.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWebAppUtils) - -#include "nsStandaloneNativeMenu.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsStandaloneNativeMenu) - -#include "nsSystemStatusBarCocoa.h" -NS_GENERIC_FACTORY_CONSTRUCTOR(nsSystemStatusBarCocoa) - -#include "GfxInfo.h" -namespace mozilla { -namespace widget { -// This constructor should really be shared with all platforms. -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) -} // namespace widget -} // namespace mozilla - -NS_DEFINE_NAMED_CID(NS_WINDOW_CID); -NS_DEFINE_NAMED_CID(NS_POPUP_CID); -NS_DEFINE_NAMED_CID(NS_CHILD_CID); -NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); -NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); -NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); -NS_DEFINE_NAMED_CID(NS_SOUND_CID); -NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID); -NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID); -NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); -NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID); -NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID); -NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID); -NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); -NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID); -NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID); -NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_PRINTDIALOGSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID); -NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_NATIVEMENUSERVICE_CID); -NS_DEFINE_NAMED_CID(NS_MACDOCKSUPPORT_CID); -NS_DEFINE_NAMED_CID(NS_MACWEBAPPUTILS_CID); -NS_DEFINE_NAMED_CID(NS_STANDALONENATIVEMENU_CID); -NS_DEFINE_NAMED_CID(NS_MACSYSTEMSTATUSBAR_CID); -NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); - -static const mozilla::Module::CIDEntry kWidgetCIDs[] = { - { &kNS_WINDOW_CID, false, NULL, nsCocoaWindowConstructor }, - { &kNS_POPUP_CID, false, NULL, nsCocoaWindowConstructor }, - { &kNS_CHILD_CID, false, NULL, nsChildViewConstructor }, - { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_COLORPICKER_CID, false, NULL, nsColorPickerConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor, mozilla::Module::ALLOW_IN_GPU_PROCESS }, - { &kNS_SOUND_CID, false, NULL, nsSoundConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor }, - { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor }, - { &kNS_CLIPBOARD_CID, false, NULL, nsClipboardConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor }, - { &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor }, - { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor, - mozilla::Module::MAIN_PROCESS_ONLY }, - { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor }, - { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor }, - { &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsXConstructor }, - { &kNS_PRINTDIALOGSERVICE_CID, false, NULL, nsPrintDialogServiceXConstructor }, - { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceXConstructor }, - { &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, OSXNotificationCenterConstructor }, - { &kNS_NATIVEMENUSERVICE_CID, false, NULL, nsNativeMenuServiceXConstructor }, - { &kNS_MACDOCKSUPPORT_CID, false, NULL, nsMacDockSupportConstructor }, - { &kNS_MACWEBAPPUTILS_CID, false, NULL, nsMacWebAppUtilsConstructor }, - { &kNS_STANDALONENATIVEMENU_CID, false, NULL, nsStandaloneNativeMenuConstructor }, - { &kNS_MACSYSTEMSTATUSBAR_CID, false, NULL, nsSystemStatusBarCocoaConstructor }, - { &kNS_GFXINFO_CID, false, NULL, mozilla::widget::GfxInfoConstructor }, - { NULL } -}; - -static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { - { "@mozilla.org/widgets/window/mac;1", &kNS_WINDOW_CID }, - { "@mozilla.org/widgets/popup/mac;1", &kNS_POPUP_CID }, - { "@mozilla.org/widgets/childwindow/mac;1", &kNS_CHILD_CID }, - { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/appshell/mac;1", &kNS_APPSHELL_CID, mozilla::Module::ALLOW_IN_GPU_PROCESS }, - { "@mozilla.org/sound;1", &kNS_SOUND_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID }, - { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID }, - { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID }, - { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID }, - { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, - mozilla::Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID }, - { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID }, - { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID }, - { NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID }, - { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID }, - { "@mozilla.org/system-alerts-service;1", &kNS_SYSTEMALERTSSERVICE_CID }, - { "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID }, - { "@mozilla.org/widget/macdocksupport;1", &kNS_MACDOCKSUPPORT_CID }, - { "@mozilla.org/widget/mac-web-app-utils;1", &kNS_MACWEBAPPUTILS_CID }, - { "@mozilla.org/widget/standalonenativemenu;1", &kNS_STANDALONENATIVEMENU_CID }, - { "@mozilla.org/widget/macsystemstatusbar;1", &kNS_MACSYSTEMSTATUSBAR_CID }, - { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, - { NULL } -}; - -static void -nsWidgetCocoaModuleDtor() -{ - // Shutdown all XP level widget classes. - WidgetUtils::Shutdown(); - - NativeKeyBindings::Shutdown(); - nsLookAndFeel::Shutdown(); - nsToolkit::Shutdown(); - nsAppShellShutdown(); -} - -static const mozilla::Module kWidgetModule = { - mozilla::Module::kVersion, - kWidgetCIDs, - kWidgetContracts, - NULL, - NULL, - nsAppShellInit, - nsWidgetCocoaModuleDtor, - mozilla::Module::ALLOW_IN_GPU_PROCESS -}; - -NSMODULE_DEFN(nsWidgetMacModule) = &kWidgetModule; diff --git a/widget/cocoa/nsWindowMap.h b/widget/cocoa/nsWindowMap.h deleted file mode 100644 index c6ad72c010..0000000000 --- a/widget/cocoa/nsWindowMap.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsWindowMap_h_ -#define nsWindowMap_h_ - -#import - -// WindowDataMap -// -// In both mozilla and embedding apps, we need to have a place to put -// per-top-level-window logic and data, to handle such things as IME -// commit when the window gains/loses focus. We can't use a window -// delegate, because an embeddor probably already has one. Nor can we -// subclass NSWindow, again because we can't impose that burden on the -// embeddor. -// -// So we have a global map of NSWindow -> TopLevelWindowData, and set -// up TopLevelWindowData as a notification observer etc. - -@interface WindowDataMap : NSObject -{ -@private - NSMutableDictionary* mWindowMap; // dict of TopLevelWindowData keyed by address of NSWindow -} - -+ (WindowDataMap*)sharedWindowDataMap; - -- (void)ensureDataForWindow:(NSWindow*)inWindow; -- (id)dataForWindow:(NSWindow*)inWindow; - -// set data for a given window. inData is retained (and any previously set data -// is released). -- (void)setData:(id)inData forWindow:(NSWindow*)inWindow; - -// remove the data for the given window. the data is released. -- (void)removeDataForWindow:(NSWindow*)inWindow; - -@end - -@class ChildView; - -// TopLevelWindowData -// -// Class to hold per-window data, and handle window state changes. - -@interface TopLevelWindowData : NSObject -{ -@private -} - -- (id)initWithWindow:(NSWindow*)inWindow; -+ (void)activateInWindow:(NSWindow*)aWindow; -+ (void)deactivateInWindow:(NSWindow*)aWindow; -+ (void)activateInWindowViews:(NSWindow*)aWindow; -+ (void)deactivateInWindowViews:(NSWindow*)aWindow; - -@end - -#endif // nsWindowMap_h_ diff --git a/widget/cocoa/nsWindowMap.mm b/widget/cocoa/nsWindowMap.mm deleted file mode 100644 index c43b024086..0000000000 --- a/widget/cocoa/nsWindowMap.mm +++ /dev/null @@ -1,311 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsWindowMap.h" -#include "nsObjCExceptions.h" -#include "nsChildView.h" -#include "nsCocoaWindow.h" - -@interface WindowDataMap(Private) - -- (NSString*)keyForWindow:(NSWindow*)inWindow; - -@end - -@interface TopLevelWindowData(Private) - -- (void)windowResignedKey:(NSNotification*)inNotification; -- (void)windowBecameKey:(NSNotification*)inNotification; -- (void)windowWillClose:(NSNotification*)inNotification; - -@end - -#pragma mark - - -@implementation WindowDataMap - -+ (WindowDataMap*)sharedWindowDataMap -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - static WindowDataMap* sWindowMap = nil; - if (!sWindowMap) - sWindowMap = [[WindowDataMap alloc] init]; - - return sWindowMap; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (id)init -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - mWindowMap = [[NSMutableDictionary alloc] initWithCapacity:10]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindowMap release]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)ensureDataForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!inWindow || [self dataForWindow:inWindow]) - return; - - TopLevelWindowData* windowData = [[TopLevelWindowData alloc] initWithWindow:inWindow]; - [self setData:windowData forWindow:inWindow]; // takes ownership - [windowData release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (id)dataForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [mWindowMap objectForKey:[self keyForWindow:inWindow]]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)setData:(id)inData forWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindowMap setObject:inData forKey:[self keyForWindow:inWindow]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)removeDataForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mWindowMap removeObjectForKey:[self keyForWindow:inWindow]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (NSString*)keyForWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - return [NSString stringWithFormat:@"%p", inWindow]; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -@end - -// TopLevelWindowData -// -// This class holds data about top-level windows. We can't use a window -// delegate, because an embedder may already have one. - -@implementation TopLevelWindowData - -- (id)initWithWindow:(NSWindow*)inWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - - if ((self = [super init])) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowBecameKey:) - name:NSWindowDidBecomeKeyNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowResignedKey:) - name:NSWindowDidResignKeyNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowBecameMain:) - name:NSWindowDidBecomeMainNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowResignedMain:) - name:NSWindowDidResignMainNotification - object:inWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:inWindow]; - } - return self; - - NS_OBJC_END_TRY_ABORT_BLOCK_NIL; -} - -- (void)dealloc -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// As best I can tell, if the notification's object has a corresponding -// top-level widget (an nsCocoaWindow object), it has a delegate (set in -// nsCocoaWindow::StandardCreate()) of class WindowDelegate, and otherwise -// not (Camino didn't use top-level widgets (nsCocoaWindow objects) -- -// only child widgets (nsChildView objects)). (The notification is sent -// to windowBecameKey: or windowBecameMain: below.) -// -// For use with clients that (like Firefox) do use top-level widgets (and -// have NSWindow delegates of class WindowDelegate). -+ (void)activateInWindow:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - WindowDelegate* delegate = (WindowDelegate*) [aWindow delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) - return; - - if ([delegate toplevelActiveState]) - return; - [delegate sendToplevelActivateEvents]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// See comments above activateInWindow: -// -// If we're using top-level widgets (nsCocoaWindow objects), we send them -// NS_DEACTIVATE events (which propagate to child widgets (nsChildView -// objects) via nsWebShellWindow::HandleEvent()). -// -// For use with clients that (like Firefox) do use top-level widgets (and -// have NSWindow delegates of class WindowDelegate). -+ (void)deactivateInWindow:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - WindowDelegate* delegate = (WindowDelegate*) [aWindow delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) - return; - - if (![delegate toplevelActiveState]) - return; - [delegate sendToplevelDeactivateEvents]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// For use with clients that (like Camino) don't use top-level widgets (and -// don't have NSWindow delegates of class WindowDelegate). -+ (void)activateInWindowViews:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - id firstResponder = [aWindow firstResponder]; - if ([firstResponder isKindOfClass:[ChildView class]]) - [firstResponder viewsWindowDidBecomeKey]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// For use with clients that (like Camino) don't use top-level widgets (and -// don't have NSWindow delegates of class WindowDelegate). -+ (void)deactivateInWindowViews:(NSWindow*)aWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - id firstResponder = [aWindow firstResponder]; - if ([firstResponder isKindOfClass:[ChildView class]]) - [firstResponder viewsWindowDidResignKey]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -// We make certain exceptions for top-level windows in non-embedders (see -// comment above windowBecameMain below). And we need (elsewhere) to guard -// against sending duplicate events. But in general the NS_ACTIVATE event -// should be sent when a native window becomes key, and the NS_DEACTIVATE -// event should be sent when it resignes key. -- (void)windowBecameKey:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) { - [TopLevelWindowData activateInWindowViews:window]; - } else if ([window isSheet]) { - [TopLevelWindowData activateInWindow:window]; - } - - [[window contentView] setNeedsDisplay:YES]; -} - -- (void)windowResignedKey:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) { - [TopLevelWindowData deactivateInWindowViews:window]; - } else if ([window isSheet]) { - [TopLevelWindowData deactivateInWindow:window]; - } - - [[window contentView] setNeedsDisplay:YES]; -} - -// The appearance of a top-level window depends on its main state (not its key -// state). So (for non-embedders) we need to ensure that a top-level window -// is main when an NS_ACTIVATE event is sent to Gecko for it. -- (void)windowBecameMain:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - // Don't send events to a top-level window that has a sheet open above it -- - // as far as Gecko is concerned, it's inactive, and stays so until the sheet - // closes. - if (delegate && [delegate isKindOfClass:[WindowDelegate class]] && ![window attachedSheet]) - [TopLevelWindowData activateInWindow:window]; -} - -- (void)windowResignedMain:(NSNotification*)inNotification -{ - NSWindow* window = (NSWindow*)[inNotification object]; - - id delegate = [window delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]] && ![window attachedSheet]) - [TopLevelWindowData deactivateInWindow:window]; -} - -- (void)windowWillClose:(NSNotification*)inNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - // postpone our destruction - [[self retain] autorelease]; - - // remove ourselves from the window map (which owns us) - [[WindowDataMap sharedWindowDataMap] removeDataForWindow:[inNotification object]]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -@end diff --git a/widget/cocoa/resources/MainMenu.nib/classes.nib b/widget/cocoa/resources/MainMenu.nib/classes.nib deleted file mode 100644 index b9b4b09f6b..0000000000 --- a/widget/cocoa/resources/MainMenu.nib/classes.nib +++ /dev/null @@ -1,4 +0,0 @@ -{ - IBClasses = ({CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }); - IBVersion = 1; -} \ No newline at end of file diff --git a/widget/cocoa/resources/MainMenu.nib/info.nib b/widget/cocoa/resources/MainMenu.nib/info.nib deleted file mode 100644 index bcf3ace841..0000000000 --- a/widget/cocoa/resources/MainMenu.nib/info.nib +++ /dev/null @@ -1,21 +0,0 @@ - - - - - IBDocumentLocation - 159 127 356 240 0 0 1920 1178 - IBEditorPositions - - 29 - 413 971 130 44 0 0 1920 1178 - - IBFramework Version - 443.0 - IBOpenObjects - - 29 - - IBSystem Version - 8F46 - - diff --git a/widget/cocoa/resources/MainMenu.nib/keyedobjects.nib b/widget/cocoa/resources/MainMenu.nib/keyedobjects.nib deleted file mode 100644 index 16b3f7e523ed223596981d8b5ce48d7c05993cf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1877 zcmZWpYitx{6rJw{<=Jh4Sj#so!zfECM2B&0E52thPzkRXP7XJ#P=_s4#Zx%b?2&b>4B zE5fp-JDukcCY1H)*}K{yMuW@bMk(rZz@H|oN~J?rSNI%i{c>tnsEZu!w`KO}JMFQVPZk!HxEC&}35J%fefpUV&u!fN;!7{D zef9MnJKx&9=iR;g4}N^;@X-_BoIG{z`;#N**w9kbUrwp~Hrc z7&$5>b@Z4t$JlY>Crq4_J~?B`RHwJ}0}*W-BfzRD-JcP$pEIXP;jTU5d|@*1{72 zV?k+KsVfh>e^5@+7eOsahw!rU7Tz0TDm-nTN~2IbCO;Y#o4g>%SRt;;-{$pI^S(Th z59O)n0*mdnbx(=)5K$@XVF{cxOaX&jk`gP{rHID+@f1Fi_xHI(Sut(_MJj*C2ME1? zl$SSz0}(~Fukc2->R98d)lF*v!w3TxU5XS@6**X{2J37|=Ib+eWlU~#sUerBHGt!u zSbYRyVOORUN1&@98s@=_GK9*jrI2|KrsfCDcJxhN*WKNnEZ77AB-nT|PvUkyiVvxE zscYnLSS*jK#v5CH_E~%8I=&vfsE{-@77a>fzX$R`d;sV*VXf`~gTiG}upuHw8^FWn zO>LW=hsMHKTkU#~4^||g zK*&7%XYuujzuo8bRztH5Xc!rI_NBl5t7Bgu=aYCkpUg9Osx8}wY$I(m;n}z59L}?! ziRYg+*PPr77h5kHV_95a&HfztR0;_~k}zCw2or@&VUAENlnQ_(WhJHtX zqTA>Wx{L1P-ncLBj|bq9I2~u;Oq`30a0w1z2`gB`jkpZC-1Nb05gpc48 zxC5WX=kNu58F%4d@n85J?k0#3!bneIBST0ENhcX(Dw#&6lUXF66q31Q9tn^jSxK77 zRewdh15eA zQ7>Iio9G6*k#3@!=@z<`Zll}j9@& -GfxInfo::GetGfxDriverInfo() -{ - if (mDriverInfo->IsEmpty()) { - APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Ios, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAll), GfxDriverInfo::allDevices, - nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_STATUS_OK, - DRIVER_COMPARISON_IGNORED, GfxDriverInfo::allDriverVersions ); - } - - return *mDriverInfo; -} - -nsresult -GfxInfo::GetFeatureStatusImpl(int32_t aFeature, - int32_t *aStatus, - nsAString & aSuggestedDriverVersion, - const nsTArray& aDriverInfo, - OperatingSystem* aOS /* = nullptr */) -{ - NS_ENSURE_ARG_POINTER(aStatus); - aSuggestedDriverVersion.SetIsVoid(true); - *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; - if (aOS) - *aOS = OperatingSystem::Ios; - - if (mShutdownOccurred) { - return NS_OK; - } - - // OpenGL layers are never blacklisted on iOS. - // This early return is so we avoid potentially slow - // GLStrings initialization on startup when we initialize GL layers. - if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS || - aFeature == nsIGfxInfo::FEATURE_WEBGL_OPENGL || - aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) { - *aStatus = nsIGfxInfo::FEATURE_STATUS_OK; - return NS_OK; - } - - return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aOS); -} - -#ifdef DEBUG - -// Implement nsIGfxInfoDebug - -NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion) -{ - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) -{ - return NS_ERROR_FAILURE; -} - -#endif - -} -} diff --git a/widget/uikit/GfxInfo.h b/widget/uikit/GfxInfo.h deleted file mode 100644 index 16a2242515..0000000000 --- a/widget/uikit/GfxInfo.h +++ /dev/null @@ -1,78 +0,0 @@ -/* vim: se cin sw=2 ts=2 et : */ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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_widget_GfxInfo_h__ -#define __mozilla_widget_GfxInfo_h__ - -#include "GfxInfoBase.h" -#include "GfxDriverInfo.h" - -#include "nsString.h" -#include "mozilla/UniquePtr.h" - -namespace mozilla { - -namespace gl { -class GLContext; -} - -namespace widget { - -class GfxInfo : public GfxInfoBase -{ -private: - ~GfxInfo(); - -public: - GfxInfo(); - - // We only declare the subset of nsIGfxInfo that we actually implement. The - // rest is brought forward from GfxInfoBase. - NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled); - NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled); - NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion); - NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams); - NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription); - NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver); - NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID); - NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID); - NS_IMETHOD GetAdapterSubsysID(nsAString & aAdapterSubsysID); - NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM); - NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion); - NS_IMETHOD GetAdapterDriverDate(nsAString & aAdapterDriverDate); - NS_IMETHOD GetAdapterDescription2(nsAString & aAdapterDescription); - NS_IMETHOD GetAdapterDriver2(nsAString & aAdapterDriver); - NS_IMETHOD GetAdapterVendorID2(nsAString & aAdapterVendorID); - NS_IMETHOD GetAdapterDeviceID2(nsAString & aAdapterDeviceID); - NS_IMETHOD GetAdapterSubsysID2(nsAString & aAdapterSubsysID); - NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM); - NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion); - NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate); - NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active); - using GfxInfoBase::GetFeatureStatus; - using GfxInfoBase::GetFeatureSuggestedDriverVersion; - using GfxInfoBase::GetWebGLParameter; - -#ifdef DEBUG - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIGFXINFODEBUG -#endif - -protected: - - virtual nsresult GetFeatureStatusImpl(int32_t aFeature, - int32_t *aStatus, - nsAString & aSuggestedDriverVersion, - const nsTArray& aDriverInfo, - OperatingSystem* aOS = nullptr); - virtual const nsTArray& GetGfxDriverInfo(); -}; - -} // namespace widget -} // namespace mozilla - -#endif /* __mozilla_widget_GfxInfo_h__ */ diff --git a/widget/uikit/moz.build b/widget/uikit/moz.build deleted file mode 100644 index 2c6c188de6..0000000000 --- a/widget/uikit/moz.build +++ /dev/null @@ -1,18 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -SOURCES += [ - 'GfxInfo.cpp', - 'nsAppShell.mm', - 'nsLookAndFeel.mm', - 'nsScreenManager.mm', - 'nsWidgetFactory.mm', - 'nsWindow.mm', -] - -FINAL_LIBRARY = 'xul' -LOCAL_INCLUDES += [ - '/widget', -] diff --git a/widget/uikit/nsAppShell.h b/widget/uikit/nsAppShell.h deleted file mode 100644 index a88fa8b4f1..0000000000 --- a/widget/uikit/nsAppShell.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -/* - * Runs the main native UIKit run loop, interrupting it as needed to process - * Gecko events. - */ - -#ifndef nsAppShell_h_ -#define nsAppShell_h_ - -#include "nsBaseAppShell.h" -#include "nsTArray.h" - -#include -#include -#include - -@class AppShellDelegate; - -class nsAppShell : public nsBaseAppShell -{ -public: - NS_IMETHOD ResumeNative(void); - - nsAppShell(); - - nsresult Init(); - - NS_IMETHOD Run(void); - NS_IMETHOD Exit(void); - // Called by the application delegate - void WillTerminate(void); - - static nsAppShell* gAppShell; - static UIWindow* gWindow; - static NSMutableArray* gTopLevelViews; - -protected: - virtual ~nsAppShell(); - - static void ProcessGeckoEvents(void* aInfo); - virtual void ScheduleNativeEventCallback(); - virtual bool ProcessNextNativeEvent(bool aMayWait); - - NSAutoreleasePool* mAutoreleasePool; - AppShellDelegate* mDelegate; - CFRunLoopRef mCFRunLoop; - CFRunLoopSourceRef mCFRunLoopSource; - - bool mTerminated; - bool mNotifiedWillTerminate; -}; - -#endif // nsAppShell_h_ diff --git a/widget/uikit/nsAppShell.mm b/widget/uikit/nsAppShell.mm deleted file mode 100644 index ac007132fd..0000000000 --- a/widget/uikit/nsAppShell.mm +++ /dev/null @@ -1,271 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#import -#import -#import -#import - -#include "nsAppShell.h" -#include "nsCOMPtr.h" -#include "nsIFile.h" -#include "nsDirectoryServiceDefs.h" -#include "nsString.h" -#include "nsIRollupListener.h" -#include "nsIWidget.h" -#include "nsThreadUtils.h" -#include "nsIWindowMediator.h" -#include "nsMemoryPressure.h" -#include "nsServiceManagerUtils.h" -#include "nsIInterfaceRequestor.h" -#include "nsIWebBrowserChrome.h" - -nsAppShell *nsAppShell::gAppShell = NULL; -UIWindow *nsAppShell::gWindow = nil; -NSMutableArray *nsAppShell::gTopLevelViews = [[NSMutableArray alloc] init]; - -#define ALOG(args...) fprintf(stderr, args); fprintf(stderr, "\n") - -// ViewController -@interface ViewController : UIViewController -@end - - -@implementation ViewController - -- (void)loadView { - ALOG("[ViewController loadView]"); - CGRect r = {{0, 0}, {100, 100}}; - self.view = [[UIView alloc] initWithFrame:r]; - [self.view setBackgroundColor:[UIColor lightGrayColor]]; - // add all of the top level views as children - for (UIView* v in nsAppShell::gTopLevelViews) { - ALOG("[ViewController.view addSubView:%p]", v); - [self.view addSubview:v]; - } - [nsAppShell::gTopLevelViews release]; - nsAppShell::gTopLevelViews = nil; -} -@end - -// AppShellDelegate -// -// Acts as a delegate for the UIApplication - -@interface AppShellDelegate : NSObject { -} -@property (strong, nonatomic) UIWindow *window; -@end - -@implementation AppShellDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - ALOG("[AppShellDelegate application:didFinishLaunchingWithOptions:]"); - // We only create one window, since we can only display one window at - // a time anyway. Also, iOS 4 fails to display UIWindows if you - // create them before calling UIApplicationMain, so this makes more sense. - nsAppShell::gWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] retain]; - self.window = nsAppShell::gWindow; - - self.window.rootViewController = [[ViewController alloc] init]; - - // just to make things more visible for now - nsAppShell::gWindow.backgroundColor = [UIColor blueColor]; - [nsAppShell::gWindow makeKeyAndVisible]; - - return YES; -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationWillTerminate:]"); - nsAppShell::gAppShell->WillTerminate(); -} - -- (void)applicationDidBecomeActive:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationDidBecomeActive:]"); -} - -- (void)applicationWillResignActive:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationWillResignActive:]"); -} - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application -{ - ALOG("[AppShellDelegate applicationDidReceiveMemoryWarning:]"); - NS_DispatchMemoryPressure(MemPressure_New); -} -@end - -// nsAppShell implementation - -NS_IMETHODIMP -nsAppShell::ResumeNative(void) -{ - return nsBaseAppShell::ResumeNative(); -} - -nsAppShell::nsAppShell() - : mAutoreleasePool(NULL), - mDelegate(NULL), - mCFRunLoop(NULL), - mCFRunLoopSource(NULL), - mTerminated(false), - mNotifiedWillTerminate(false) -{ - gAppShell = this; -} - -nsAppShell::~nsAppShell() -{ - if (mAutoreleasePool) { - [mAutoreleasePool release]; - mAutoreleasePool = NULL; - } - - if (mCFRunLoop) { - if (mCFRunLoopSource) { - ::CFRunLoopRemoveSource(mCFRunLoop, mCFRunLoopSource, - kCFRunLoopCommonModes); - ::CFRelease(mCFRunLoopSource); - } - ::CFRelease(mCFRunLoop); - } - - gAppShell = NULL; -} - -// Init -// -// public -nsresult -nsAppShell::Init() -{ - mAutoreleasePool = [[NSAutoreleasePool alloc] init]; - - // Add a CFRunLoopSource to the main native run loop. The source is - // responsible for interrupting the run loop when Gecko events are ready. - - mCFRunLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; - NS_ENSURE_STATE(mCFRunLoop); - ::CFRetain(mCFRunLoop); - - CFRunLoopSourceContext context; - bzero(&context, sizeof(context)); - // context.version = 0; - context.info = this; - context.perform = ProcessGeckoEvents; - - mCFRunLoopSource = ::CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); - NS_ENSURE_STATE(mCFRunLoopSource); - - ::CFRunLoopAddSource(mCFRunLoop, mCFRunLoopSource, kCFRunLoopCommonModes); - - return nsBaseAppShell::Init(); -} - -// ProcessGeckoEvents -// -// The "perform" target of mCFRunLoop, called when mCFRunLoopSource is -// signalled from ScheduleNativeEventCallback. -// -// protected static -void -nsAppShell::ProcessGeckoEvents(void* aInfo) -{ - nsAppShell* self = static_cast (aInfo); - self->NativeEventCallback(); - self->Release(); -} - -// WillTerminate -// -// public -void -nsAppShell::WillTerminate() -{ - mNotifiedWillTerminate = true; - if (mTerminated) - return; - mTerminated = true; - // We won't get another chance to process events - NS_ProcessPendingEvents(NS_GetCurrentThread()); - - // Unless we call nsBaseAppShell::Exit() here, it might not get called - // at all. - nsBaseAppShell::Exit(); -} - -// ScheduleNativeEventCallback -// -// protected virtual -void -nsAppShell::ScheduleNativeEventCallback() -{ - if (mTerminated) - return; - - NS_ADDREF_THIS(); - - // This will invoke ProcessGeckoEvents on the main thread. - ::CFRunLoopSourceSignal(mCFRunLoopSource); - ::CFRunLoopWakeUp(mCFRunLoop); -} - -// ProcessNextNativeEvent -// -// protected virtual -bool -nsAppShell::ProcessNextNativeEvent(bool aMayWait) -{ - if (mTerminated) - return false; - - NSString* currentMode = nil; - NSDate* waitUntil = nil; - if (aMayWait) - waitUntil = [NSDate distantFuture]; - NSRunLoop* currentRunLoop = [NSRunLoop currentRunLoop]; - - BOOL eventProcessed = NO; - do { - currentMode = [currentRunLoop currentMode]; - if (!currentMode) - currentMode = NSDefaultRunLoopMode; - - if (aMayWait) - eventProcessed = [currentRunLoop runMode:currentMode beforeDate:waitUntil]; - else - [currentRunLoop acceptInputForMode:currentMode beforeDate:waitUntil]; - } while(eventProcessed && aMayWait); - - return false; -} - -// Run -// -// public -NS_IMETHODIMP -nsAppShell::Run(void) -{ - ALOG("nsAppShell::Run"); - char argv[1][4] = {"app"}; - UIApplicationMain(1, (char**)argv, nil, @"AppShellDelegate"); - // UIApplicationMain doesn't exit. :-( - return NS_OK; -} - -NS_IMETHODIMP -nsAppShell::Exit(void) -{ - if (mTerminated) - return NS_OK; - - mTerminated = true; - return nsBaseAppShell::Exit(); -} diff --git a/widget/uikit/nsLookAndFeel.h b/widget/uikit/nsLookAndFeel.h deleted file mode 100644 index 91c0c2d73e..0000000000 --- a/widget/uikit/nsLookAndFeel.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 __nsLookAndFeel -#define __nsLookAndFeel - -#include "nsXPLookAndFeel.h" - -class nsLookAndFeel: public nsXPLookAndFeel -{ -public: - nsLookAndFeel(); - virtual ~nsLookAndFeel(); - - virtual nsresult NativeGetColor(const ColorID aID, nscolor &aResult); - virtual nsresult GetIntImpl(IntID aID, int32_t &aResult); - virtual nsresult GetFloatImpl(FloatID aID, float &aResult); - virtual bool GetFontImpl(FontID aID, nsString& aFontName, - gfxFontStyle& aFontStyle, - float aDevPixPerCSSPixel); - virtual char16_t GetPasswordCharacterImpl() - { - // unicode value for the bullet character, used for password textfields. - return 0x2022; - } - - static bool UseOverlayScrollbars() - { - return true; - } -}; - -#endif diff --git a/widget/uikit/nsLookAndFeel.mm b/widget/uikit/nsLookAndFeel.mm deleted file mode 100644 index bb593eb51e..0000000000 --- a/widget/uikit/nsLookAndFeel.mm +++ /dev/null @@ -1,401 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#import -#import - -#include "nsLookAndFeel.h" -#include "nsStyleConsts.h" -#include "gfxFont.h" -#include "gfxFontConstants.h" - -nsLookAndFeel::nsLookAndFeel() - : nsXPLookAndFeel() -{ -} - -nsLookAndFeel::~nsLookAndFeel() -{ -} - -static nscolor GetColorFromUIColor(UIColor* aColor) -{ - CGColorRef cgColor = [aColor CGColor]; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgColor)); - const CGFloat* components = CGColorGetComponents(cgColor); - if (model == kCGColorSpaceModelRGB) { - return NS_RGB((unsigned int)(components[0] * 255.0), - (unsigned int)(components[1] * 255.0), - (unsigned int)(components[2] * 255.0)); - } - else if (model == kCGColorSpaceModelMonochrome) { - unsigned int val = (unsigned int)(components[0] * 255.0); - return NS_RGBA(val, val, val, - (unsigned int)(components[1] * 255.0)); - } - NS_NOTREACHED("Unhandled color space!"); - return 0; -} - -nsresult -nsLookAndFeel::NativeGetColor(const ColorID aID, nscolor &aResult) -{ - nsresult res = NS_OK; - - switch (aID) { - case eColorID_WindowBackground: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_WindowForeground: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_WidgetBackground: - aResult = NS_RGB(0xdd,0xdd,0xdd); - break; - case eColorID_WidgetForeground: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_WidgetSelectBackground: - aResult = NS_RGB(0x80,0x80,0x80); - break; - case eColorID_WidgetSelectForeground: - aResult = NS_RGB(0x00,0x00,0x80); - break; - case eColorID_Widget3DHighlight: - aResult = NS_RGB(0xa0,0xa0,0xa0); - break; - case eColorID_Widget3DShadow: - aResult = NS_RGB(0x40,0x40,0x40); - break; - case eColorID_TextBackground: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_TextForeground: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_TextSelectBackground: - case eColorID_highlight: // CSS2 color - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_menuhover: - aResult = NS_RGB(0xee,0xee,0xee); - break; - case eColorID_TextSelectForeground: - case eColorID_highlighttext: // CSS2 color - case eColorID__moz_menuhovertext: - GetColor(eColorID_TextSelectBackground, aResult); - if (aResult == 0x000000) - aResult = NS_RGB(0xff,0xff,0xff); - else - aResult = NS_DONT_CHANGE_COLOR; - break; - case eColorID_IMESelectedRawTextBackground: - case eColorID_IMESelectedConvertedTextBackground: - case eColorID_IMERawInputBackground: - case eColorID_IMEConvertedTextBackground: - aResult = NS_TRANSPARENT; - break; - case eColorID_IMESelectedRawTextForeground: - case eColorID_IMESelectedConvertedTextForeground: - case eColorID_IMERawInputForeground: - case eColorID_IMEConvertedTextForeground: - aResult = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_IMERawInputUnderline: - case eColorID_IMEConvertedTextUnderline: - aResult = NS_40PERCENT_FOREGROUND_COLOR; - break; - case eColorID_IMESelectedRawTextUnderline: - case eColorID_IMESelectedConvertedTextUnderline: - aResult = NS_SAME_AS_FOREGROUND_COLOR; - break; - case eColorID_SpellCheckerUnderline: - aResult = NS_RGB(0xff, 0, 0); - break; - - // - // css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors - // - case eColorID_buttontext: - case eColorID__moz_buttonhovertext: - case eColorID_captiontext: - case eColorID_menutext: - case eColorID_infotext: - case eColorID__moz_menubartext: - case eColorID_windowtext: - aResult = GetColorFromUIColor([UIColor darkTextColor]); - break; - case eColorID_activecaption: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_activeborder: - aResult = NS_RGB(0x00,0x00,0x00); - break; - case eColorID_appworkspace: - aResult = NS_RGB(0xFF,0xFF,0xFF); - break; - case eColorID_background: - aResult = NS_RGB(0x63,0x63,0xCE); - break; - case eColorID_buttonface: - case eColorID__moz_buttonhoverface: - aResult = NS_RGB(0xF0,0xF0,0xF0); - break; - case eColorID_buttonhighlight: - aResult = NS_RGB(0xFF,0xFF,0xFF); - break; - case eColorID_buttonshadow: - aResult = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID_graytext: - aResult = NS_RGB(0x44,0x44,0x44); - break; - case eColorID_inactiveborder: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_inactivecaption: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID_inactivecaptiontext: - aResult = NS_RGB(0x45,0x45,0x45); - break; - case eColorID_scrollbar: - aResult = NS_RGB(0,0,0); //XXX - break; - case eColorID_threeddarkshadow: - aResult = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID_threedshadow: - aResult = NS_RGB(0xE0,0xE0,0xE0); - break; - case eColorID_threedface: - aResult = NS_RGB(0xF0,0xF0,0xF0); - break; - case eColorID_threedhighlight: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_threedlightshadow: - aResult = NS_RGB(0xDA,0xDA,0xDA); - break; - case eColorID_menu: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID_infobackground: - aResult = NS_RGB(0xFF,0xFF,0xC7); - break; - case eColorID_windowframe: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID_window: - case eColorID__moz_field: - case eColorID__moz_combobox: - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID__moz_fieldtext: - case eColorID__moz_comboboxtext: - aResult = GetColorFromUIColor([UIColor darkTextColor]); - break; - case eColorID__moz_dialog: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_dialogtext: - case eColorID__moz_cellhighlighttext: - case eColorID__moz_html_cellhighlighttext: - aResult = GetColorFromUIColor([UIColor darkTextColor]); - break; - case eColorID__moz_dragtargetzone: - case eColorID__moz_mac_chrome_active: - case eColorID__moz_mac_chrome_inactive: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_mac_focusring: - aResult = NS_RGB(0x3F,0x98,0xDD); - break; - case eColorID__moz_mac_menushadow: - aResult = NS_RGB(0xA3,0xA3,0xA3); - break; - case eColorID__moz_mac_menutextdisable: - aResult = NS_RGB(0x88,0x88,0x88); - break; - case eColorID__moz_mac_menutextselect: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_mac_disabledtoolbartext: - aResult = NS_RGB(0x3F,0x3F,0x3F); - break; - case eColorID__moz_mac_menuselect: - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_buttondefault: - aResult = NS_RGB(0xDC,0xDC,0xDC); - break; - case eColorID__moz_cellhighlight: - case eColorID__moz_html_cellhighlight: - case eColorID__moz_mac_secondaryhighlight: - // For inactive list selection - aResult = NS_RGB(0xaa,0xaa,0xaa); - break; - case eColorID__moz_eventreerow: - // Background color of even list rows. - aResult = NS_RGB(0xff,0xff,0xff); - break; - case eColorID__moz_oddtreerow: - // Background color of odd list rows. - aResult = NS_TRANSPARENT; - break; - case eColorID__moz_nativehyperlinktext: - // There appears to be no available system defined color. HARDCODING to the appropriate color. - aResult = NS_RGB(0x14,0x4F,0xAE); - break; - default: - NS_WARNING("Someone asked nsILookAndFeel for a color I don't know about"); - aResult = NS_RGB(0xff,0xff,0xff); - res = NS_ERROR_FAILURE; - break; - } - - return res; -} - -NS_IMETHODIMP -nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) -{ - nsresult res = nsXPLookAndFeel::GetIntImpl(aID, aResult); - if (NS_SUCCEEDED(res)) - return res; - res = NS_OK; - - switch (aID) { - case eIntID_CaretBlinkTime: - aResult = 567; - break; - case eIntID_CaretWidth: - aResult = 1; - break; - case eIntID_ShowCaretDuringSelection: - aResult = 0; - break; - case eIntID_SelectTextfieldsOnKeyFocus: - // Select textfield content when focused by kbd - // used by nsEventStateManager::sTextfieldSelectModel - aResult = 1; - break; - case eIntID_SubmenuDelay: - aResult = 200; - break; - case eIntID_MenusCanOverlapOSBar: - // xul popups are not allowed to overlap the menubar. - aResult = 0; - break; - case eIntID_SkipNavigatingDisabledMenuItem: - aResult = 1; - break; - case eIntID_DragThresholdX: - case eIntID_DragThresholdY: - aResult = 4; - break; - case eIntID_ScrollArrowStyle: - aResult = eScrollArrow_None; - break; - case eIntID_ScrollSliderStyle: - aResult = eScrollThumbStyle_Proportional; - break; - case eIntID_TreeOpenDelay: - aResult = 1000; - break; - case eIntID_TreeCloseDelay: - aResult = 1000; - break; - case eIntID_TreeLazyScrollDelay: - aResult = 150; - break; - case eIntID_TreeScrollDelay: - aResult = 100; - break; - case eIntID_TreeScrollLinesMax: - aResult = 3; - break; - case eIntID_DWMCompositor: - case eIntID_WindowsClassic: - case eIntID_WindowsDefaultTheme: - case eIntID_TouchEnabled: - aResult = 0; - res = NS_ERROR_NOT_IMPLEMENTED; - break; - case eIntID_MacGraphiteTheme: - aResult = 0; - break; - case eIntID_TabFocusModel: - aResult = 1; // default to just textboxes - break; - case eIntID_ScrollToClick: - aResult = 0; - break; - case eIntID_ChosenMenuItemsShouldBlink: - aResult = 1; - break; - case eIntID_IMERawInputUnderlineStyle: - case eIntID_IMEConvertedTextUnderlineStyle: - case eIntID_IMESelectedRawTextUnderlineStyle: - case eIntID_IMESelectedConvertedTextUnderline: - aResult = NS_STYLE_TEXT_DECORATION_STYLE_SOLID; - break; - case eIntID_SpellCheckerUnderlineStyle: - aResult = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED; - break; - case eIntID_ContextMenuOffsetVertical: - case eIntID_ContextMenuOffsetHorizontal: - aResult = 2; - break; - default: - aResult = 0; - res = NS_ERROR_FAILURE; - } - return res; -} - -NS_IMETHODIMP -nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult) -{ - nsresult res = nsXPLookAndFeel::GetFloatImpl(aID, aResult); - if (NS_SUCCEEDED(res)) - return res; - res = NS_OK; - - switch (aID) { - case eFloatID_IMEUnderlineRelativeSize: - aResult = 2.0f; - break; - case eFloatID_SpellCheckerUnderlineRelativeSize: - aResult = 2.0f; - break; - default: - aResult = -1.0; - res = NS_ERROR_FAILURE; - } - - return res; -} - -bool -nsLookAndFeel::GetFontImpl(FontID aID, nsString &aFontName, - gfxFontStyle &aFontStyle, - float aDevPixPerCSSPixel) -{ - // hack for now - if (aID == eFont_Window || aID == eFont_Document) { - aFontStyle.style = NS_FONT_STYLE_NORMAL; - aFontStyle.weight = NS_FONT_WEIGHT_NORMAL; - aFontStyle.stretch = NS_FONT_STRETCH_NORMAL; - aFontStyle.size = 14 * aDevPixPerCSSPixel; - aFontStyle.systemFont = true; - - aFontName.AssignLiteral("sans-serif"); - return true; - } - - //TODO: implement more here? - return false; -} diff --git a/widget/uikit/nsScreenManager.h b/widget/uikit/nsScreenManager.h deleted file mode 100644 index 1ff6a87ec7..0000000000 --- a/widget/uikit/nsScreenManager.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 nsScreenManager_h_ -#define nsScreenManager_h_ - -#include "nsBaseScreen.h" -#include "nsIScreenManager.h" -#include "nsCOMPtr.h" -#include "nsRect.h" - -@class UIScreen; - -class UIKitScreen : public nsBaseScreen -{ -public: - explicit UIKitScreen (UIScreen* screen); - ~UIKitScreen () {} - - NS_IMETHOD GetId(uint32_t* outId) { - *outId = 0; - return NS_OK; - } - - NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight); - NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth); - NS_IMETHOD GetColorDepth(int32_t* aColorDepth); - NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor); - NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) - { - return GetContentsScaleFactor(aScaleFactor); - } - -private: - UIScreen* mScreen; -}; - -class UIKitScreenManager : public nsIScreenManager -{ -public: - UIKitScreenManager (); - - NS_DECL_ISUPPORTS - - NS_DECL_NSISCREENMANAGER - - static LayoutDeviceIntRect GetBounds(); - -private: - virtual ~UIKitScreenManager () {} - //TODO: support >1 screen, iPad supports external displays - nsCOMPtr mScreen; -}; - -#endif // nsScreenManager_h_ diff --git a/widget/uikit/nsScreenManager.mm b/widget/uikit/nsScreenManager.mm deleted file mode 100644 index 601c911cd9..0000000000 --- a/widget/uikit/nsScreenManager.mm +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#import - -#include "gfxPoint.h" -#include "nsScreenManager.h" -#include "nsAppShell.h" - -static LayoutDeviceIntRect gScreenBounds; -static bool gScreenBoundsSet = false; - -UIKitScreen::UIKitScreen(UIScreen* aScreen) -{ - mScreen = [aScreen retain]; -} - -NS_IMETHODIMP -UIKitScreen::GetRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - return GetRectDisplayPix(outX, outY, outWidth, outHeight); -} - -NS_IMETHODIMP -UIKitScreen::GetAvailRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - return GetAvailRectDisplayPix(outX, outY, outWidth, outHeight); -} - -NS_IMETHODIMP -UIKitScreen::GetRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - nsIntRect rect = UIKitScreenManager::GetBounds(); - *outX = rect.x; - *outY = rect.y; - *outWidth = rect.width; - *outHeight = rect.height; - - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetAvailRectDisplayPix(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight) -{ - CGRect rect = [mScreen applicationFrame]; - CGFloat scale = [mScreen scale]; - - *outX = rect.origin.x * scale; - *outY = rect.origin.y * scale; - *outWidth = rect.size.width * scale; - *outHeight = rect.size.height * scale; - - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetPixelDepth(int32_t *aPixelDepth) -{ - // Close enough. - *aPixelDepth = 24; - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreen::GetColorDepth(int32_t *aColorDepth) -{ - return GetPixelDepth(aColorDepth); -} - -NS_IMETHODIMP -UIKitScreen::GetContentsScaleFactor(double* aContentsScaleFactor) -{ - *aContentsScaleFactor = [mScreen scale]; - return NS_OK; -} - -NS_IMPL_ISUPPORTS(UIKitScreenManager, nsIScreenManager) - -UIKitScreenManager::UIKitScreenManager() -: mScreen(new UIKitScreen([UIScreen mainScreen])) -{ -} - -LayoutDeviceIntRect -UIKitScreenManager::GetBounds() -{ - if (!gScreenBoundsSet) { - CGRect rect = [[UIScreen mainScreen] bounds]; - CGFloat scale = [[UIScreen mainScreen] scale]; - gScreenBounds.x = rect.origin.x * scale; - gScreenBounds.y = rect.origin.y * scale; - gScreenBounds.width = rect.size.width * scale; - gScreenBounds.height = rect.size.height * scale; - gScreenBoundsSet = true; - } - printf("UIKitScreenManager::GetBounds: %d %d %d %d\n", - gScreenBounds.x, gScreenBounds.y, gScreenBounds.width, gScreenBounds.height); - return gScreenBounds; -} - -NS_IMETHODIMP -UIKitScreenManager::GetPrimaryScreen(nsIScreen** outScreen) -{ - NS_IF_ADDREF(*outScreen = mScreen.get()); - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForRect(int32_t inLeft, - int32_t inTop, - int32_t inWidth, - int32_t inHeight, - nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForId(uint32_t id, - nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::ScreenForNativeWidget(void* aWidget, nsIScreen** outScreen) -{ - return GetPrimaryScreen(outScreen); -} - -NS_IMETHODIMP -UIKitScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens) -{ - //TODO: support multiple screens - *aNumberOfScreens = 1; - return NS_OK; -} - -NS_IMETHODIMP -UIKitScreenManager::GetSystemDefaultScale(float* aScale) -{ - *aScale = [UIScreen mainScreen].scale; - return NS_OK; -} diff --git a/widget/uikit/nsWidgetFactory.mm b/widget/uikit/nsWidgetFactory.mm deleted file mode 100644 index 9e4f028ff6..0000000000 --- a/widget/uikit/nsWidgetFactory.mm +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 "nsIFactory.h" -#include "nsISupports.h" -#include "nsIComponentManager.h" -#include "mozilla/ModuleUtils.h" - -#include "nsWidgetsCID.h" - -#include "nsAppShell.h" -#include "nsAppShellSingleton.h" -#include "nsLookAndFeel.h" -#include "nsScreenManager.h" -#include "nsWindow.h" - -NS_GENERIC_FACTORY_CONSTRUCTOR(UIKitScreenManager) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) - -#include "GfxInfo.h" -namespace mozilla { -namespace widget { -// This constructor should really be shared with all platforms. -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init) -} -} - -NS_DEFINE_NAMED_CID(NS_WINDOW_CID); -NS_DEFINE_NAMED_CID(NS_CHILD_CID); -NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); -NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); -NS_DEFINE_NAMED_CID(NS_GFXINFO_CID); - -static const mozilla::Module::CIDEntry kWidgetCIDs[] = { - { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor }, - { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor }, - { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor }, - { &kNS_SCREENMANAGER_CID, false, nullptr, UIKitScreenManagerConstructor }, - { &kNS_GFXINFO_CID, false, nullptr, mozilla::widget::GfxInfoConstructor }, - { nullptr } -}; - -static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { - { "@mozilla.org/widgets/window/uikit;1", &kNS_WINDOW_CID }, - { "@mozilla.org/widgets/childwindow/uikit;1", &kNS_CHILD_CID }, - { "@mozilla.org/widget/appshell/uikit;1", &kNS_APPSHELL_CID }, - { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID }, - { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID }, - { nullptr } -}; - -static void -nsWidgetUIKitModuleDtor() -{ - nsLookAndFeel::Shutdown(); - nsAppShellShutdown(); -} - -static const mozilla::Module kWidgetModule = { - mozilla::Module::kVersion, - kWidgetCIDs, - kWidgetContracts, - nullptr, - nullptr, - nsAppShellInit, - nsWidgetUIKitModuleDtor -}; - -NSMODULE_DEFN(nsWidgetUIKitModule) = &kWidgetModule; diff --git a/widget/uikit/nsWindow.h b/widget/uikit/nsWindow.h deleted file mode 100644 index cb18c09069..0000000000 --- a/widget/uikit/nsWindow.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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 NSWINDOW_H_ -#define NSWINDOW_H_ - -#include "nsBaseWidget.h" -#include "gfxPoint.h" - -#include "nsTArray.h" - -@class UIWindow; -@class UIView; -@class ChildView; - -class nsWindow : - public nsBaseWidget -{ - typedef nsBaseWidget Inherited; - -public: - nsWindow(); - - NS_DECL_ISUPPORTS_INHERITED - - // - // nsIWidget - // - - virtual MOZ_MUST_USE nsresult Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData = nullptr) - override; - virtual void Destroy() override; - NS_IMETHOD Show(bool aState) override; - NS_IMETHOD Enable(bool aState) override { - return NS_OK; - } - virtual bool IsEnabled() const override { - return true; - } - virtual bool IsVisible() const override { - return mVisible; - } - NS_IMETHOD SetFocus(bool aState=false) override; - virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; - - virtual void SetBackgroundColor(const nscolor &aColor) override; - virtual void* GetNativeData(uint32_t aDataType) override; - - NS_IMETHOD Move(double aX, double aY) override; - virtual void SetSizeMode(nsSizeMode aMode) override; - void EnteredFullScreen(bool aFullScreen); - NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override; - NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override; - virtual LayoutDeviceIntRect GetScreenBounds() override; - void ReportMoveEvent(); - void ReportSizeEvent(); - void ReportSizeModeEvent(nsSizeMode aMode); - - CGFloat BackingScaleFactor(); - void BackingScaleFactorChanged(); - virtual float GetDPI() override { - //XXX: terrible - return 326.0f; - } - virtual double GetDefaultScaleInternal() override { - return BackingScaleFactor(); - } - virtual int32_t RoundsWidgetCoordinatesTo() override; - - NS_IMETHOD SetTitle(const nsAString& aTitle) override { - return NS_OK; - } - - NS_IMETHOD Invalidate(const LayoutDeviceIntRect& aRect) override; - virtual nsresult ConfigureChildren(const nsTArray& aConfigurations) override; - NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) override; - - void WillPaintWindow(); - bool PaintWindow(LayoutDeviceIntRegion aRegion); - - bool HasModalDescendents() { return false; } - - //NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) override; - NS_IMETHOD_(void) SetInputContext( - const InputContext& aContext, - const InputContextAction& aAction); - NS_IMETHOD_(InputContext) GetInputContext(); - /* - NS_IMETHOD_(bool) ExecuteNativeKeyBinding( - NativeKeyBindingsType aType, - const mozilla::WidgetKeyboardEvent& aEvent, - DoCommandCallback aCallback, - void* aCallbackData) override; - */ - -protected: - virtual ~nsWindow(); - void BringToFront(); - nsWindow *FindTopLevel(); - bool IsTopLevel(); - nsresult GetCurrentOffset(uint32_t &aOffset, uint32_t &aLength); - nsresult DeleteRange(int aOffset, int aLen); - - void TearDownView(); - - ChildView* mNativeView; - bool mVisible; - nsTArray mChildren; - nsWindow* mParent; - InputContext mInputContext; - - void OnSizeChanged(const mozilla::gfx::IntSize& aSize); - - static void DumpWindows(); - static void DumpWindows(const nsTArray& wins, int indent = 0); - static void LogWindow(nsWindow *win, int index, int indent); -}; - -#endif /* NSWINDOW_H_ */ diff --git a/widget/uikit/nsWindow.mm b/widget/uikit/nsWindow.mm deleted file mode 100644 index 874626237c..0000000000 --- a/widget/uikit/nsWindow.mm +++ /dev/null @@ -1,862 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -#include - -#include "nsWindow.h" -#include "nsScreenManager.h" -#include "nsAppShell.h" - -#include "nsWidgetsCID.h" -#include "nsGfxCIID.h" - -#include "gfxQuartzSurface.h" -#include "gfxUtils.h" -#include "gfxImageSurface.h" -#include "gfxContext.h" -#include "nsRegion.h" -#include "Layers.h" -#include "nsTArray.h" - -#include "mozilla/BasicEvents.h" -#include "mozilla/TouchEvents.h" -#include "mozilla/Unused.h" - -#include "GeckoProfiler.h" - -using namespace mozilla; -using namespace mozilla::dom; -using namespace mozilla::layers; - -#define ALOG(args...) fprintf(stderr, args); fprintf(stderr, "\n") - -static LayoutDeviceIntPoint -UIKitPointsToDevPixels(CGPoint aPoint, CGFloat aBackingScale) -{ - return LayoutDeviceIntPoint(NSToIntRound(aPoint.x * aBackingScale), - NSToIntRound(aPoint.y * aBackingScale)); -} - -static CGRect -DevPixelsToUIKitPoints(const LayoutDeviceIntRect& aRect, CGFloat aBackingScale) -{ - return CGRectMake((CGFloat)aRect.x / aBackingScale, - (CGFloat)aRect.y / aBackingScale, - (CGFloat)aRect.width / aBackingScale, - (CGFloat)aRect.height / aBackingScale); -} - -// Used to retain a Cocoa object for the remainder of a method's execution. -class nsAutoRetainUIKitObject { -public: -nsAutoRetainUIKitObject(id anObject) -{ - mObject = [anObject retain]; -} -~nsAutoRetainUIKitObject() -{ - [mObject release]; -} -private: - id mObject; // [STRONG] -}; - -@interface ChildView : UIView -{ -@public - nsWindow* mGeckoChild; // weak ref - BOOL mWaitingForPaint; - CFMutableDictionaryRef mTouches; - int mNextTouchID; -} -// sets up our view, attaching it to its owning gecko view -- (id)initWithFrame:(CGRect)inFrame geckoChild:(nsWindow*)inChild; -// Our Gecko child was Destroy()ed -- (void)widgetDestroyed; -// Tear down this ChildView -- (void)delayedTearDown; -- (void)sendMouseEvent:(EventMessage) aType point:(LayoutDeviceIntPoint)aPoint widget:(nsWindow*)aWindow; -- (void)handleTap:(UITapGestureRecognizer *)sender; -- (BOOL)isUsingMainThreadOpenGL; -- (void)drawUsingOpenGL; -- (void)drawUsingOpenGLCallback; -- (void)sendTouchEvent:(EventMessage) aType touches:(NSSet*)aTouches widget:(nsWindow*)aWindow; -// Event handling (UIResponder) -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; -@end - -@implementation ChildView -+ (Class)layerClass { - return [CAEAGLLayer class]; -} - -- (id)initWithFrame:(CGRect)inFrame geckoChild:(nsWindow*)inChild -{ - self.multipleTouchEnabled = YES; - if ((self = [super initWithFrame:inFrame])) { - mGeckoChild = inChild; - } - ALOG("[ChildView[%p] initWithFrame:] (mGeckoChild = %p)", (void*)self, (void*)mGeckoChild); - self.opaque = YES; - self.alpha = 1.0; - - UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] - initWithTarget:self action:@selector(handleTap:)]; - tapRecognizer.numberOfTapsRequired = 1; - [self addGestureRecognizer:tapRecognizer]; - - mTouches = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr); - mNextTouchID = 0; - return self; -} - -- (void)widgetDestroyed -{ - mGeckoChild = nullptr; - CFRelease(mTouches); -} - -- (void)delayedTearDown -{ - [self removeFromSuperview]; - [self release]; -} - -- (void)sendMouseEvent:(EventMessage) aType point:(LayoutDeviceIntPoint)aPoint widget:(nsWindow*)aWindow -{ - WidgetMouseEvent event(true, aType, aWindow, - WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); - - event.mRefPoint = aPoint; - event.mClickCount = 1; - event.button = WidgetMouseEvent::eLeftButton; - event.mTime = PR_IntervalNow(); - event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; - - nsEventStatus status; - aWindow->DispatchEvent(&event, status); -} - -- (void)handleTap:(UITapGestureRecognizer *)sender -{ - if (sender.state == UIGestureRecognizerStateEnded) { - ALOG("[ChildView[%p] handleTap]", self); - LayoutDeviceIntPoint lp = UIKitPointsToDevPixels([sender locationInView:self], [self contentScaleFactor]); - [self sendMouseEvent:eMouseMove point:lp widget:mGeckoChild]; - [self sendMouseEvent:eMouseDown point:lp widget:mGeckoChild]; - [self sendMouseEvent:eMouseUp point:lp widget:mGeckoChild]; - } -} - -- (void)sendTouchEvent:(EventMessage) aType touches:(NSSet*)aTouches widget:(nsWindow*)aWindow -{ - WidgetTouchEvent event(true, aType, aWindow); - //XXX: I think nativeEvent.timestamp * 1000 is probably usable here but - // I don't care that much right now. - event.mTime = PR_IntervalNow(); - event.mTouches.SetCapacity(aTouches.count); - for (UITouch* touch in aTouches) { - LayoutDeviceIntPoint loc = UIKitPointsToDevPixels([touch locationInView:self], [self contentScaleFactor]); - LayoutDeviceIntPoint radius = UIKitPointsToDevPixels([touch majorRadius], [touch majorRadius]); - void* value; - if (!CFDictionaryGetValueIfPresent(mTouches, touch, (const void**)&value)) { - // This shouldn't happen. - NS_ASSERTION(false, "Got a touch that we didn't know about"); - continue; - } - int id = reinterpret_cast(value); - RefPtr t = new Touch(id, loc, radius, 0.0f, 1.0f); - event.mRefPoint = loc; - event.mTouches.AppendElement(t); - } - aWindow->DispatchInputEvent(&event); -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesBegan", self); - if (!mGeckoChild) - return; - - for (UITouch* touch : touches) { - CFDictionaryAddValue(mTouches, touch, (void*)mNextTouchID); - mNextTouchID++; - } - [self sendTouchEvent:eTouchStart - touches:[event allTouches] - widget:mGeckoChild]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesCancelled", self); - [self sendTouchEvent:eTouchCancel touches:touches widget:mGeckoChild]; - for (UITouch* touch : touches) { - CFDictionaryRemoveValue(mTouches, touch); - } - if (CFDictionaryGetCount(mTouches) == 0) { - mNextTouchID = 0; - } -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesEnded", self); - if (!mGeckoChild) - return; - - [self sendTouchEvent:eTouchEnd touches:touches widget:mGeckoChild]; - for (UITouch* touch : touches) { - CFDictionaryRemoveValue(mTouches, touch); - } - if (CFDictionaryGetCount(mTouches) == 0) { - mNextTouchID = 0; - } -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - ALOG("[ChildView[%p] touchesMoved", self); - if (!mGeckoChild) - return; - - [self sendTouchEvent:eTouchMove - touches:[event allTouches] - widget:mGeckoChild]; -} - -- (void)setNeedsDisplayInRect:(CGRect)aRect -{ - if ([self isUsingMainThreadOpenGL]) { - // Draw without calling drawRect. This prevent us from - // needing to access the normal window buffer surface unnecessarily, so we - // waste less time synchronizing the two surfaces. - if (!mWaitingForPaint) { - mWaitingForPaint = YES; - // Use NSRunLoopCommonModes instead of the default NSDefaultRunLoopMode - // so that the timer also fires while a native menu is open. - [self performSelector:@selector(drawUsingOpenGLCallback) - withObject:nil - afterDelay:0 - inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; - } - } -} - -- (BOOL)isUsingMainThreadOpenGL -{ - if (!mGeckoChild || ![self window]) - return NO; - - return mGeckoChild->GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL; -} - -- (void)drawUsingOpenGL -{ - ALOG("drawUsingOpenGL"); - PROFILER_LABEL("ChildView", "drawUsingOpenGL", - js::ProfileEntry::Category::GRAPHICS); - - if (!mGeckoChild->IsVisible()) - return; - - mWaitingForPaint = NO; - - LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds(); - LayoutDeviceIntRegion region(geckoBounds); - - mGeckoChild->PaintWindow(region); -} - -// Called asynchronously after setNeedsDisplay in order to avoid entering the -// normal drawing machinery. -- (void)drawUsingOpenGLCallback -{ - if (mWaitingForPaint) { - [self drawUsingOpenGL]; - } -} - -// The display system has told us that a portion of our view is dirty. Tell -// gecko to paint it -- (void)drawRect:(CGRect)aRect -{ - CGContextRef cgContext = UIGraphicsGetCurrentContext(); - [self drawRect:aRect inContext:cgContext]; -} - -- (void)drawRect:(CGRect)aRect inContext:(CGContextRef)aContext -{ -#ifdef DEBUG_UPDATE - LayoutDeviceIntRect geckoBounds = mGeckoChild->GetBounds(); - - fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n gecko bounds: [%d %d %d %d]\n", - self, mGeckoChild, - aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height, aContext, - geckoBounds.x, geckoBounds.y, geckoBounds.width, geckoBounds.height); - - CGAffineTransform xform = CGContextGetCTM(aContext); - fprintf (stderr, " xform in: [%f %f %f %f %f %f]\n", xform.a, xform.b, xform.c, xform.d, xform.tx, xform.ty); -#endif - - if (true) { - // For Gecko-initiated repaints in OpenGL mode, drawUsingOpenGL is - // directly called from a delayed perform callback - without going through - // drawRect. - // Paints that come through here are triggered by something that Cocoa - // controls, for example by window resizing or window focus changes. - - // Do GL composition and return. - [self drawUsingOpenGL]; - return; - } - PROFILER_LABEL("ChildView", "drawRect", - js::ProfileEntry::Category::GRAPHICS); - - // The CGContext that drawRect supplies us with comes with a transform that - // scales one user space unit to one Cocoa point, which can consist of - // multiple dev pixels. But Gecko expects its supplied context to be scaled - // to device pixels, so we need to reverse the scaling. - double scale = mGeckoChild->BackingScaleFactor(); - CGContextSaveGState(aContext); - CGContextScaleCTM(aContext, 1.0 / scale, 1.0 / scale); - - CGSize viewSize = [self bounds].size; - gfx::IntSize backingSize(viewSize.width * scale, viewSize.height * scale); - - CGContextSaveGState(aContext); - - LayoutDeviceIntRegion region = - LayoutDeviceIntRect(NSToIntRound(aRect.origin.x * scale), - NSToIntRound(aRect.origin.y * scale), - NSToIntRound(aRect.size.width * scale), - NSToIntRound(aRect.size.height * scale)); - - // Create Cairo objects. - RefPtr targetSurface; - - RefPtr targetContext; - if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(gfx::BackendType::CAIRO)) { - // This is dead code unless you mess with prefs, but keep it around for - // debugging. - targetSurface = new gfxQuartzSurface(aContext, backingSize); - targetSurface->SetAllowUseAsSource(false); - RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface, - backingSize); - if (!dt || !dt->IsValid()) { - gfxDevCrash(mozilla::gfx::LogReason::InvalidContext) << "Window context problem 2 " << backingSize; - return; - } - dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr); - targetContext = gfxContext::CreateOrNull(dt); - } else { - MOZ_ASSERT_UNREACHABLE("COREGRAPHICS is the only supported backend"); - } - MOZ_ASSERT(targetContext); // already checked for valid draw targets above - - // Set up the clip region. - targetContext->NewPath(); - for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - targetContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height)); - } - targetContext->Clip(); - - //nsAutoRetainCocoaObject kungFuDeathGrip(self); - bool painted = false; - if (mGeckoChild->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) { - nsBaseWidget::AutoLayerManagerSetup - setupLayerManager(mGeckoChild, targetContext, BufferMode::BUFFER_NONE); - painted = mGeckoChild->PaintWindow(region); - } else if (mGeckoChild->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { - // We only need this so that we actually get DidPaintWindow fired - painted = mGeckoChild->PaintWindow(region); - } - - targetContext = nullptr; - targetSurface = nullptr; - - CGContextRestoreGState(aContext); - - // Undo the scale transform so that from now on the context is in - // CocoaPoints again. - CGContextRestoreGState(aContext); - if (!painted && [self isOpaque]) { - // Gecko refused to draw, but we've claimed to be opaque, so we have to - // draw something--fill with white. - CGContextSetRGBFillColor(aContext, 1, 1, 1, 1); - CGContextFillRect(aContext, aRect); - } - -#ifdef DEBUG_UPDATE - fprintf (stderr, "---- update done ----\n"); - -#if 0 - CGContextSetRGBStrokeColor (aContext, - ((((unsigned long)self) & 0xff)) / 255.0, - ((((unsigned long)self) & 0xff00) >> 8) / 255.0, - ((((unsigned long)self) & 0xff0000) >> 16) / 255.0, - 0.5); -#endif - CGContextSetRGBStrokeColor(aContext, 1, 0, 0, 0.8); - CGContextSetLineWidth(aContext, 4.0); - CGContextStrokeRect(aContext, aRect); -#endif -} -@end - -NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, Inherited) - -nsWindow::nsWindow() -: mNativeView(nullptr), - mVisible(false), - mParent(nullptr) -{ -} - -nsWindow::~nsWindow() -{ - [mNativeView widgetDestroyed]; // Safe if mNativeView is nil. - TearDownView(); // Safe if called twice. -} - -void nsWindow::TearDownView() -{ - if (!mNativeView) - return; - - [mNativeView performSelectorOnMainThread:@selector(delayedTearDown) withObject:nil waitUntilDone:false]; - mNativeView = nil; -} - -bool -nsWindow::IsTopLevel() -{ - return mWindowType == eWindowType_toplevel || - mWindowType == eWindowType_dialog || - mWindowType == eWindowType_invisible; -} - -// -// nsIWidget -// - -nsresult -nsWindow::Create(nsIWidget* aParent, - nsNativeWidget aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - ALOG("nsWindow[%p]::Create %p/%p [%d %d %d %d]", (void*)this, (void*)aParent, (void*)aNativeParent, aRect.x, aRect.y, aRect.width, aRect.height); - nsWindow* parent = (nsWindow*) aParent; - ChildView* nativeParent = (ChildView*)aNativeParent; - - if (parent == nullptr && nativeParent) - parent = nativeParent->mGeckoChild; - if (parent && nativeParent == nullptr) - nativeParent = parent->mNativeView; - - // for toplevel windows, bounds are fixed to full screen size - if (parent == nullptr) { - if (nsAppShell::gWindow == nil) { - mBounds = UIKitScreenManager::GetBounds(); - } else { - CGRect cgRect = [nsAppShell::gWindow bounds]; - mBounds.x = cgRect.origin.x; - mBounds.y = cgRect.origin.y; - mBounds.width = cgRect.size.width; - mBounds.height = cgRect.size.height; - } - } else { - mBounds = aRect; - } - - ALOG("nsWindow[%p]::Create bounds: %d %d %d %d", (void*)this, - mBounds.x, mBounds.y, mBounds.width, mBounds.height); - - // Set defaults which can be overriden from aInitData in BaseCreate - mWindowType = eWindowType_toplevel; - mBorderStyle = eBorderStyle_default; - - Inherited::BaseCreate(aParent, aInitData); - - NS_ASSERTION(IsTopLevel() || parent, "non top level window doesn't have a parent!"); - - mNativeView = [[ChildView alloc] initWithFrame:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor()) geckoChild:this]; - mNativeView.hidden = YES; - - if (parent) { - parent->mChildren.AppendElement(this); - mParent = parent; - } - - if (nativeParent) { - [nativeParent addSubview:mNativeView]; - } else if (nsAppShell::gWindow) { - [nsAppShell::gWindow.rootViewController.view addSubview:mNativeView]; - } - else { - [nsAppShell::gTopLevelViews addObject:mNativeView]; - } - - return NS_OK; -} - -void -nsWindow::Destroy() -{ - for (uint32_t i = 0; i < mChildren.Length(); ++i) { - // why do we still have children? - mChildren[i]->SetParent(nullptr); - } - - if (mParent) - mParent->mChildren.RemoveElement(this); - - [mNativeView widgetDestroyed]; - - nsBaseWidget::Destroy(); - - //ReportDestroyEvent(); - - TearDownView(); - - nsBaseWidget::OnDestroy(); - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::ConfigureChildren(const nsTArray& config) -{ - for (uint32_t i = 0; i < config.Length(); ++i) { - nsWindow *childWin = (nsWindow*) config[i].mChild.get(); - childWin->Resize(config[i].mBounds.x, - config[i].mBounds.y, - config[i].mBounds.width, - config[i].mBounds.height, - false); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Show(bool aState) -{ - if (aState != mVisible) { - mNativeView.hidden = aState ? NO : YES; - if (aState) { - UIView* parentView = mParent ? mParent->mNativeView : nsAppShell::gWindow.rootViewController.view; - [parentView bringSubviewToFront:mNativeView]; - [mNativeView setNeedsDisplay]; - } - mVisible = aState; - } - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Move(double aX, double aY) -{ - if (!mNativeView || (mBounds.x == aX && mBounds.y == aY)) - return NS_OK; - - //XXX: handle this - // The point we have is in Gecko coordinates (origin top-left). Convert - // it to Cocoa ones (origin bottom-left). - mBounds.x = aX; - mBounds.y = aY; - - mNativeView.frame = DevPixelsToUIKitPoints(mBounds, BackingScaleFactor()); - - if (mVisible) - [mNativeView setNeedsDisplay]; - - ReportMoveEvent(); - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Resize(double aX, double aY, - double aWidth, double aHeight, - bool aRepaint) -{ - BOOL isMoving = (mBounds.x != aX || mBounds.y != aY); - BOOL isResizing = (mBounds.width != aWidth || mBounds.height != aHeight); - if (!mNativeView || (!isMoving && !isResizing)) - return NS_OK; - - if (isMoving) { - mBounds.x = aX; - mBounds.y = aY; - } - if (isResizing) { - mBounds.width = aWidth; - mBounds.height = aHeight; - } - - [mNativeView setFrame:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor())]; - - if (mVisible && aRepaint) - [mNativeView setNeedsDisplay]; - - if (isMoving) - ReportMoveEvent(); - - if (isResizing) - ReportSizeEvent(); - - return NS_OK; -} - -NS_IMETHODIMP nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) -{ - if (!mNativeView || (mBounds.width == aWidth && mBounds.height == aHeight)) - return NS_OK; - - mBounds.width = aWidth; - mBounds.height = aHeight; - - [mNativeView setFrame:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor())]; - - if (mVisible && aRepaint) - [mNativeView setNeedsDisplay]; - - ReportSizeEvent(); - - return NS_OK; -} - -void -nsWindow::SetSizeMode(nsSizeMode aMode) -{ - if (aMode == static_cast(mSizeMode)) { - return; - } - - mSizeMode = static_cast(aMode); - if (aMode == nsSizeMode_Maximized || aMode == nsSizeMode_Fullscreen) { - // Resize to fill screen - nsBaseWidget::InfallibleMakeFullScreen(true); - } - ReportSizeModeEvent(aMode); -} - -NS_IMETHODIMP -nsWindow::Invalidate(const LayoutDeviceIntRect& aRect) -{ - if (!mNativeView || !mVisible) - return NS_OK; - - MOZ_RELEASE_ASSERT(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT, - "Shouldn't need to invalidate with accelerated OMTC layers!"); - - - [mNativeView setNeedsLayout]; - [mNativeView setNeedsDisplayInRect:DevPixelsToUIKitPoints(mBounds, BackingScaleFactor())]; - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::SetFocus(bool aRaise) -{ - [[mNativeView window] makeKeyWindow]; - [mNativeView becomeFirstResponder]; - return NS_OK; -} - -void nsWindow::WillPaintWindow() -{ - if (mWidgetListener) { - mWidgetListener->WillPaintWindow(this); - } -} - -bool nsWindow::PaintWindow(LayoutDeviceIntRegion aRegion) -{ - if (!mWidgetListener) - return false; - - bool returnValue = false; - returnValue = mWidgetListener->PaintWindow(this, aRegion); - - if (mWidgetListener) { - mWidgetListener->DidPaintWindow(); - } - - return returnValue; -} - -void nsWindow::ReportMoveEvent() -{ - NotifyWindowMoved(mBounds.x, mBounds.y); -} - -void nsWindow::ReportSizeModeEvent(nsSizeMode aMode) -{ - if (mWidgetListener) { - // This is terrible. - nsSizeMode theMode; - switch (aMode) { - case nsSizeMode_Maximized: - theMode = nsSizeMode_Maximized; - break; - case nsSizeMode_Fullscreen: - theMode = nsSizeMode_Fullscreen; - break; - default: - return; - } - mWidgetListener->SizeModeChanged(theMode); - } -} - -void nsWindow::ReportSizeEvent() -{ - if (mWidgetListener) { - LayoutDeviceIntRect innerBounds = GetClientBounds(); - mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height); - } -} - -LayoutDeviceIntRect -nsWindow::GetScreenBounds() -{ - return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size()); -} - -LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() -{ - LayoutDeviceIntPoint offset(0, 0); - if (mParent) { - offset = mParent->WidgetToScreenOffset(); - } - - CGPoint temp = [mNativeView convertPoint:temp toView:nil]; - - if (!mParent && nsAppShell::gWindow) { - // convert to screen coords - temp = [nsAppShell::gWindow convertPoint:temp toWindow:nil]; - } - - offset.x += temp.x; - offset.y += temp.y; - - return offset; -} - -NS_IMETHODIMP -nsWindow::DispatchEvent(mozilla::WidgetGUIEvent* aEvent, - nsEventStatus& aStatus) -{ - aStatus = nsEventStatus_eIgnore; - nsCOMPtr kungFuDeathGrip(aEvent->mWidget); - - if (mWidgetListener) - aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents); - - return NS_OK; -} - -NS_IMETHODIMP_(void) -nsWindow::SetInputContext(const InputContext& aContext, - const InputContextAction& aAction) -{ - //TODO: actually show VKB - mInputContext = aContext; -} - -NS_IMETHODIMP_(mozilla::widget::InputContext) -nsWindow::GetInputContext() -{ - return mInputContext; -} - -void -nsWindow::SetBackgroundColor(const nscolor &aColor) -{ - mNativeView.backgroundColor = [UIColor colorWithRed:NS_GET_R(aColor) - green:NS_GET_G(aColor) - blue:NS_GET_B(aColor) - alpha:NS_GET_A(aColor)]; -} - -void* nsWindow::GetNativeData(uint32_t aDataType) -{ - void* retVal = nullptr; - - switch (aDataType) - { - case NS_NATIVE_WIDGET: - case NS_NATIVE_DISPLAY: - retVal = (void*)mNativeView; - break; - - case NS_NATIVE_WINDOW: - retVal = [mNativeView window]; - break; - - case NS_NATIVE_GRAPHIC: - NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a UIKit child view!"); - break; - - case NS_NATIVE_OFFSETX: - retVal = 0; - break; - - case NS_NATIVE_OFFSETY: - retVal = 0; - break; - - case NS_NATIVE_PLUGIN_PORT: - // not implemented - break; - - case NS_RAW_NATIVE_IME_CONTEXT: - retVal = GetPseudoIMEContext(); - if (retVal) { - break; - } - retVal = NS_ONLY_ONE_NATIVE_IME_CONTEXT; - break; - } - - return retVal; -} - -CGFloat -nsWindow::BackingScaleFactor() -{ - if (mNativeView) { - return [mNativeView contentScaleFactor]; - } - return [UIScreen mainScreen].scale; -} - -int32_t -nsWindow::RoundsWidgetCoordinatesTo() -{ - if (BackingScaleFactor() == 2.0) { - return 2; - } - return 1; -} From 70b9128474c75ab5011ea17287089870f3c8f6bb Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sun, 9 May 2021 00:29:23 +0000 Subject: [PATCH 3/4] Issue #1751 -- Update crashtests --- testing/crashtest/crashtests.list | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/crashtest/crashtests.list b/testing/crashtest/crashtests.list index 863c10b9f6..3d798220ef 100644 --- a/testing/crashtest/crashtests.list +++ b/testing/crashtest/crashtests.list @@ -67,7 +67,6 @@ include ../../security/manager/ssl/crashtests/crashtests.list include ../../view/crashtests/crashtests.list -include ../../widget/cocoa/crashtests/crashtests.list include ../../widget/crashtests/crashtests.list include ../../widget/gtk/crashtests/crashtests.list From 214ac352e5a8417487197837d06aa2f88835de4a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Fri, 7 May 2021 01:37:36 +0000 Subject: [PATCH 4/4] [Pale-Moon] Issue #1865 - Remove mac-specific resources This removes Mac-specific branding resources, shell service components, and the Mac browser theme. --- application/palemoon/base/moz.build | 4 +- .../branding/shared/branding.mozbuild | 8 - .../palemoon/branding/unofficial/disk.icns | Bin 39250 -> 0 bytes .../branding/unofficial/document.icns | Bin 12451 -> 0 bytes .../palemoon/branding/unofficial/dsstore | Bin 6148 -> 0 bytes .../palemoon/branding/unofficial/firefox.icns | Bin 12079 -> 0 bytes .../palemoon/components/build/moz.build | 5 +- .../palemoon/components/preferences/moz.build | 2 +- .../palemoon/components/shell/moz.build | 4 - .../components/shell/nsIMacShellService.idl | 15 - .../components/shell/nsMacShellService.cpp | 434 --- .../components/shell/nsMacShellService.h | 32 - application/palemoon/themes/moz.build | 4 +- .../palemoon/themes/osx/Geolocation-16.png | Bin 704 -> 0 bytes .../palemoon/themes/osx/Geolocation-64.png | Bin 8424 -> 0 bytes application/palemoon/themes/osx/Info.png | Bin 641 -> 0 bytes .../palemoon/themes/osx/KUI-background.png | Bin 222 -> 0 bytes application/palemoon/themes/osx/KUI-close.png | Bin 393 -> 0 bytes application/palemoon/themes/osx/Makefile.in | 7 - .../palemoon/themes/osx/Privacy-16.png | Bin 800 -> 0 bytes .../palemoon/themes/osx/Privacy-32.png | Bin 1995 -> 0 bytes .../palemoon/themes/osx/Privacy-48.png | Bin 3884 -> 0 bytes .../palemoon/themes/osx/Privacy-64.png | Bin 8140 -> 0 bytes application/palemoon/themes/osx/Search.png | Bin 437 -> 0 bytes application/palemoon/themes/osx/Secure24.png | Bin 1098 -> 0 bytes .../palemoon/themes/osx/Toolbar-inverted.png | Bin 7101 -> 0 bytes .../palemoon/themes/osx/Toolbar-inverted.svg | 302 -- application/palemoon/themes/osx/Toolbar.png | Bin 16015 -> 0 bytes application/palemoon/themes/osx/Toolbar.svg | 1356 -------- .../palemoon/themes/osx/aboutCertError.css | 73 - .../aboutCertError_sectionCollapsed-rtl.png | Bin 791 -> 0 bytes .../osx/aboutCertError_sectionCollapsed.png | Bin 776 -> 0 bytes .../osx/aboutCertError_sectionExpanded.png | Bin 767 -> 0 bytes .../themes/osx/aboutPrivateBrowsing.css | 47 - .../themes/osx/aboutSessionRestore.css | 73 - .../palemoon/themes/osx/aboutSyncTabs.css | 101 - .../palemoon/themes/osx/actionicon-tab.png | Bin 425 -> 0 bytes .../palemoon/themes/osx/autocomplete.css | 198 -- application/palemoon/themes/osx/browser.css | 2884 ----------------- .../osx/click-to-play-warning-stripes.png | Bin 1563 -> 0 bytes .../themes/osx/communicator/communicator.css | 6 - .../palemoon/themes/osx/communicator/jar.mn | 7 - .../themes/osx/communicator/moz.build | 6 - .../osx/downloads/allDownloadsViewOverlay.css | 146 - .../palemoon/themes/osx/downloads/buttons.png | Bin 6881 -> 0 bytes .../downloads/contentAreaDownloadsView.css | 22 - .../download-notification-finish.png | Bin 3755 -> 0 bytes .../downloads/download-notification-start.png | Bin 3166 -> 0 bytes .../themes/osx/downloads/download-summary.png | Bin 741 -> 0 bytes .../themes/osx/downloads/downloads.css | 396 --- .../palemoon/themes/osx/engineManager.css | 16 - .../themes/osx/feeds/feed-icons-16.png | Bin 2187 -> 0 bytes .../palemoon/themes/osx/feeds/feedIcon.png | Bin 1833 -> 0 bytes .../palemoon/themes/osx/feeds/feedIcon16.png | Bin 791 -> 0 bytes .../themes/osx/feeds/subscribe-ui.css | 29 - .../palemoon/themes/osx/feeds/subscribe.css | 159 - application/palemoon/themes/osx/icon.png | Bin 2185 -> 0 bytes .../themes/osx/identity-icons-generic.png | Bin 965 -> 0 bytes .../themes/osx/identity-icons-https-ev.png | Bin 708 -> 0 bytes .../osx/identity-icons-https-mixed-active.png | Bin 984 -> 0 bytes .../themes/osx/identity-icons-https.png | Bin 672 -> 0 bytes application/palemoon/themes/osx/identity.png | Bin 10508 -> 0 bytes .../palemoon/themes/osx/imagedocument.png | Bin 2185 -> 0 bytes application/palemoon/themes/osx/jar.mn | 181 -- .../themes/osx/keyhole-forward-mask.svg | 15 - .../palemoon/themes/osx/livemark-folder.png | Bin 680 -> 0 bytes application/palemoon/themes/osx/menu-back.png | Bin 341 -> 0 bytes .../palemoon/themes/osx/menu-forward.png | Bin 343 -> 0 bytes .../themes/osx/mixed-content-blocked-16.png | Bin 346 -> 0 bytes .../themes/osx/mixed-content-blocked-64.png | Bin 2063 -> 0 bytes application/palemoon/themes/osx/monitor.png | Bin 6217 -> 0 bytes .../palemoon/themes/osx/monitor_16-10.png | Bin 6787 -> 0 bytes application/palemoon/themes/osx/moz.build | 8 - .../palemoon/themes/osx/newtab/newTab.css | 36 - .../palemoon/themes/osx/page-livemarks.png | Bin 683 -> 0 bytes .../palemoon/themes/osx/page-livemarks@2x.png | Bin 1167 -> 0 bytes application/palemoon/themes/osx/pageInfo.css | 258 -- application/palemoon/themes/osx/pageInfo.png | Bin 8118 -> 0 bytes .../themes/osx/panel-expander-closed.png | Bin 155 -> 0 bytes .../themes/osx/panel-expander-closed@2x.png | Bin 362 -> 0 bytes .../themes/osx/panel-expander-open.png | Bin 155 -> 0 bytes .../themes/osx/panel-expander-open@2x.png | Bin 356 -> 0 bytes .../palemoon/themes/osx/panel-plus-sign.png | Bin 212 -> 0 bytes .../osx/permissions/aboutPermissions.css | 153 - .../themes/osx/places/allBookmarks.png | Bin 673 -> 0 bytes .../palemoon/themes/osx/places/bookmark.png | Bin 1779 -> 0 bytes .../themes/osx/places/bookmarksMenu.png | Bin 353 -> 0 bytes .../themes/osx/places/bookmarksToolbar.png | Bin 524 -> 0 bytes .../themes/osx/places/bookmarksToolbar@2x.png | Bin 1179 -> 0 bytes .../palemoon/themes/osx/places/calendar.png | Bin 614 -> 0 bytes .../palemoon/themes/osx/places/downloads.png | Bin 678 -> 0 bytes .../themes/osx/places/editBookmark.png | Bin 1642 -> 0 bytes .../themes/osx/places/editBookmarkOverlay.css | 105 - .../osx/places/expander-closed-active.png | Bin 1329 -> 0 bytes .../themes/osx/places/expander-closed.png | Bin 837 -> 0 bytes .../osx/places/expander-open-active.png | Bin 1329 -> 0 bytes .../themes/osx/places/expander-open.png | Bin 818 -> 0 bytes .../themes/osx/places/folderDropArrow.png | Bin 201 -> 0 bytes .../themes/osx/places/folderDropArrow@2x.png | Bin 443 -> 0 bytes .../palemoon/themes/osx/places/history.png | Bin 843 -> 0 bytes .../palemoon/themes/osx/places/history@2x.png | Bin 1872 -> 0 bytes .../themes/osx/places/libraryToolbar.png | Bin 2217 -> 0 bytes .../themes/osx/places/libraryToolbar.svg | 41 - .../themes/osx/places/livemark-item.png | Bin 863 -> 0 bytes .../palemoon/themes/osx/places/organizer.css | 136 - .../palemoon/themes/osx/places/places.css | 146 - .../palemoon/themes/osx/places/query.png | Bin 549 -> 0 bytes .../palemoon/themes/osx/places/query@2x.png | Bin 1055 -> 0 bytes .../palemoon/themes/osx/places/starred48.png | Bin 1785 -> 0 bytes .../palemoon/themes/osx/places/tag.png | Bin 789 -> 0 bytes .../palemoon/themes/osx/places/tag@2x.png | Bin 1593 -> 0 bytes .../themes/osx/places/toolbarDropMarker.png | Bin 302 -> 0 bytes .../themes/osx/places/unfiledBookmarks.png | Bin 586 -> 0 bytes .../themes/osx/places/unfiledBookmarks@2x.png | Bin 1289 -> 0 bytes .../themes/osx/places/unsortedBookmarks.png | Bin 780 -> 0 bytes .../themes/osx/places/unstarred48.png | Bin 818 -> 0 bytes .../palemoon/themes/osx/pointerLock-16.png | Bin 249 -> 0 bytes .../palemoon/themes/osx/pointerLock-64.png | Bin 1119 -> 0 bytes .../themes/osx/preferences/Options-sync.png | Bin 3585 -> 0 bytes .../themes/osx/preferences/Options.png | Bin 9077 -> 0 bytes .../themes/osx/preferences/alwaysAsk.png | Bin 446 -> 0 bytes .../themes/osx/preferences/application.png | Bin 441 -> 0 bytes .../themes/osx/preferences/applications.css | 64 - .../palemoon/themes/osx/preferences/mail.png | Bin 630 -> 0 bytes .../themes/osx/preferences/preferences.css | 142 - .../themes/osx/preferences/saveFile.png | Bin 791 -> 0 bytes .../themes/osx/privatebrowsing-dark.png | Bin 1355 -> 0 bytes .../themes/osx/privatebrowsing-light.png | Bin 696 -> 0 bytes .../themes/osx/privatebrowsing-mask.png | Bin 1074 -> 0 bytes .../themes/osx/privatebrowsing-mask@2x.png | Bin 2639 -> 0 bytes .../palemoon/themes/osx/reload-stop-go.png | Bin 1945 -> 0 bytes .../palemoon/themes/osx/sanitizeDialog.css | 93 - .../themes/osx/searchbar-dropdown-arrow.png | Bin 509 -> 0 bytes application/palemoon/themes/osx/searchbar.css | 79 - .../themes/osx/setDesktopBackground.css | 18 - application/palemoon/themes/osx/shared.inc | 6 - .../palemoon/themes/osx/slowStartup-16.png | Bin 512 -> 0 bytes .../palemoon/themes/osx/statusbar/overlay.css | 108 - .../palemoon/themes/osx/statusbar/prefs.css | 13 - application/palemoon/themes/osx/sync-128.png | Bin 20229 -> 0 bytes application/palemoon/themes/osx/sync-16.png | Bin 1847 -> 0 bytes application/palemoon/themes/osx/sync-32.png | Bin 3384 -> 0 bytes application/palemoon/themes/osx/sync-bg.png | Bin 21309 -> 0 bytes .../palemoon/themes/osx/sync-desktopIcon.png | Bin 291 -> 0 bytes .../palemoon/themes/osx/sync-mobileIcon.png | Bin 352 -> 0 bytes .../palemoon/themes/osx/sync-throbber.png | Bin 10362 -> 0 bytes .../palemoon/themes/osx/syncCommon.css | 49 - .../palemoon/themes/osx/syncProgress.css | 46 - application/palemoon/themes/osx/syncQuota.css | 26 - application/palemoon/themes/osx/syncSetup.css | 132 - .../osx/tabbrowser/alltabs-inverted.png | Bin 469 -> 0 bytes .../themes/osx/tabbrowser/alltabs.png | Bin 584 -> 0 bytes .../themes/osx/tabbrowser/connecting.png | Bin 8540 -> 0 bytes .../themes/osx/tabbrowser/loading.png | Bin 10727 -> 0 bytes .../themes/osx/tabbrowser/newtab-inverted.png | Bin 247 -> 0 bytes .../palemoon/themes/osx/tabbrowser/newtab.png | Bin 237 -> 0 bytes .../tabbrowser/tab-arrow-left-inverted.png | Bin 250 -> 0 bytes .../themes/osx/tabbrowser/tab-arrow-left.png | Bin 368 -> 0 bytes .../osx/tabbrowser/tab-overflow-border.png | Bin 193 -> 0 bytes .../osx/tabbrowser/tabDragIndicator.png | Bin 3117 -> 0 bytes .../toolbarbutton-dropdown-arrow-inverted.png | Bin 221 -> 0 bytes .../osx/toolbarbutton-dropdown-arrow.png | Bin 287 -> 0 bytes .../palemoon/themes/osx/urlbar-arrow.png | Bin 305 -> 0 bytes .../themes/osx/urlbar-history-dropmarker.png | Bin 480 -> 0 bytes .../themes/osx/urlbar-popup-blocked.png | Bin 745 -> 0 bytes .../themes/osx/web-notifications-icon.svg | 15 - .../themes/osx/web-notifications-tray.svg | 23 - .../themes/osx/webRTC-shareDevice-16.png | Bin 233 -> 0 bytes .../themes/osx/webRTC-shareDevice-64.png | Bin 1097 -> 0 bytes .../themes/osx/webRTC-sharingDevice-16.png | Bin 404 -> 0 bytes 170 files changed, 5 insertions(+), 8224 deletions(-) delete mode 100644 application/palemoon/branding/unofficial/disk.icns delete mode 100644 application/palemoon/branding/unofficial/document.icns delete mode 100644 application/palemoon/branding/unofficial/dsstore delete mode 100644 application/palemoon/branding/unofficial/firefox.icns delete mode 100644 application/palemoon/components/shell/nsIMacShellService.idl delete mode 100644 application/palemoon/components/shell/nsMacShellService.cpp delete mode 100644 application/palemoon/components/shell/nsMacShellService.h delete mode 100644 application/palemoon/themes/osx/Geolocation-16.png delete mode 100644 application/palemoon/themes/osx/Geolocation-64.png delete mode 100644 application/palemoon/themes/osx/Info.png delete mode 100644 application/palemoon/themes/osx/KUI-background.png delete mode 100644 application/palemoon/themes/osx/KUI-close.png delete mode 100644 application/palemoon/themes/osx/Makefile.in delete mode 100644 application/palemoon/themes/osx/Privacy-16.png delete mode 100644 application/palemoon/themes/osx/Privacy-32.png delete mode 100644 application/palemoon/themes/osx/Privacy-48.png delete mode 100644 application/palemoon/themes/osx/Privacy-64.png delete mode 100644 application/palemoon/themes/osx/Search.png delete mode 100644 application/palemoon/themes/osx/Secure24.png delete mode 100644 application/palemoon/themes/osx/Toolbar-inverted.png delete mode 100644 application/palemoon/themes/osx/Toolbar-inverted.svg delete mode 100644 application/palemoon/themes/osx/Toolbar.png delete mode 100644 application/palemoon/themes/osx/Toolbar.svg delete mode 100644 application/palemoon/themes/osx/aboutCertError.css delete mode 100644 application/palemoon/themes/osx/aboutCertError_sectionCollapsed-rtl.png delete mode 100644 application/palemoon/themes/osx/aboutCertError_sectionCollapsed.png delete mode 100644 application/palemoon/themes/osx/aboutCertError_sectionExpanded.png delete mode 100644 application/palemoon/themes/osx/aboutPrivateBrowsing.css delete mode 100644 application/palemoon/themes/osx/aboutSessionRestore.css delete mode 100644 application/palemoon/themes/osx/aboutSyncTabs.css delete mode 100644 application/palemoon/themes/osx/actionicon-tab.png delete mode 100644 application/palemoon/themes/osx/autocomplete.css delete mode 100644 application/palemoon/themes/osx/browser.css delete mode 100644 application/palemoon/themes/osx/click-to-play-warning-stripes.png delete mode 100644 application/palemoon/themes/osx/communicator/communicator.css delete mode 100644 application/palemoon/themes/osx/communicator/jar.mn delete mode 100644 application/palemoon/themes/osx/communicator/moz.build delete mode 100644 application/palemoon/themes/osx/downloads/allDownloadsViewOverlay.css delete mode 100644 application/palemoon/themes/osx/downloads/buttons.png delete mode 100644 application/palemoon/themes/osx/downloads/contentAreaDownloadsView.css delete mode 100644 application/palemoon/themes/osx/downloads/download-notification-finish.png delete mode 100644 application/palemoon/themes/osx/downloads/download-notification-start.png delete mode 100644 application/palemoon/themes/osx/downloads/download-summary.png delete mode 100644 application/palemoon/themes/osx/downloads/downloads.css delete mode 100644 application/palemoon/themes/osx/engineManager.css delete mode 100644 application/palemoon/themes/osx/feeds/feed-icons-16.png delete mode 100644 application/palemoon/themes/osx/feeds/feedIcon.png delete mode 100644 application/palemoon/themes/osx/feeds/feedIcon16.png delete mode 100644 application/palemoon/themes/osx/feeds/subscribe-ui.css delete mode 100644 application/palemoon/themes/osx/feeds/subscribe.css delete mode 100644 application/palemoon/themes/osx/icon.png delete mode 100644 application/palemoon/themes/osx/identity-icons-generic.png delete mode 100644 application/palemoon/themes/osx/identity-icons-https-ev.png delete mode 100644 application/palemoon/themes/osx/identity-icons-https-mixed-active.png delete mode 100644 application/palemoon/themes/osx/identity-icons-https.png delete mode 100644 application/palemoon/themes/osx/identity.png delete mode 100644 application/palemoon/themes/osx/imagedocument.png delete mode 100644 application/palemoon/themes/osx/jar.mn delete mode 100644 application/palemoon/themes/osx/keyhole-forward-mask.svg delete mode 100644 application/palemoon/themes/osx/livemark-folder.png delete mode 100644 application/palemoon/themes/osx/menu-back.png delete mode 100644 application/palemoon/themes/osx/menu-forward.png delete mode 100644 application/palemoon/themes/osx/mixed-content-blocked-16.png delete mode 100644 application/palemoon/themes/osx/mixed-content-blocked-64.png delete mode 100644 application/palemoon/themes/osx/monitor.png delete mode 100644 application/palemoon/themes/osx/monitor_16-10.png delete mode 100644 application/palemoon/themes/osx/moz.build delete mode 100644 application/palemoon/themes/osx/newtab/newTab.css delete mode 100644 application/palemoon/themes/osx/page-livemarks.png delete mode 100644 application/palemoon/themes/osx/page-livemarks@2x.png delete mode 100644 application/palemoon/themes/osx/pageInfo.css delete mode 100644 application/palemoon/themes/osx/pageInfo.png delete mode 100644 application/palemoon/themes/osx/panel-expander-closed.png delete mode 100644 application/palemoon/themes/osx/panel-expander-closed@2x.png delete mode 100644 application/palemoon/themes/osx/panel-expander-open.png delete mode 100644 application/palemoon/themes/osx/panel-expander-open@2x.png delete mode 100644 application/palemoon/themes/osx/panel-plus-sign.png delete mode 100644 application/palemoon/themes/osx/permissions/aboutPermissions.css delete mode 100644 application/palemoon/themes/osx/places/allBookmarks.png delete mode 100644 application/palemoon/themes/osx/places/bookmark.png delete mode 100644 application/palemoon/themes/osx/places/bookmarksMenu.png delete mode 100644 application/palemoon/themes/osx/places/bookmarksToolbar.png delete mode 100644 application/palemoon/themes/osx/places/bookmarksToolbar@2x.png delete mode 100644 application/palemoon/themes/osx/places/calendar.png delete mode 100644 application/palemoon/themes/osx/places/downloads.png delete mode 100644 application/palemoon/themes/osx/places/editBookmark.png delete mode 100644 application/palemoon/themes/osx/places/editBookmarkOverlay.css delete mode 100644 application/palemoon/themes/osx/places/expander-closed-active.png delete mode 100644 application/palemoon/themes/osx/places/expander-closed.png delete mode 100644 application/palemoon/themes/osx/places/expander-open-active.png delete mode 100644 application/palemoon/themes/osx/places/expander-open.png delete mode 100644 application/palemoon/themes/osx/places/folderDropArrow.png delete mode 100644 application/palemoon/themes/osx/places/folderDropArrow@2x.png delete mode 100644 application/palemoon/themes/osx/places/history.png delete mode 100644 application/palemoon/themes/osx/places/history@2x.png delete mode 100644 application/palemoon/themes/osx/places/libraryToolbar.png delete mode 100644 application/palemoon/themes/osx/places/libraryToolbar.svg delete mode 100644 application/palemoon/themes/osx/places/livemark-item.png delete mode 100644 application/palemoon/themes/osx/places/organizer.css delete mode 100644 application/palemoon/themes/osx/places/places.css delete mode 100644 application/palemoon/themes/osx/places/query.png delete mode 100644 application/palemoon/themes/osx/places/query@2x.png delete mode 100644 application/palemoon/themes/osx/places/starred48.png delete mode 100644 application/palemoon/themes/osx/places/tag.png delete mode 100644 application/palemoon/themes/osx/places/tag@2x.png delete mode 100644 application/palemoon/themes/osx/places/toolbarDropMarker.png delete mode 100644 application/palemoon/themes/osx/places/unfiledBookmarks.png delete mode 100644 application/palemoon/themes/osx/places/unfiledBookmarks@2x.png delete mode 100644 application/palemoon/themes/osx/places/unsortedBookmarks.png delete mode 100644 application/palemoon/themes/osx/places/unstarred48.png delete mode 100644 application/palemoon/themes/osx/pointerLock-16.png delete mode 100644 application/palemoon/themes/osx/pointerLock-64.png delete mode 100644 application/palemoon/themes/osx/preferences/Options-sync.png delete mode 100644 application/palemoon/themes/osx/preferences/Options.png delete mode 100644 application/palemoon/themes/osx/preferences/alwaysAsk.png delete mode 100644 application/palemoon/themes/osx/preferences/application.png delete mode 100644 application/palemoon/themes/osx/preferences/applications.css delete mode 100644 application/palemoon/themes/osx/preferences/mail.png delete mode 100644 application/palemoon/themes/osx/preferences/preferences.css delete mode 100644 application/palemoon/themes/osx/preferences/saveFile.png delete mode 100644 application/palemoon/themes/osx/privatebrowsing-dark.png delete mode 100644 application/palemoon/themes/osx/privatebrowsing-light.png delete mode 100644 application/palemoon/themes/osx/privatebrowsing-mask.png delete mode 100644 application/palemoon/themes/osx/privatebrowsing-mask@2x.png delete mode 100644 application/palemoon/themes/osx/reload-stop-go.png delete mode 100644 application/palemoon/themes/osx/sanitizeDialog.css delete mode 100644 application/palemoon/themes/osx/searchbar-dropdown-arrow.png delete mode 100644 application/palemoon/themes/osx/searchbar.css delete mode 100644 application/palemoon/themes/osx/setDesktopBackground.css delete mode 100644 application/palemoon/themes/osx/shared.inc delete mode 100644 application/palemoon/themes/osx/slowStartup-16.png delete mode 100644 application/palemoon/themes/osx/statusbar/overlay.css delete mode 100644 application/palemoon/themes/osx/statusbar/prefs.css delete mode 100644 application/palemoon/themes/osx/sync-128.png delete mode 100644 application/palemoon/themes/osx/sync-16.png delete mode 100644 application/palemoon/themes/osx/sync-32.png delete mode 100644 application/palemoon/themes/osx/sync-bg.png delete mode 100644 application/palemoon/themes/osx/sync-desktopIcon.png delete mode 100644 application/palemoon/themes/osx/sync-mobileIcon.png delete mode 100644 application/palemoon/themes/osx/sync-throbber.png delete mode 100644 application/palemoon/themes/osx/syncCommon.css delete mode 100644 application/palemoon/themes/osx/syncProgress.css delete mode 100644 application/palemoon/themes/osx/syncQuota.css delete mode 100644 application/palemoon/themes/osx/syncSetup.css delete mode 100644 application/palemoon/themes/osx/tabbrowser/alltabs-inverted.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/alltabs.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/connecting.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/loading.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/newtab-inverted.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/newtab.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/tab-arrow-left-inverted.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/tab-arrow-left.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/tab-overflow-border.png delete mode 100644 application/palemoon/themes/osx/tabbrowser/tabDragIndicator.png delete mode 100644 application/palemoon/themes/osx/toolbarbutton-dropdown-arrow-inverted.png delete mode 100644 application/palemoon/themes/osx/toolbarbutton-dropdown-arrow.png delete mode 100644 application/palemoon/themes/osx/urlbar-arrow.png delete mode 100644 application/palemoon/themes/osx/urlbar-history-dropmarker.png delete mode 100644 application/palemoon/themes/osx/urlbar-popup-blocked.png delete mode 100644 application/palemoon/themes/osx/web-notifications-icon.svg delete mode 100644 application/palemoon/themes/osx/web-notifications-tray.svg delete mode 100644 application/palemoon/themes/osx/webRTC-shareDevice-16.png delete mode 100644 application/palemoon/themes/osx/webRTC-shareDevice-64.png delete mode 100644 application/palemoon/themes/osx/webRTC-sharingDevice-16.png diff --git a/application/palemoon/base/moz.build b/application/palemoon/base/moz.build index dfa89c7d30..c1470f25c9 100644 --- a/application/palemoon/base/moz.build +++ b/application/palemoon/base/moz.build @@ -6,11 +6,9 @@ DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] DEFINES['APP_LICENSE_BLOCK'] = '%s/content/overrides/app-license.html' % SRCDIR -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'): +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['HAVE_SHELL_SERVICE'] = 1 DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1 - -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1 JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file diff --git a/application/palemoon/branding/shared/branding.mozbuild b/application/palemoon/branding/shared/branding.mozbuild index 284520add8..e253620d27 100644 --- a/application/palemoon/branding/shared/branding.mozbuild +++ b/application/palemoon/branding/shared/branding.mozbuild @@ -30,14 +30,6 @@ def ApplicationBranding(): 'wizHeaderRTL.bmp', 'wizWatermark.bmp', ] - elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - BRANDING_FILES += [ - '../shared/background.png', - 'disk.icns', - 'document.icns', - 'dsstore', - 'firefox.icns', - ] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: BRANDING_FILES += [ 'default16.png', diff --git a/application/palemoon/branding/unofficial/disk.icns b/application/palemoon/branding/unofficial/disk.icns deleted file mode 100644 index e97e490585226e69da9cfff20b3b4db2384d963e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39250 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 diff --git a/application/palemoon/branding/unofficial/document.icns b/application/palemoon/branding/unofficial/document.icns deleted file mode 100644 index dd5f7aa8924682fa0bfde8072f91db79b87bf73c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12451 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 DEgNTD diff --git a/application/palemoon/branding/unofficial/firefox.icns b/application/palemoon/branding/unofficial/firefox.icns deleted file mode 100644 index 117ddb195258602ac6214320942f55ce1af385c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12079 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 J-v+*v{s+LxEp7k+ diff --git a/application/palemoon/components/build/moz.build b/application/palemoon/components/build/moz.build index ebacbec8f3..26f2d14237 100644 --- a/application/palemoon/components/build/moz.build +++ b/application/palemoon/components/build/moz.build @@ -29,7 +29,6 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'netapi32.dll', ] -# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code) -# GTK2: Need to link with glib for GNOME shell service -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'): +# GTK: Need to link with glib for GNOME shell service +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): OS_LIBS += CONFIG['TK_LIBS'] diff --git a/application/palemoon/components/preferences/moz.build b/application/palemoon/components/preferences/moz.build index 49b3c3d766..c888607f0f 100644 --- a/application/palemoon/components/preferences/moz.build +++ b/application/palemoon/components/preferences/moz.build @@ -7,7 +7,7 @@ for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'): DEFINES[var] = CONFIG[var] -if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'): +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['HAVE_SHELL_SERVICE'] = 1 JAR_MANIFESTS += ['jar.mn'] \ No newline at end of file diff --git a/application/palemoon/components/shell/moz.build b/application/palemoon/components/shell/moz.build index 6e086f96d0..de34f17fb8 100644 --- a/application/palemoon/components/shell/moz.build +++ b/application/palemoon/components/shell/moz.build @@ -9,8 +9,6 @@ XPIDL_SOURCES += ['nsIShellService.idl'] if CONFIG['OS_ARCH'] == 'WINNT': XPIDL_SOURCES += ['nsIWindowsShellService.idl'] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - XPIDL_SOURCES += ['nsIMacShellService.idl'] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: XPIDL_SOURCES += ['nsIGNOMEShellService.idl'] @@ -18,8 +16,6 @@ XPIDL_MODULE = 'shellservice' if CONFIG['OS_ARCH'] == 'WINNT': SOURCES += ['nsWindowsShellService.cpp'] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - SOURCES += ['nsMacShellService.cpp'] elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: SOURCES += ['nsGNOMEShellService.cpp'] diff --git a/application/palemoon/components/shell/nsIMacShellService.idl b/application/palemoon/components/shell/nsIMacShellService.idl deleted file mode 100644 index 6a532bbd0b..0000000000 --- a/application/palemoon/components/shell/nsIMacShellService.idl +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsIShellService.idl" - -[scriptable, uuid(387fdc80-0077-4b60-a0d9-d9e80a83ba64)] -interface nsIMacShellService : nsIShellService -{ - const long APPLICATION_KEYCHAIN_ACCESS = 2; - const long APPLICATION_NETWORK = 3; - const long APPLICATION_DESKTOP = 4; -}; - diff --git a/application/palemoon/components/shell/nsMacShellService.cpp b/application/palemoon/components/shell/nsMacShellService.cpp deleted file mode 100644 index d8d64039d3..0000000000 --- a/application/palemoon/components/shell/nsMacShellService.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "nsDirectoryServiceDefs.h" -#include "nsIDOMElement.h" -#include "nsIDOMHTMLImageElement.h" -#include "nsIImageLoadingContent.h" -#include "nsIDocument.h" -#include "nsIContent.h" -#include "nsILocalFileMac.h" -#include "nsIObserverService.h" -#include "nsIPrefService.h" -#include "nsIServiceManager.h" -#include "nsIStringBundle.h" -#include "nsIURL.h" -#include "nsIWebBrowserPersist.h" -#include "nsMacShellService.h" -#include "nsIProperties.h" -#include "nsServiceManagerUtils.h" -#include "nsShellService.h" -#include "nsStringAPI.h" -#include "nsIDocShell.h" -#include "nsILoadContext.h" - -#include -#include - -#define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane") -#define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane") - -#define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari" - -NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener) - -NS_IMETHODIMP -nsMacShellService::IsDefaultBrowser(bool aStartupCheck, - bool aForAllTypes, - bool* aIsDefaultBrowser) -{ - *aIsDefaultBrowser = false; - - CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle()); - if (!firefoxID) { - // CFBundleGetIdentifier is expected to return nullptr only if the specified - // bundle doesn't have a bundle identifier in its plist. In this case, that - // means a failure, since our bundle does have an identifier. - return NS_ERROR_FAILURE; - } - - // Get the default http handler's bundle ID (or nullptr if it has not been - // explicitly set) - CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http")); - if (defaultBrowserID) { - *aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo; - ::CFRelease(defaultBrowserID); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers) -{ - // Note: We don't support aForAllUsers on Mac OS X. - - CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle()); - if (!firefoxID) { - return NS_ERROR_FAILURE; - } - - if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - - if (aClaimAllTypes) { - if (::LSSetDefaultHandlerForURLScheme(CFSTR("ftp"), firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll, firefoxID) != noErr) { - return NS_ERROR_FAILURE; - } - } - - nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) { - (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true); - // Reset the number of times the dialog should be shown - // before it is silenced. - (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::SetDesktopBackground(nsIDOMElement* aElement, - int32_t aPosition) -{ - // Note: We don't support aPosition on OS X. - - // Get the image URI: - nsresult rv; - nsCOMPtr imageContent = do_QueryInterface(aElement, - &rv); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr imageURI; - rv = imageContent->GetCurrentURI(getter_AddRefs(imageURI)); - NS_ENSURE_SUCCESS(rv, rv); - - // We need the referer URI for nsIWebBrowserPersist::saveURI - nsCOMPtr content = do_QueryInterface(aElement, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsIURI *docURI = content->OwnerDoc()->GetDocumentURI(); - if (!docURI) - return NS_ERROR_FAILURE; - - // Get the desired image file name - nsCOMPtr imageURL(do_QueryInterface(imageURI)); - if (!imageURL) { - // XXXmano (bug 300293): Non-URL images (e.g. the data: protocol) are not - // yet supported. What filename should we take here? - return NS_ERROR_NOT_IMPLEMENTED; - } - - nsAutoCString fileName; - imageURL->GetFileName(fileName); - nsCOMPtr fileLocator - (do_GetService("@mozilla.org/file/directory_service;1", &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - // Get the current user's "Pictures" folder (That's ~/Pictures): - fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), - getter_AddRefs(mBackgroundFile)); - if (!mBackgroundFile) - return NS_ERROR_OUT_OF_MEMORY; - - nsAutoString fileNameUnicode; - CopyUTF8toUTF16(fileName, fileNameUnicode); - - // and add the imgage file name itself: - mBackgroundFile->Append(fileNameUnicode); - - // Download the image; the desktop background will be set in OnStateChange() - nsCOMPtr wbp - (do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | - nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES | - nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE; - - wbp->SetPersistFlags(flags); - wbp->SetProgressListener(this); - - nsCOMPtr loadContext; - nsCOMPtr container = content->OwnerDoc()->GetContainer(); - nsCOMPtr docShell = do_QueryInterface(container); - if (docShell) { - loadContext = do_QueryInterface(docShell); - } - - return wbp->SaveURI(imageURI, nullptr, - docURI, content->OwnerDoc()->GetReferrerPolicy(), - nullptr, nullptr, - mBackgroundFile, loadContext); -} - -NS_IMETHODIMP -nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - int32_t aCurSelfProgress, - int32_t aMaxSelfProgress, - int32_t aCurTotalProgress, - int32_t aMaxTotalProgress) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - nsIURI* aLocation, - uint32_t aFlags) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - nsresult aStatus, - const char16_t* aMessage) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - uint32_t aState) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - uint32_t aStateFlags, - nsresult aStatus) -{ - if (aStateFlags & STATE_STOP) { - nsCOMPtr os(do_GetService("@mozilla.org/observer-service;1")); - if (os) - os->NotifyObservers(nullptr, "shell:desktop-background-changed", nullptr); - - bool exists = false; - mBackgroundFile->Exists(&exists); - if (!exists) - return NS_OK; - - nsAutoCString nativePath; - mBackgroundFile->GetNativePath(nativePath); - - AEDesc tAEDesc = { typeNull, nil }; - OSErr err = noErr; - AliasHandle aliasHandle = nil; - FSRef pictureRef; - OSStatus status; - - // Convert the path into a FSRef - status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef, - nullptr); - if (status == noErr) { - err = ::FSNewAlias(nil, &pictureRef, &aliasHandle); - if (err == noErr && aliasHandle == nil) - err = paramErr; - - if (err == noErr) { - // We need the descriptor (based on the picture file reference) - // for the 'Set Desktop Picture' apple event. - char handleState = ::HGetState((Handle)aliasHandle); - ::HLock((Handle)aliasHandle); - err = ::AECreateDesc(typeAlias, *aliasHandle, - GetHandleSize((Handle)aliasHandle), &tAEDesc); - // unlock the alias handler - ::HSetState((Handle)aliasHandle, handleState); - ::DisposeHandle((Handle)aliasHandle); - } - if (err == noErr) { - AppleEvent tAppleEvent; - OSType sig = 'MACS'; - AEBuildError tAEBuildError; - // Create a 'Set Desktop Pictue' Apple Event - err = ::AEBuildAppleEvent(kAECoreSuite, kAESetData, typeApplSignature, - &sig, sizeof(OSType), kAutoGenerateReturnID, - kAnyTransactionID, &tAppleEvent, &tAEBuildError, - "'----':'obj '{want:type (prop),form:prop" \ - ",seld:type('dpic'),from:'null'()},data:(@)", - &tAEDesc); - if (err == noErr) { - AppleEvent reply = { typeNull, nil }; - // Sent the event we built, the reply event isn't necessary - err = ::AESend(&tAppleEvent, &reply, kAENoReply, kAENormalPriority, - kNoTimeOut, nil, nil); - ::AEDisposeDesc(&tAppleEvent); - } - } - } - } - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::OpenApplication(int32_t aApplication) -{ - nsresult rv = NS_OK; - CFURLRef appURL = nil; - OSStatus err = noErr; - - switch (aApplication) { - case nsIShellService::APPLICATION_MAIL: - { - CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault, - CFSTR("mailto:"), nullptr); - err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL); - ::CFRelease(tempURL); - } - break; - case nsIShellService::APPLICATION_NEWS: - { - CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault, - CFSTR("news:"), nullptr); - err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL); - ::CFRelease(tempURL); - } - break; - case nsIMacShellService::APPLICATION_KEYCHAIN_ACCESS: - err = ::LSGetApplicationForInfo('APPL', 'kcmr', nullptr, kLSRolesAll, - nullptr, &appURL); - break; - case nsIMacShellService::APPLICATION_NETWORK: - { - nsCOMPtr lf; - rv = NS_NewNativeLocalFile(NETWORK_PREFPANE, true, getter_AddRefs(lf)); - NS_ENSURE_SUCCESS(rv, rv); - bool exists; - lf->Exists(&exists); - if (!exists) - return NS_ERROR_FILE_NOT_FOUND; - return lf->Launch(); - } - case nsIMacShellService::APPLICATION_DESKTOP: - { - nsCOMPtr lf; - rv = NS_NewNativeLocalFile(DESKTOP_PREFPANE, true, getter_AddRefs(lf)); - NS_ENSURE_SUCCESS(rv, rv); - bool exists; - lf->Exists(&exists); - if (!exists) - return NS_ERROR_FILE_NOT_FOUND; - return lf->Launch(); - } - } - - if (appURL && err == noErr) { - err = ::LSOpenCFURLRef(appURL, nullptr); - rv = err != noErr ? NS_ERROR_FAILURE : NS_OK; - - ::CFRelease(appURL); - } - - return rv; -} - -NS_IMETHODIMP -nsMacShellService::GetDesktopBackgroundColor(uint32_t *aColor) -{ - // This method and |SetDesktopBackgroundColor| has no meaning on Mac OS X. - // The mac desktop preferences UI uses pictures for the few solid colors it - // supports. - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -nsMacShellService::SetDesktopBackgroundColor(uint32_t aColor) -{ - // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X. - // The mac desktop preferences UI uses pictures for the few solid colors it - // supports. - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -nsMacShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI) -{ - nsCOMPtr lfm(do_QueryInterface(aApplication)); - CFURLRef appURL; - nsresult rv = lfm->GetCFURL(&appURL); - if (NS_FAILED(rv)) - return rv; - - const nsCString spec(aURI); - const UInt8* uriString = (const UInt8*)spec.get(); - CFURLRef uri = ::CFURLCreateWithBytes(nullptr, uriString, aURI.Length(), - kCFStringEncodingUTF8, nullptr); - if (!uri) - return NS_ERROR_OUT_OF_MEMORY; - - CFArrayRef uris = ::CFArrayCreate(nullptr, (const void**)&uri, 1, nullptr); - if (!uris) { - ::CFRelease(uri); - return NS_ERROR_OUT_OF_MEMORY; - } - - LSLaunchURLSpec launchSpec; - launchSpec.appURL = appURL; - launchSpec.itemURLs = uris; - launchSpec.passThruParams = nullptr; - launchSpec.launchFlags = kLSLaunchDefaults; - launchSpec.asyncRefCon = nullptr; - - OSErr err = ::LSOpenFromURLSpec(&launchSpec, nullptr); - - ::CFRelease(uris); - ::CFRelease(uri); - - return err != noErr ? NS_ERROR_FAILURE : NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::GetDefaultFeedReader(nsIFile** _retval) -{ - nsresult rv = NS_ERROR_FAILURE; - *_retval = nullptr; - - CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed")); - if (!defaultHandlerID) { - defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault, - SAFARI_BUNDLE_IDENTIFIER, - kCFStringEncodingASCII); - } - - CFURLRef defaultHandlerURL = nullptr; - OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator, - defaultHandlerID, - nullptr, // inName - nullptr, // outAppRef - &defaultHandlerURL); - - if (status == noErr && defaultHandlerURL) { - nsCOMPtr defaultReader = - do_CreateInstance("@mozilla.org/file/local;1", &rv); - if (NS_SUCCEEDED(rv)) { - rv = defaultReader->InitWithCFURL(defaultHandlerURL); - if (NS_SUCCEEDED(rv)) { - NS_ADDREF(*_retval = defaultReader); - rv = NS_OK; - } - } - - ::CFRelease(defaultHandlerURL); - } - - ::CFRelease(defaultHandlerID); - - return rv; -} diff --git a/application/palemoon/components/shell/nsMacShellService.h b/application/palemoon/components/shell/nsMacShellService.h deleted file mode 100644 index db95278092..0000000000 --- a/application/palemoon/components/shell/nsMacShellService.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 nsmacshellservice_h____ -#define nsmacshellservice_h____ - -#include "nsIMacShellService.h" -#include "nsIWebProgressListener.h" -#include "nsIFile.h" -#include "nsCOMPtr.h" - -class nsMacShellService : public nsIMacShellService, - public nsIWebProgressListener -{ -public: - nsMacShellService() {}; - - NS_DECL_ISUPPORTS - NS_DECL_NSISHELLSERVICE - NS_DECL_NSIMACSHELLSERVICE - NS_DECL_NSIWEBPROGRESSLISTENER - -protected: - virtual ~nsMacShellService() {}; - -private: - nsCOMPtr mBackgroundFile; -}; - -#endif // nsmacshellservice_h____ diff --git a/application/palemoon/themes/moz.build b/application/palemoon/themes/moz.build index 4267990dd9..0fe67acd00 100644 --- a/application/palemoon/themes/moz.build +++ b/application/palemoon/themes/moz.build @@ -5,9 +5,7 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT'] -if toolkit == 'cocoa': - DIRS += ['osx'] -elif toolkit in ('gtk2', 'gtk3', 'qt'): +if toolkit in ('gtk2', 'gtk3', 'qt'): DIRS += ['linux'] else: DIRS += ['windows'] diff --git a/application/palemoon/themes/osx/Geolocation-16.png b/application/palemoon/themes/osx/Geolocation-16.png deleted file mode 100644 index d710e7336dbc445d36ee4868257d9139c50f8919..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 704 zcmV;x0zdtUP)-5(CMB)PU52^dKA1ETy7* zTUpEKsECw;Hq3MtZKJ(PS_V5{d|^p>Z6!^^qad|FJq=L344R^{YPU5FEw2el$Y~-w zPgqiJv9N^P0%S2kaam1uL-VV`QYs)r)Ict2(loZZC9SB@j2=Lo{G!4fe4+yA;!+Cg z&1(7Rl=hk0xm_2QQZz$Xhzkpd$(k8iIbY|OklW3mqGNKy)j#s8j+y-p zUJ;p{3=FI*85kH9u|%&T(8gt4LXtZ)jjXTQdj?-t(9plYplxh@(?2p9C=hr{)6jgo zu(bS2Mos}t12}jU`Nd?Hs_U3+w|4fq;Sn5tSxv|E3WJ7$`2o+s=v&&xmd3<-K||Nn z*vUKOhO)NdZU$*Z^;So(pnGy^+AWy23dk_9^NXX4ODkzM+qih&5tmhNVi1&&*R*!= zzGrIZexHR;SPNMpzl8j9UNPC(sD|=u8Cp5tHM4WO!zV1I2^Lh-Hf(bXh5 zR}^lDslC@RLtEDaaLt^2TIxpD=N!C3?klS6G{aM(n4B`3p{3n2&%l@`macwJfa$(n zQOnpmJgwkXNMi0y8C5+CVHu@16FZMbPQIa!bc`*R0aGO#MrP7Awaj$&kGSt0k?=eu zDerlHUH9YM+Rn#;@tIHEf?}RJcn9CrG&IY^nHxb^%g92-*vhflGbCznL{j#%@T9C~ m?g0^d49)GE)D289vNHgKsnY3}7pKGk0000P)q}F%6_deVF@xDa@f<)S$an8Kw{LXXV`_?&i zf8XEt`EAed3g;aEKY#o`nI~B-T7WZvRW6{9K+G34w-Fcw?q-AA{~z&h#s5hL3{-yi zUjNzh3?bZGT!(xs9iC5w#NkjlA|X-EF=mvQus899`l zyOIsA^d}3zKm~>;V)h=a1)0DLav9Ih1kwwA>HD7Wq!j+jw=I5eXhuKC!XRYa7@c(f zxP0Oz-`Vrwf7xWM)7m(bYO51vwRNbA-`;t$$g6MA?adO~)i>GTuK$w*V4wm!hbo?w zBJe#CMS+Ymp_d)@yhYPetf?7yteF^Jamkn7xx7nkE!w(cI6RJTz2-A?FI&u_qNHTJ zvJ_(5q!L>ZVsn@09_jbZZev~b_;)Wq-WP-4!{HbEmJtaT%Wtfe; zOfK>=)xev5z>{w}R2sN4Nqd%?ksr`EG{9v)`YPE44l|tP&?O%sdBq#~{)Q=>gEybl zj_>e1M2lU<#L&)_g4A#qcIDX&E;5cblp`yxMF4d z$ZnmqoxEoFU)Svh%)bW&|K(bJ_i$AzW3%0@QC8=JzRglz|J3duzJ2Yw8>mc=k_#dh zbuK~fw_Np`+sUvrD!xkopAttBZ{kyvt3Krxr&G&75jK0HXKE##i)BEE6KpCj@`)^vihJ`Ws7amL}a z<+yf_^Jj;g+gF4jz#&Lg!mfjL9^QP2f!&j2>M?n17!_TxVp(a`ik6RDxk%grQ~?Fp zKNN&N2!MeK42{)2ZC$Y?>lYsrr7!;Y{`XzEZQE~K^Z(R;J>ZuW>&_dJtG;OPWiig_K=oivRaW< z3csFGE2r!{1mWUiIsN>Fw}0qV|3g3tNd8a|jv9c03TR{f$%<;LhyMI0>iciG^PV@Z z7#`e3AO-nMNHL!w6Z&*{A)i>M=xfpJs`T^yYyX<#a?el*i$uXP{&{o>Wn&>pAx^Ot zobYi5oOT@F9@3qWJTp|`;6$B3D?+95lN4D`Nh>Mi<1u@N6Ea=>TzKV)TdrP{eaoUE zdx09Dj}`>^2V`)v7Mqqh^80^2c*}S0`1z$P#z%ILi#%F$89G`E6tW@hEd{Q5c$fw4 zLyV5K^60e}vafv^X^_VTS-w(VMm-XEE=39hxeVm95c-I~Lj;niCsXd-S7oSf(Y{aO z`BbGx#q*fr{;0aK|_mign>_Q#j-|DQ%@p3{oZ@%?OacrP_&9N#h{n3 zq_3l1NpY#c$N=XARyF*9Qx>N!D2G!9qYO6DxKtxj4T-|WDY~2zPbajt?V#BE12*0N zT9%x(h2A-TxAk2Y^t^dto}EX#9gZdn2xDBBDAV!q)cRXCZvFi7$R?~vJ>LCvh2uSi z*C7!CWGaYyQm|0jndR8@XJGab`Yl*dBz03o=1Aq=1_!dY+vtNdMd@Xhc5$wfeQ4#bwzvO_Ai|=s`VRo4gLHB z*`c4)8#_LF|1>R&1iSY~-1w>`JbCgQmLI6ID5z4eX1L=oE+W6BMti2t+$RpQ{j>#0 zJUnd>ks(XGCJ-}X4=av!IP0E!-4v@W6Qk`M+I1#jpwRv%rfOSAZ0*=I ze8tXVXUT1VnM!dl2Ey<9fYqV}$$MQrX%_papqBa! z<+2AXD-S! z0Mr*2UU(}!mjSEAN>>oSVqx%Ve9=Z72Irh@c2=kIhbmPjT|lvH2dD6)gGf2n&V}F=xj(`Qa*QE>EYiaLDJtn&Ww@_;$AW$5VDWqyuN0^fnEP;u^Vu zYpxA>p5=|j8H+WIYpV=aS?Z;T>4DXB&YdE)LyTb=yvr(4TV*cq>{Y>{3ICFcIi>LN- z{*SgWHNTB^Q=x}RdP>u{y#ZlYiNf9j$)+<<=VtJnBPSe*5IEToD+TsNUGQNM0)!9< zDG^d2Jc;ln!V?6c&*C+|Bo-401C#rwdFksU>pS)Kg5CKk0YR*Hp2$mnH;k9I0F))Q(88EuChjkx+1rJ>J zYBsDskpa0JIaP;wmX0M8yz%~z@~OW(g{%Mda%l+0o9yHH)Zp7f5HfQ@g)| zU(J3elWsPJSuv+^FYo>KyZOXlU&y6D`V!saL(e`$BPu*kd-pp~AVd=Z*#H5r0mPwQ zC$qe($kI-q)6W`b$pXpNjR&sWTXj7^@KSleAR0$O90!C?PrJ8F>>6fS$1+CiJ|=Z& zD|oEGl{0pgSus22k|%c~`aDK-FBDoZ)4jyIBxkI>nRYXR^+Rrb-QV!U#c$)GFk;2v zR*t>@2P~-FNmu6>uN(V1m;T#VSl@m&KRM|tHuj$MY*ctQEY6^CBoNLWxig*>qce25 zmGpP+qA+KS!f~5ezjczeyB54)Tni?oO6YK7rR4VJn8=@eXc13O${d1jYyCv zbX}oqDXP+p2IUl~9CO+yxa|A~v1vqa_fFzuB|D=}Z2ic^eHQ|Uo?j;%-U1ukelcc$ zLaX$WEsuOQK2%=OnTgTfBWNJC4vocmP|r&abZ1a;NNH0mCE0})J|NiXmU4Uc-Tapi zKFqxrz5`RPph_ib(`6l#CpUfP zO3vH(lg5^4MuEeuaL>sd+z|;>5-WD>%(8jgGCDdok?0E9Xe)EVCsu4OyTyR_dsAU2 zgBuw)myMk{|BP^af+*UN17>JTTmxIxj>3hH5wN|dJ*bZ$1PZ6i4%d<4yzpo zAL~4{5u`?tC`Uat)U>0DPu0s%6A`HfU5%k!ZUCn=&RXt2_BFikP2c15v#w|8Ks&v? zQ~c%rFY=AM-p=u(Pc;%J(*(jaL1}&u0uQ9XNJs1xsnAqZh4E@|%nSfWhC}}a(hmQS z%J!D3DWgQl#HbUD*CS!p#!3u%1qLJr{XQNiLxM?^n*GzL~%3kM3 z;CwJKB2h?_VvsoDV~yj!g|Fnn?$fz^)9t)r;wP->*~OiEKFm$xGQKnKd?w2go)En4 z+OHEQ)09;WPk`_w&I+`u5#;t3;T-?@+x~?ZAWBm)<+?%DH08-&T=GehFu(*U{W~Qt z68w7ktFhW590*S!u((v?G8xdWVd`hWcFzIeu=0nU8V;Nn;liNNDobKy8snV6;Zydq zd~^BL{B-I(uG{ogF3fD;gW*qk+sOC%Z0B1TKYN^!(lBY7kjqMp5O~tVSc?RlnL0AD ze({#r5ANF5S}mtk>V`^9Q>_~+u_8${sWO~?=wV#R@@W6r&xzG8Q8?|eR${fqY4@Dp zpL?&lXHByMbmTqju);%o8I168X$sW}E{?I-`ThIU3M4zs_eTzs8%k z+(ShrXf%m680oN{L7~x}Au*b-{%CveQFVmsiKSdOn3_R`8sT|3AvylwMntQ}i0NV^ z+l^GV8G{8PO|eqq3=R6v04-(+a5#QH8@jB+cQNyV2dRrztaZe$jY+eh354J96Q%}9 z9kjz4iAfE=&adVX`x(A`@MD~m9pMscEW0b_<}-5~>XjI20I;3~&meHT_wr>!FWD4* z!)42-jgi!9hH6byuPN$vMVe?<4Q;^hkUZG72CHVQYH_K-DT8zJIlaB-TtD0QJCYfW zRE12Y$5LP`bLGFWF!};3TW&koPL9%q zVCfReM;@wj>XsNI9r%tQ+lUB8yl|QIdH#9OxByEE4YQ67^1HFu*zVR z#W;x}z^N2hOXyzwTUz>lN+mAyP*yT9E62wkth21s@~*u#`lby(eMJsWf-(Y+?jsv* zFUkN5=xiY>Cv`);W=QH9RnzELbCTYStywm7tZd}vslh6POHz!sIOCf2eoSw67pvRv z;}tzOu_*r-p#y1;w7zLJGYq!b4f5SMS#bbK6|KW&{%djg=@> zV-n*S%EHGk%kfJafP;(Tgg5`ZN}O7Z2r^m z%IEd>8sHsDdKt6xSl01fW*6>eZ0xFMiy#|oOsp}n!CH^8kyFUedz`ph$7Kb=7kCD~ zazT!ryA*%6qsE!DQ|8=i_`>Vv<7bLnU#KbaEC34&Fi>d#FuNza#q*+5RUG4m1{o;2 z+z28g*&g?y<3_`wknuUDUEtEs;=HZs6eg4*6M9JD2m{ax5DI5g0&g~p+keR1!bX0v z_0LFEgtL~MKSeG(jYnHSo~V z5YNFiyJ{@%vt0j!D&Km4v}Fc>Bdfs|WWd7t*-b68TA3WFq5_Q!BukP3WQ$-+y%!xT z0$&gq$7tm~y!dhaEO;U!@+^sTc(T#62m(;n5qdtJTun{YDTJG73->czUBJBdE%bNZ zOXQ89(jw33cM>OOv2n)*s90f=MhR?UgNYR;*5r!^X9cOV4o z76%L#@_c-2%#yj&eEgl{`ze2z8-Aq|O&sMMG6z?P3Pbg+*QSk-qI(%*uzb$qW* zF+9Z6ThAk{Cg{4t)OAx7y53+w$DEzir~2^I#RyLlwPeYPKC&*v*B&BqxVqs$d%zv@ z`>|sY9og;Y_Fs^B`%3`;V2*DWyH=bqcWV$zbZk&{%?bvwHN&HF3A&=t)s(5}n0maQ z)IcrKXk)0S24gMCI+Qjf#$uc$(Fwx4mA3pZS=99?Em4AJ9h2pL^1&QDS>)j4LJl1Y zNUABit}(S{MzOE&LY_VHrg_6WMxQO zu8qw-f5lyW*J)8o4ek1W^q(zzU(^XU{eS^#OP99Z-m|FZlY`s#qv{&#HBN3_YG}!i zl4~mwM2|CFtst!f4MG`wU*M&NNI+~2LP(r*_FEN;;;RtooJR3+XT0saikLmU=T?uBR5I4XL)&Q$sa2)Dner5Gze3snOPP2g?@Sfpk?C z^*u#gO3<|wT~nx7C1J(fd-z`f%;JR) zp{fd1Rp{yr2#tL|Lw}uGRO+zS5d=^=*hUyhGFgwFg<~u`=VmD0i{~=r(goy9LeHGc z9Sd6g;o+Me9AMnuLYwq~OI{R!W{5CAeEPEdjmuA6!mK$3geTGE0z;2nO;&c`;gDFQ zvtUglZB>o1l_rhisTLcmv8EPVsx?iil9D8fdSWP5Q%d!igQaOkOVi{s1E^}_$ZJM< zRo9K{xM}&c;lF}V5M~5n)+3Yk$>u_&$Wx!_L%KRyb2S+h?X9q4Y3q&6ZmT8(2i4c@*RT zAtdHd4{1#`(qiqfrXj{O+f;$T4+VbY5oA1~tWPE%l5MrL&C;}X>?X=(2-3GUI#3Jd zl;)qh^zVUM-xYm%e`5bNZjt{E26Y15eKZ3S4oDUj<-U_w&;Cg5SBt*tn<djedhL4b?0TYb?rIgc1l3taIRr=N$VKvIXWW8RVGL*7NlJ zC!>|cHZyk5Ybfr8vZ=g}pYaKE0hwaR{NrvR@)I)h7-af!l#MWX$t(8%{3j>9<)YV1 zTRMe2XS?Nr&y+RdkiCfwZqreX$jl5#0L8AW`+wxx_1V|Of6fE-d89SP^5eFkjG?># z+oV=uT%$c^T|;>%9Kr|dY=afTHGUTkV-IH}p3C)wccIqDIaBep^{H!-~~UDR^M$$NKr&-AP$t|pYH`#ApOd(b8#otbiR4l8J6 zhSoM%AWUPWG36ly250{l#l>4^`K&qd@i0m|P`)qR!T-uG;K&p%)P4RO%4k)}on27!lP?0tiynGte; zvN|0IC&y~5!qHrijXclyh^xIkvHmK~UQR$IJNmnTGOy6cA)WTo95iX2|6Nw5Va^KjMdT zcXyQX@BifKAAY8-H9z^bYu@#eW3)##CwS=_-@`X{-**12etl=jcGj=EVr{Z>!@hou z!fK5$j?2#ZG^67O5rM#AiM7T`fpV7AT2g07j6pfm0L5BTYFWPz5UyW?tvUTgGEeEE@ho@{h zm5hyS`}fZZKl0!sa%FVV6GO#yQ-$`ij&s(2{>#BdAG>z@ll%Kb9Fxflg775f&U%De zlA@F%7X@f%iJc`j8lf7;R>lgX6-Xq)9_jHR)lg{7;dDPyYZfo^@uPrD-q1b!NxHkr zB>GG`+P2YJe2_S(@wpfpsXU%np%<&SWO@#9s*wq z0wbv?-N+j(q}m~yzCj8}-am#^Eg@5+2|&og1)J&bzn^?~9DevsjI#(Q(c)~z51jDZ zZQr@~*0F1bJKwFQtf{!X{sw$zJ#FW#RK>2uSigON63WU-)pr$M$ z5VT|qMDc$`XF`gZfG8UhWqkZ_8STaSAP*o#mX5HUL-CpE&Ik0pyYKtq`svBZYOPX9 zRFY_%w!&#ATxtd8k25RWIcK@&5Lru99O&8f_52cf=FoP3)0xTnUoN(`cFkS9c>b(Y zFFL=sYwEa@^4}#;Qy8Ujksy(V1VzoIRBTEqjVY^ys!pjHLt+gn0x!&v;jL5;y#+6j zw6<-dqx}hr`6{i&G5jDT?-j6OH9I!X-nQ|sb?b(A?b%-`m&ek$K5le6fi;uDsVU*o zDM?Zmxcb=0HuJ{-Kmd`0+&{ODo_NKA>eoe4v^}#uTKm5Gs-KP*x^u;rmd>ulOXv5T zeA?-YxP{ecK46T z`a=)In?@cQf=)WZ^z0y7oK2mLY?0(ldVl%lG5#?G=E!q_=^ZS=Q zwEALyken!*t+Z!%k}lZe2>k9=}jp>uM5*;EdeTy^ebdDoWFseOCKtCdPAN#ar($7Q9`X=`)|XUaHT z64-J>s5VFC>mXu4zm)QS@Cy@1Fd>=&;@(+Ak2Dxknw##@_j!PQhGuNX~XucNG9smTC25ITC3D3ohX&YTC2KNs%Dg` zT5D=JTLD{bh^sbeE^6YripPLG8s%U1OH)msFvErnka3Wm0cGYMh>Q>-Bc#koDI+0e z=t&t!=>W`KwqtRQmDwRtZ*LV{-4^%0H9z9WvS8zWE6a-rG3*UdU!HP;kG0wkjGEQHWb+!q{jDp?~N_#J$yf|WN>&RjG86cV>^kHC*et#d$=YIonccN)MAIhfy0000< KMNUMnLSTaD2x3+M diff --git a/application/palemoon/themes/osx/Info.png b/application/palemoon/themes/osx/Info.png deleted file mode 100644 index d09e82b6c6138941336e5039b2561be1ab5e891f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 641 zcmV-{0)G98P)8oGTzsj`3~=8?v_$nV$o5tKjR_ z!|U6H{obY)fKDO+Sw#YcvI-fqGl*Rt1HLZ7Z&s>0u-?AGRdXYpWOBejqjj#N1tM*6 z=LYJ<0z5*rPoG2nW)^=S;O5Hb5kx9?GaVNm@~8Cbp<(?Uu`WKBq>p+Sv_r;u1`n;_BcK+#rxgoq7h1B-y^~Mopaj zYODi-ICm8D2#=hAN6BL1BG~dW91ZYOQ$Uk9)7^00O}&3Ns^mC#Z=zlxki#e8WiG&* zyr$wL(`?J$sXuAN$*Pe$>@9Kx&*MEji1!Nv27z9IaGd b{SsgRWJpUVeM5OP00000NkvXXu0mjf_t_@n diff --git a/application/palemoon/themes/osx/KUI-background.png b/application/palemoon/themes/osx/KUI-background.png deleted file mode 100644 index 104a49f7b0e15a0a8c3ebab4b36750239e72ea80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^AodmxHXyn7)7~9GioL|s*OmPSyC9#uz$X9KKY&7< z1s;*b3=I5(a+f z|E=PLk>Wfm&2&*kh38=jGo^|?M{~zlZALjrqX7F_Nb6Mw<&;$U8 CZBdH= diff --git a/application/palemoon/themes/osx/KUI-close.png b/application/palemoon/themes/osx/KUI-close.png deleted file mode 100644 index 08eeb8183168c637770f7d891660dc844c7e0948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmV;40e1e0P)R00004XF*Lt006O%3;baP0003PNklH$cI}0RhK3snmVga+a&n4%{P^)F zm^pv`{P|~OWMlzSpaHX$3`?*Y4gx1np1cW^QvfOA0eKBw0TGtqG#sQ?OH0cc7N2+( z;;@7mJ=~;f;2}dT$*$rBVnK2YC(05fC8Z!68=E9@4JT*`FrU1C@ZiB$3X?T{OQ>Nu zvL%An*4D}Q@8AE1ZurHE7vCu>D+fU11t(x4$7X5(ng$U~Bblbjl%^StrbPwK3p<(@ n*R-v0=uu_Tw$f*yakB*gjUXBJFM#-B00000NkvXXu0mjfU}2Te diff --git a/application/palemoon/themes/osx/Makefile.in b/application/palemoon/themes/osx/Makefile.in deleted file mode 100644 index 173ca68435..0000000000 --- a/application/palemoon/themes/osx/Makefile.in +++ /dev/null @@ -1,7 +0,0 @@ -# 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/. - -ICON_FILES := icon.png -ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} -INSTALL_TARGETS += ICON diff --git a/application/palemoon/themes/osx/Privacy-16.png b/application/palemoon/themes/osx/Privacy-16.png deleted file mode 100644 index a4be3e9acf875dbe122c3ffdceea8d89259d9229..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 800 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 diff --git a/application/palemoon/themes/osx/Secure24.png b/application/palemoon/themes/osx/Secure24.png deleted file mode 100644 index 896343afc5f3630236dc26b3471789fba8394768..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1098 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 diff --git a/application/palemoon/themes/osx/Toolbar-inverted.svg b/application/palemoon/themes/osx/Toolbar-inverted.svg deleted file mode 100644 index ce59313e68..0000000000 --- a/application/palemoon/themes/osx/Toolbar-inverted.svg +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/Toolbar.png b/application/palemoon/themes/osx/Toolbar.png deleted file mode 100644 index 8ec756e03dee80984e99dd30d4595be7a5982761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16015 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 JPDHLkV1k~)c1!>O diff --git a/application/palemoon/themes/osx/Toolbar.svg b/application/palemoon/themes/osx/Toolbar.svg deleted file mode 100644 index 7a68c06087..0000000000 --- a/application/palemoon/themes/osx/Toolbar.svg +++ /dev/null @@ -1,1356 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/application/palemoon/themes/osx/aboutCertError.css b/application/palemoon/themes/osx/aboutCertError.css deleted file mode 100644 index 100bb3d3bb..0000000000 --- a/application/palemoon/themes/osx/aboutCertError.css +++ /dev/null @@ -1,73 +0,0 @@ -/* 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/. */ - - -html { - background: #833; -} - -body { - margin: 0; - padding: 0 1em; - color: -moz-FieldText; - font: message-box; -} - -h1 { - margin: 0 0 .6em 0; - border-bottom: 1px solid ThreeDLightShadow; - font-size: 160%; -} - -h2 { - font-size: 130%; -} - -#errorPageContainer { - position: relative; - min-width: 13em; - max-width: 52em; - margin: 4em auto; - border: 2px solid #DD0D09; - border-radius: 10px; - box-shadow: 0px 0px 8px red; - padding: 3em; - padding-inline-start: 30px; - background: url("chrome://global/skin/icons/sslWarning.png") left 0 no-repeat -moz-Field; - background-origin: content-box; -} - -#errorPageContainer:-moz-dir(rtl) { - background-position: right 0; -} - -#errorTitle { - margin-inline-start: 80px; -} - -#errorLongContent { - margin-inline-start: 80px; -} - -.expander > button { - padding-inline-start: 20px; - margin-inline-start: -20px; - background: url("chrome://browser/skin/aboutCertError_sectionExpanded.png") left center no-repeat; - border: none; - font: inherit; - color: inherit; - cursor: pointer; -} - -.expander > button:-moz-dir(rtl) { - background-position: right center; -} - -.expander[collapsed] > button { - background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png"); -} - -.expander[collapsed] > button:-moz-dir(rtl) { - background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png"); -} diff --git a/application/palemoon/themes/osx/aboutCertError_sectionCollapsed-rtl.png b/application/palemoon/themes/osx/aboutCertError_sectionCollapsed-rtl.png deleted file mode 100644 index 84ba18c0a388d48a4aa3e8782f151cb69e20936e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmV+y1L*vTP)4Tx0C?K1(mQBVQ5eAS|4ooaln^i#?36*OLX?;U+C@m4hfNw|NK*2cOzusS zXmWGC_a;7Ys30y*f{&pH4l0d^f`b(-Se#r0rJzANIO|yGA|(#jlMGT_{NTXve0-e8 zcMjOUl{Kwt16r!7XHL(03dNFVtj}I-I5>o>EF0QPI-O+K*#3+JuyMSsY0byCmv6q^ z>?LlUdwS#UhW90Z52s!zmO%0X?waKg;I3HC0q#qtW`a})+;Y9FfOHM;>bXo9q!qwf zv-}!xRxG~tD_}*%@6|mm{j>?*Df_)7* zTqu@2){&Qgz?lhpE1w6>W_{CA~$SD}_!P@mvZmW+3NCzFpV!#i8v~Lym+#3wG z@-TJ`cD@V-KUW8XohM-b3hUc)NALdbmn40Ff6c8sTXXni3hidAF97(Uw*A5ifH(Je(*vAFzS1YNrzy$Eo=w_qB zi;Y-ZSSd&5g|F7bsbP&C%Ltz@C(^=Ibs;OPnX|*1su9hO*2(3C^-g9%_(FSrSg%wg z!}F-kR8qKM#&g0%h>|3UpCCS_$P**Y9AU8jAAsu_Je)k4$YkF=di6(7%<5$mAl%lj z=#5(4^vq~lv+DK4Rr!S1P`Rv002ovPDHLkV1i>OZ)*Sm diff --git a/application/palemoon/themes/osx/aboutCertError_sectionCollapsed.png b/application/palemoon/themes/osx/aboutCertError_sectionCollapsed.png deleted file mode 100644 index c9805f654c79b22ce0d8435d030e775f3b7492ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 776 zcmV+j1NZ!iP)4Tx0C)kdlTT>Va1_VCZIM-!Qt%JxDF>MfRbpG%E`x6UAuNp?n51_5vX7S{VaOUheVQhe%@FR!=2v=pxn3kkGxol&bU*Kb(){e1U zk8dyCe7D}u-8%p5#@)5Zt8IcjIb_m=fGJw3yow;KY>#RDQA47#a;priom{$Bkk}Mz4w8Y>mzMr;MU5wKWNosQ8%4$ z*D|o%)>p^*wd^=sPiXFM!0M*lHG8fvP3rpy{Og_XnP&$+(;mp&9{rtp zU0g2_=wAcM2_R16i&bF!KCtI4AdyD8KNj~h$%4mqGedpiu?y9l-m9ia10}pn?n}%z_HX z|3C6X_&M-!{6wx;djIG(6aFw;z3lci*)gt|&4y+R({%dOh>+Fg;}Ib$ij(*aV&<+& z9Cuc%0001kNkl8e4Bzhe!CePa&jMrMqnUZM!Cqk(^}uj3 zUIS1y?!adULJkxLAJ2IF|M_|chI0|B@UY0%h{w!9E(HMplqvO5LNk{D00004Tx0C)kdlTT>Va1_VCZIM-!Qt%JxDF>MfRbpG%E`x6UAuNp?n51_5vX7S{VaOUheVQhe%@FR!=2v=pxn3kkGxol&bU*Kb(){e1U zk8dyCe7D}u-8%p5#@)5Zt8IcjIb_m=fGJw3yow;KY>#RDQA47#a;priom{$Bkk}Mz4w8Y>mzMr;MU5wKWNosQ8%4$ z*D|o%)>p^*wd^=sPiXFM!0M*lHG8fvP3rpy{Og_XnP&$+(;mp&9{rtp zU0g2_=wAcM2_R16i&bF!KCtI4AdyD8KNj~h$%4mqGedpiu?y9l-m9ia10}pn?n}%z_HX z|3C6X_&M-!{6wx;djIG(6aFw;z3lci*)gt|&4y+R({%dOh>+Fg;}Ib$ij(*aV&<+& z9Cuc%0001bNklzLGbhSj{je;rlJeO`9cnlQS>muWuOdpQ4dCD9&L1C zFrQV}4MQBm0FVj}`2q}uxWus #errorPageContainer { - background-image: url("chrome://browser/skin/Privacy-48.png"); -} - -body.normal > #errorPageContainer { - background-image: url("chrome://global/skin/icons/question-48.png"); -} - -#clearRecentHistoryDesc { - margin-top: 2em; -} - -#clearRecentHistoryDesc > p { - font-size: 110%; /* to match the value set in chrome://global/skin/netError.css */ -} - -#startPrivateBrowsingDesc > button { - margin-inline-start: 0; -} - -#footerDesc > p { - font-size: 110%; /* to match the value set in chrome://global/skin/netError.css */ -} - -#moreInfo { - font-size: 110%; /* to match the value set in chrome://global/skin/netError.css */ - padding-inline-start: 25px; - background: url("chrome://global/skin/icons/information-16.png") no-repeat top left; -} - -#moreInfo:-moz-dir(rtl) { - background-position: top right; -} - -#moreInfoText { - margin-bottom: 0; -} - -#moreInfoLinkContainer { - margin-top: 0.5em; -} diff --git a/application/palemoon/themes/osx/aboutSessionRestore.css b/application/palemoon/themes/osx/aboutSessionRestore.css deleted file mode 100644 index 4fa490798d..0000000000 --- a/application/palemoon/themes/osx/aboutSessionRestore.css +++ /dev/null @@ -1,73 +0,0 @@ -%if 0 -/* 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/. */ -%endif - -html { - background: #f8ffd0; - height: 100%; -} - -body { - height: 100%; - text-align: center; -} - -#errorPageContainer { - background-image: url("chrome://global/skin/icons/warning-large.png"); - display: -moz-box; - width: -moz-available; - max-width: 85%; - height: 75%; - max-height: 85%; - -moz-box-orient: vertical; - text-align: start; - border: 2px solid #efc; - box-shadow: 0px 0px 8px #aaa; -} - -#errorShortDesc > p { - margin-top: 0.4em; - margin-bottom: 0; -} - -#errorLongContent, #errorTrailerDesc { - display: -moz-box; - -moz-box-flex: 1; - -moz-box-orient: vertical; -} - -#tabList { - margin-top: 2.5em; - width: 100%; - min-height: 12em; -} - -treechildren::-moz-tree-image(icon), -treechildren::-moz-tree-image(noicon) { - padding-right: 2px; - margin: 0px 2px; - width: 16px; - height: 16px; -} - -treechildren::-moz-tree-image(noicon) { - list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); -} -treechildren::-moz-tree-image(container, noicon) { - list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png"); -} -treechildren::-moz-tree-image(checked) { - list-style-image: url("chrome://global/skin/checkbox/cbox-check.gif"); -} -treechildren::-moz-tree-image(partial) { - list-style-image: url("chrome://global/skin/checkbox/cbox-check-dis.gif"); -} - -#buttons { - width: 100%; -} -#buttons > button { - margin-top: 2em; -} diff --git a/application/palemoon/themes/osx/aboutSyncTabs.css b/application/palemoon/themes/osx/aboutSyncTabs.css deleted file mode 100644 index 1fcd8304f7..0000000000 --- a/application/palemoon/themes/osx/aboutSyncTabs.css +++ /dev/null @@ -1,101 +0,0 @@ -/* 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/. */ - -#tabs-display, -#tabsList { - background-color: transparent; - -moz-appearance: none; - margin: 0; -} - -#tabsList { - width: 100%; -} - -#tabs-display { - background: #fff url(chrome://browser/skin/sync-bg.png) repeat-x center -80px; -} - -#headers { - background: url(chrome://browser/skin/sync-32.png) no-repeat; - margin-top: 4px; - width: 45em; - height: 32px; - margin-inline-start: 2em; - margin-inline-end: 2em; -} - -#tabsListHeading { - font-size: 140%; - font-weight: bold; - margin-inline-start: 40px; -} - -richlistitem { - margin-inline-end: 2em; -} - -richlistitem[selected="true"], -richlistitem:focus { - outline-style: none; -} - -richlistitem[type="tab"] { - min-height: 3em; - border: #999999 1px solid !important; - padding: 2px 5px; - margin-bottom: 4px; - margin-inline-start: 4em; - border-radius: 6px; - background-color: menu; - width: 44em; - opacity: 0.9; - box-shadow: - inset rgba(255, 255, 255, 0.5) 0 1px 0px, - inset rgba(0, 0, 0, 0.1) 0 -2px 0px, - rgba(0, 0, 0, 0.1) 0px 1px 0px; -} - -richlistitem[type="tab"][selected="true"] { - background-color: -moz-MenuHover; -} - -richlistitem[type="client"] { - min-height: 2em; - color: #000000; - margin-inline-start: 2em; - margin-top: 2px; - margin-bottom: 3px; - width: 42em; - border-radius: 6px; - background-color: transparent; - -moz-user-focus: ignore !important; -} -richlistitem.mobile[type="client"] { - list-style-image: url("chrome://browser/skin/sync-mobileIcon.png"); -} -richlistitem.desktop[type="client"] { - list-style-image: url("chrome://browser/skin/sync-desktopIcon.png"); -} - -.title, -.clientName { - color: #000000; - font-size: 1.1em; -} - -.title[selected="true"], -.url[selected="true"] { - color: inherit; -} - -.url { - color: -moz-nativehyperlinktext; - font-size: 0.95em; -} - -.tabIcon { - padding-inline-start: 2px; - padding-top: 2px; -} diff --git a/application/palemoon/themes/osx/actionicon-tab.png b/application/palemoon/themes/osx/actionicon-tab.png deleted file mode 100644 index ced958ebbe39646e15fef004e6c1a5bb3f2f21f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 425 zcmV;a0apHrP)890**5YIeup{!-#^vVGFzRrcR zQv+Lq;u0@)kklF%QOW~$<|YH1M~M|tG9a9&aPeanJFCNijf2?QULe&BTo>@+l($^Ad_K6BR{yRsgL*2=*Fe~PsUl_tS9wed;djCadl<`;w z27^He58hDwAFr5|>;_tR@XV=g_Z4WM&Z%WL&_GpAji~{=aG@G{;6z#X_kkr;Mh2&n zX`0L9|AG%6U;iAf%X9{?sp|nF9b=gO^D~vvt?vO!UdIny!I3w>D%N