HIWebView.mm 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612
  1. /*
  2. * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef __LP64__
  29. #import "HIWebView.h"
  30. #import "CarbonWindowAdapter.h"
  31. #import "HIViewAdapter.h"
  32. #import "QuickDrawCompatibility.h"
  33. #import "WebHTMLViewInternal.h"
  34. #import "WebKit.h"
  35. #import <WebKitSystemInterface.h>
  36. #import <wtf/ObjcRuntimeExtras.h>
  37. @interface NSWindow (AppKitSecretsHIWebViewKnows)
  38. - (void)_removeWindowRef;
  39. @end
  40. @interface NSView (AppKitSecretsHIWebViewKnows)
  41. - (void)_clearDirtyRectsForTree;
  42. @end
  43. extern "C" void HIWebViewRegisterClass();
  44. @interface MenuItemProxy : NSObject <NSValidatedUserInterfaceItem>
  45. {
  46. int _tag;
  47. SEL _action;
  48. }
  49. - (id)initWithAction:(SEL)action;
  50. - (SEL)action;
  51. - (int)tag;
  52. @end
  53. @implementation MenuItemProxy
  54. - (id)initWithAction:(SEL)action
  55. {
  56. [super init];
  57. if (self == nil) return nil;
  58. _action = action;
  59. return self;
  60. }
  61. - (SEL)action
  62. {
  63. return _action;
  64. }
  65. - (int)tag
  66. {
  67. return 0;
  68. }
  69. @end
  70. struct HIWebView
  71. {
  72. HIViewRef fViewRef;
  73. WebView* fWebView;
  74. NSView* fFirstResponder;
  75. CarbonWindowAdapter * fKitWindow;
  76. bool fIsComposited;
  77. CFRunLoopObserverRef fUpdateObserver;
  78. };
  79. typedef struct HIWebView HIWebView;
  80. static const OSType NSAppKitPropertyCreator = 'akit';
  81. /*
  82. These constants are not used. Commented out to make the compiler happy.
  83. static const OSType NSViewCarbonControlViewPropertyTag = 'view';
  84. static const OSType NSViewCarbonControlAutodisplayPropertyTag = 'autd';
  85. static const OSType NSViewCarbonControlFirstResponderViewPropertyTag = 'frvw';
  86. */
  87. static const OSType NSCarbonWindowPropertyTag = 'win ';
  88. static SEL _NSSelectorForHICommand( const HICommand* hiCommand );
  89. static const EventTypeSpec kEvents[] = {
  90. { kEventClassHIObject, kEventHIObjectConstruct },
  91. { kEventClassHIObject, kEventHIObjectDestruct },
  92. { kEventClassMouse, kEventMouseUp },
  93. { kEventClassMouse, kEventMouseMoved },
  94. { kEventClassMouse, kEventMouseDragged },
  95. { kEventClassMouse, kEventMouseWheelMoved },
  96. { kEventClassKeyboard, kEventRawKeyDown },
  97. { kEventClassKeyboard, kEventRawKeyRepeat },
  98. { kEventClassCommand, kEventCommandProcess },
  99. { kEventClassCommand, kEventCommandUpdateStatus },
  100. { kEventClassControl, kEventControlInitialize },
  101. { kEventClassControl, kEventControlDraw },
  102. { kEventClassControl, kEventControlHitTest },
  103. { kEventClassControl, kEventControlGetPartRegion },
  104. { kEventClassControl, kEventControlGetData },
  105. { kEventClassControl, kEventControlBoundsChanged },
  106. { kEventClassControl, kEventControlActivate },
  107. { kEventClassControl, kEventControlDeactivate },
  108. { kEventClassControl, kEventControlOwningWindowChanged },
  109. { kEventClassControl, kEventControlClick },
  110. { kEventClassControl, kEventControlContextualMenuClick },
  111. { kEventClassControl, kEventControlSetFocusPart }
  112. };
  113. #define kHIViewBaseClassID CFSTR( "com.apple.hiview" )
  114. #define kHIWebViewClassID CFSTR( "com.apple.HIWebView" )
  115. static HIWebView* HIWebViewConstructor( HIViewRef inView );
  116. static void HIWebViewDestructor( HIWebView* view );
  117. static OSStatus HIWebViewEventHandler(
  118. EventHandlerCallRef inCallRef,
  119. EventRef inEvent,
  120. void * inUserData );
  121. static UInt32 GetBehaviors();
  122. static ControlKind GetKind();
  123. static void Draw( HIWebView* inView, RgnHandle limitRgn, CGContextRef inContext );
  124. static ControlPartCode HitTest( HIWebView* view, const HIPoint* where );
  125. static OSStatus GetRegion( HIWebView* view, ControlPartCode inPart, RgnHandle outRgn );
  126. static void BoundsChanged(
  127. HIWebView* inView,
  128. UInt32 inOptions,
  129. const HIRect* inOriginalBounds,
  130. const HIRect* inCurrentBounds );
  131. static void OwningWindowChanged(
  132. HIWebView* view,
  133. WindowRef oldWindow,
  134. WindowRef newWindow );
  135. static void ActiveStateChanged( HIWebView* view );
  136. static OSStatus Click( HIWebView* inView, EventRef inEvent );
  137. static OSStatus ContextMenuClick( HIWebView* inView, EventRef inEvent );
  138. static OSStatus MouseUp( HIWebView* inView, EventRef inEvent );
  139. static OSStatus MouseMoved( HIWebView* inView, EventRef inEvent );
  140. static OSStatus MouseDragged( HIWebView* inView, EventRef inEvent );
  141. static OSStatus MouseWheelMoved( HIWebView* inView, EventRef inEvent );
  142. static OSStatus ProcessCommand( HIWebView* inView, const HICommand* inCommand );
  143. static OSStatus UpdateCommandStatus( HIWebView* inView, const HICommand* inCommand );
  144. static OSStatus SetFocusPart(
  145. HIWebView* view,
  146. ControlPartCode desiredFocus,
  147. RgnHandle invalidRgn,
  148. Boolean focusEverything,
  149. ControlPartCode* actualFocus );
  150. static NSView* AdvanceFocus( HIWebView* view, bool forward );
  151. static void RelinquishFocus( HIWebView* view, bool inAutodisplay );
  152. static WindowRef GetWindowRef( HIWebView* inView );
  153. static void SyncFrame( HIWebView* inView );
  154. static OSStatus WindowHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData );
  155. static void StartUpdateObserver( HIWebView* view );
  156. static void StopUpdateObserver( HIWebView* view );
  157. static inline void HIRectToQDRect( const HIRect* inRect, Rect* outRect )
  158. {
  159. outRect->top = (SInt16)CGRectGetMinY( *inRect );
  160. outRect->left = (SInt16)CGRectGetMinX( *inRect );
  161. outRect->bottom = (SInt16)CGRectGetMaxY( *inRect );
  162. outRect->right = (SInt16)CGRectGetMaxX( *inRect );
  163. }
  164. //----------------------------------------------------------------------------------
  165. // HIWebViewCreate
  166. //----------------------------------------------------------------------------------
  167. //
  168. OSStatus
  169. HIWebViewCreate(HIViewRef* outControl)
  170. {
  171. HIWebViewRegisterClass();
  172. return HIObjectCreate(kHIWebViewClassID, NULL, (HIObjectRef*)outControl);
  173. }
  174. //----------------------------------------------------------------------------------
  175. // HIWebViewGetWebView
  176. //----------------------------------------------------------------------------------
  177. //
  178. WebView*
  179. HIWebViewGetWebView( HIViewRef inView )
  180. {
  181. HIWebView* view = (HIWebView*)HIObjectDynamicCast( (HIObjectRef)inView, kHIWebViewClassID );
  182. WebView* result = NULL;
  183. if ( view )
  184. result = view->fWebView;
  185. return result;
  186. }
  187. //----------------------------------------------------------------------------------
  188. // HIWebViewConstructor
  189. //----------------------------------------------------------------------------------
  190. //
  191. static HIWebView*
  192. HIWebViewConstructor( HIViewRef inView )
  193. {
  194. HIWebView* view = (HIWebView*)malloc( sizeof( HIWebView ) );
  195. if ( view )
  196. {
  197. NSRect frame = { { 0, 0 }, { 400, 400 } };
  198. view->fViewRef = inView;
  199. WebView *webView = [[WebView alloc] initWithFrame: frame];
  200. CFRetain(webView);
  201. [webView release];
  202. view->fWebView = webView;
  203. [HIViewAdapter bindHIViewToNSView:inView nsView:view->fWebView];
  204. view->fFirstResponder = NULL;
  205. view->fKitWindow = NULL;
  206. view->fIsComposited = false;
  207. view->fUpdateObserver = NULL;
  208. }
  209. return view;
  210. }
  211. //----------------------------------------------------------------------------------
  212. // HIWebViewDestructor
  213. //----------------------------------------------------------------------------------
  214. //
  215. static void
  216. HIWebViewDestructor( HIWebView* inView )
  217. {
  218. [HIViewAdapter unbindNSView:inView->fWebView];
  219. CFRelease(inView->fWebView);
  220. free(inView);
  221. }
  222. //----------------------------------------------------------------------------------
  223. // HIWebViewRegisterClass
  224. //----------------------------------------------------------------------------------
  225. //
  226. void
  227. HIWebViewRegisterClass()
  228. {
  229. static bool sRegistered;
  230. if ( !sRegistered )
  231. {
  232. HIObjectRegisterSubclass( kHIWebViewClassID, kHIViewBaseClassID, 0, HIWebViewEventHandler,
  233. GetEventTypeCount( kEvents ), kEvents, 0, NULL );
  234. sRegistered = true;
  235. }
  236. }
  237. //----------------------------------------------------------------------------------
  238. // GetBehaviors
  239. //----------------------------------------------------------------------------------
  240. //
  241. static UInt32
  242. GetBehaviors()
  243. {
  244. return kControlSupportsDataAccess | kControlSupportsGetRegion | kControlGetsFocusOnClick;
  245. }
  246. //----------------------------------------------------------------------------------
  247. // Draw
  248. //----------------------------------------------------------------------------------
  249. //
  250. static void
  251. Draw( HIWebView* inView, RgnHandle limitRgn, CGContextRef inContext )
  252. {
  253. HIRect bounds;
  254. Rect drawRect;
  255. HIRect hiRect;
  256. bool createdContext = false;
  257. if (!inView->fIsComposited)
  258. {
  259. GrafPtr port;
  260. Rect portRect;
  261. GetPort( &port );
  262. GetPortBounds( port, &portRect );
  263. CreateCGContextForPort( port, &inContext );
  264. SyncCGContextOriginWithPort( inContext, port );
  265. CGContextTranslateCTM( inContext, 0, (portRect.bottom - portRect.top) );
  266. CGContextScaleCTM( inContext, 1, -1 );
  267. createdContext = true;
  268. }
  269. HIViewGetBounds( inView->fViewRef, &bounds );
  270. CGContextRef savedContext = WKNSWindowOverrideCGContext(inView->fKitWindow, inContext);
  271. [NSGraphicsContext setCurrentContext:[inView->fKitWindow graphicsContext]];
  272. GetRegionBounds( limitRgn, &drawRect );
  273. if ( !inView->fIsComposited )
  274. OffsetRect( &drawRect, (SInt16)-bounds.origin.x, (SInt16)-bounds.origin.y );
  275. hiRect.origin.x = drawRect.left;
  276. hiRect.origin.y = bounds.size.height - drawRect.bottom; // flip y
  277. hiRect.size.width = drawRect.right - drawRect.left;
  278. hiRect.size.height = drawRect.bottom - drawRect.top;
  279. // printf( "Drawing: drawRect is (%g %g) (%g %g)\n", hiRect.origin.x, hiRect.origin.y,
  280. // hiRect.size.width, hiRect.size.height );
  281. // FIXME: We need to do layout before Carbon has decided what region needs drawn.
  282. // In Cocoa we make sure to do layout and invalidate any new regions before draw, so everything
  283. // can be drawn in one pass. Doing a layout here will cause new regions to be invalidated, but they
  284. // will not all be drawn in this pass since we already have a fixed rect we are going to display.
  285. NSView <WebDocumentView> *documentView = [[[inView->fWebView mainFrame] frameView] documentView];
  286. if ([documentView isKindOfClass:[WebHTMLView class]])
  287. [(WebHTMLView *)documentView _web_updateLayoutAndStyleIfNeededRecursive];
  288. if ( inView->fIsComposited )
  289. [inView->fWebView displayIfNeededInRect: *(NSRect*)&hiRect];
  290. else
  291. [inView->fWebView displayRect:*(NSRect*)&hiRect];
  292. WKNSWindowRestoreCGContext(inView->fKitWindow, savedContext);
  293. if ( !inView->fIsComposited )
  294. {
  295. HIViewRef view;
  296. HIViewFindByID( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), kHIViewWindowGrowBoxID, &view );
  297. if ( view )
  298. {
  299. HIRect frame;
  300. HIViewGetBounds( view, &frame );
  301. HIViewConvertRect( &frame, view, NULL );
  302. hiRect.origin.x = drawRect.left;
  303. hiRect.origin.y = drawRect.top;
  304. hiRect.size.width = drawRect.right - drawRect.left;
  305. hiRect.size.height = drawRect.bottom - drawRect.top;
  306. HIViewConvertRect( &hiRect, inView->fViewRef, NULL );
  307. if ( CGRectIntersectsRect( frame, hiRect ) )
  308. HIViewSetNeedsDisplay( view, true );
  309. }
  310. }
  311. if ( createdContext )
  312. {
  313. CGContextSynchronize( inContext );
  314. CGContextRelease( inContext );
  315. }
  316. }
  317. //----------------------------------------------------------------------------------
  318. // HitTest
  319. //----------------------------------------------------------------------------------
  320. //
  321. static ControlPartCode
  322. HitTest( HIWebView* view, const HIPoint* where )
  323. {
  324. HIRect bounds;
  325. HIViewGetBounds( view->fViewRef, &bounds );
  326. if ( CGRectContainsPoint( bounds, *where ) )
  327. return 1;
  328. else
  329. return kControlNoPart;
  330. }
  331. //----------------------------------------------------------------------------------
  332. // GetRegion
  333. //----------------------------------------------------------------------------------
  334. //
  335. static OSStatus
  336. GetRegion(
  337. HIWebView* inView,
  338. ControlPartCode inPart,
  339. RgnHandle outRgn )
  340. {
  341. OSStatus err = eventNotHandledErr;
  342. if ( inPart == -3 ) // kControlOpaqueMetaPart:
  343. {
  344. if ( [inView->fWebView isOpaque] )
  345. {
  346. HIRect bounds;
  347. Rect temp;
  348. HIViewGetBounds( inView->fViewRef, &bounds );
  349. temp.top = (SInt16)bounds.origin.y;
  350. temp.left = (SInt16)bounds.origin.x;
  351. temp.bottom = (SInt16)CGRectGetMaxY( bounds );
  352. temp.right = (SInt16)CGRectGetMaxX( bounds );
  353. RectRgn( outRgn, &temp );
  354. err = noErr;
  355. }
  356. }
  357. return err;
  358. }
  359. static WindowRef
  360. GetWindowRef( HIWebView* inView )
  361. {
  362. return GetControlOwner( inView->fViewRef );
  363. }
  364. //----------------------------------------------------------------------------------
  365. // Click
  366. //----------------------------------------------------------------------------------
  367. //
  368. static OSStatus
  369. Click(HIWebView* inView, EventRef inEvent)
  370. {
  371. NSEvent *kitEvent = WKCreateNSEventWithCarbonClickEvent(inEvent, GetWindowRef(inView));
  372. if (!inView->fIsComposited)
  373. StartUpdateObserver(inView);
  374. [inView->fKitWindow sendEvent:kitEvent];
  375. if (!inView->fIsComposited)
  376. StopUpdateObserver(inView);
  377. [kitEvent release];
  378. return noErr;
  379. }
  380. //----------------------------------------------------------------------------------
  381. // MouseUp
  382. //----------------------------------------------------------------------------------
  383. //
  384. static OSStatus
  385. MouseUp( HIWebView* inView, EventRef inEvent )
  386. {
  387. NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
  388. [inView->fKitWindow sendEvent:kitEvent];
  389. [kitEvent release];
  390. return noErr;
  391. }
  392. //----------------------------------------------------------------------------------
  393. // MouseMoved
  394. //----------------------------------------------------------------------------------
  395. //
  396. static OSStatus
  397. MouseMoved( HIWebView* inView, EventRef inEvent )
  398. {
  399. NSEvent *kitEvent = WKCreateNSEventWithCarbonMouseMoveEvent(inEvent, inView->fKitWindow);
  400. [inView->fKitWindow sendEvent:kitEvent];
  401. [kitEvent release];
  402. return noErr;
  403. }
  404. //----------------------------------------------------------------------------------
  405. // MouseDragged
  406. //----------------------------------------------------------------------------------
  407. //
  408. static OSStatus
  409. MouseDragged( HIWebView* inView, EventRef inEvent )
  410. {
  411. NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
  412. [inView->fKitWindow sendEvent:kitEvent];
  413. [kitEvent release];
  414. return noErr;
  415. }
  416. //----------------------------------------------------------------------------------
  417. // MouseDragged
  418. //----------------------------------------------------------------------------------
  419. //
  420. static OSStatus
  421. MouseWheelMoved( HIWebView* inView, EventRef inEvent )
  422. {
  423. NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
  424. [inView->fKitWindow sendEvent:kitEvent];
  425. [kitEvent release];
  426. return noErr;
  427. }
  428. //----------------------------------------------------------------------------------
  429. // ContextMenuClick
  430. //----------------------------------------------------------------------------------
  431. //
  432. static OSStatus
  433. ContextMenuClick( HIWebView* inView, EventRef inEvent )
  434. {
  435. NSView *webView = inView->fWebView;
  436. NSWindow *window = [webView window];
  437. // Get the point out of the event.
  438. HIPoint point;
  439. GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point);
  440. HIViewConvertPoint(&point, inView->fViewRef, NULL);
  441. // Flip the Y coordinate, since Carbon is flipped relative to the AppKit.
  442. NSPoint location = NSMakePoint(point.x, [window frame].size.height - point.y);
  443. // Make up an event with the point and send it to the window.
  444. NSEvent *kitEvent = [NSEvent mouseEventWithType:NSRightMouseDown
  445. location:location
  446. modifierFlags:0
  447. timestamp:GetEventTime(inEvent)
  448. windowNumber:[window windowNumber]
  449. context:0
  450. eventNumber:0
  451. clickCount:1
  452. pressure:0];
  453. [inView->fKitWindow sendEvent:kitEvent];
  454. return noErr;
  455. }
  456. //----------------------------------------------------------------------------------
  457. // GetKind
  458. //----------------------------------------------------------------------------------
  459. //
  460. static ControlKind
  461. GetKind()
  462. {
  463. const ControlKind kMyKind = { 'appl', 'wbvw' };
  464. return kMyKind;
  465. }
  466. //----------------------------------------------------------------------------------
  467. // BoundsChanged
  468. //----------------------------------------------------------------------------------
  469. //
  470. static void
  471. BoundsChanged(
  472. HIWebView* inView,
  473. UInt32 inOptions,
  474. const HIRect* inOriginalBounds,
  475. const HIRect* inCurrentBounds )
  476. {
  477. if ( inView->fWebView )
  478. {
  479. SyncFrame( inView );
  480. }
  481. }
  482. //----------------------------------------------------------------------------------
  483. // OwningWindowChanged
  484. //----------------------------------------------------------------------------------
  485. //
  486. static void
  487. OwningWindowChanged(
  488. HIWebView* view,
  489. WindowRef oldWindow,
  490. WindowRef newWindow )
  491. {
  492. if ( newWindow ){
  493. WindowAttributes attrs;
  494. OSStatus err = GetWindowProperty(newWindow, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &view->fKitWindow);
  495. if ( err != noErr )
  496. {
  497. const EventTypeSpec kWindowEvents[] = {
  498. { kEventClassWindow, kEventWindowClosed },
  499. { kEventClassMouse, kEventMouseMoved },
  500. { kEventClassMouse, kEventMouseUp },
  501. { kEventClassMouse, kEventMouseDragged },
  502. { kEventClassMouse, kEventMouseWheelMoved },
  503. { kEventClassKeyboard, kEventRawKeyDown },
  504. { kEventClassKeyboard, kEventRawKeyRepeat },
  505. { kEventClassKeyboard, kEventRawKeyUp },
  506. { kEventClassControl, kEventControlClick },
  507. };
  508. view->fKitWindow = [[CarbonWindowAdapter alloc] initWithCarbonWindowRef: newWindow takingOwnership: NO disableOrdering:NO carbon:YES];
  509. SetWindowProperty(newWindow, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), &view->fKitWindow);
  510. InstallWindowEventHandler( newWindow, WindowHandler, GetEventTypeCount( kWindowEvents ), kWindowEvents, newWindow, NULL );
  511. }
  512. [[view->fKitWindow contentView] addSubview:view->fWebView];
  513. GetWindowAttributes( newWindow, &attrs );
  514. view->fIsComposited = ( ( attrs & kWindowCompositingAttribute ) != 0 );
  515. SyncFrame( view );
  516. }
  517. else
  518. {
  519. // Be sure to detach the cocoa view, too.
  520. if ( view->fWebView )
  521. [view->fWebView removeFromSuperview];
  522. view->fKitWindow = NULL; // break the ties that bind
  523. }
  524. }
  525. //-------------------------------------------------------------------------------------
  526. // WindowHandler
  527. //-------------------------------------------------------------------------------------
  528. // Redirect mouse events to the views beneath them. This is required for WebKit to work
  529. // properly. We install it once per window. We also tap into window close to release
  530. // the NSWindow that shadows our Carbon window.
  531. //
  532. static OSStatus
  533. WindowHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
  534. {
  535. WindowRef window = (WindowRef)inUserData;
  536. OSStatus result = eventNotHandledErr;
  537. switch( GetEventClass( inEvent ) )
  538. {
  539. case kEventClassControl:
  540. {
  541. switch( GetEventKind( inEvent ) )
  542. {
  543. case kEventControlClick:
  544. {
  545. CarbonWindowAdapter *kitWindow;
  546. OSStatus err;
  547. err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
  548. // We must be outside the HIWebView, relinquish focus.
  549. [kitWindow relinquishFocus];
  550. }
  551. break;
  552. }
  553. }
  554. break;
  555. case kEventClassKeyboard:
  556. {
  557. NSWindow* kitWindow;
  558. OSStatus err;
  559. NSEvent* kitEvent;
  560. // if the first responder in the kit window is something other than the
  561. // window, we assume a subview of the webview is focused. we must send
  562. // the event to the window so that it goes through the kit's normal TSM
  563. // logic, and -- more importantly -- allows any delegates associated
  564. // with the first responder to have a chance at the event.
  565. err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
  566. if ( err == noErr )
  567. {
  568. NSResponder* responder = [kitWindow firstResponder];
  569. if ( responder != kitWindow )
  570. {
  571. kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
  572. [kitWindow sendEvent:kitEvent];
  573. [kitEvent release];
  574. result = noErr;
  575. }
  576. }
  577. }
  578. break;
  579. case kEventClassWindow:
  580. {
  581. NSWindow* kitWindow;
  582. OSStatus err;
  583. err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
  584. if ( err == noErr )
  585. {
  586. [kitWindow _removeWindowRef];
  587. [kitWindow close];
  588. }
  589. result = noErr;
  590. }
  591. break;
  592. case kEventClassMouse:
  593. switch (GetEventKind(inEvent))
  594. {
  595. case kEventMouseMoved:
  596. {
  597. Point where;
  598. GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where);
  599. WindowRef temp;
  600. FindWindow(where, &temp);
  601. if (temp == window)
  602. {
  603. Rect bounds;
  604. GetWindowBounds(window, kWindowStructureRgn, &bounds);
  605. where.h -= bounds.left;
  606. where.v -= bounds.top;
  607. SetEventParameter(inEvent, kEventParamWindowRef, typeWindowRef, sizeof(WindowRef), &window);
  608. SetEventParameter(inEvent, kEventParamWindowMouseLocation, typeQDPoint, sizeof(Point), &where);
  609. OSStatus err = noErr;
  610. HIViewRef view = NULL;
  611. err = HIViewGetViewForMouseEvent(HIViewGetRoot(window), inEvent, &view);
  612. if (err == noErr && view && HIObjectIsOfClass((HIObjectRef)view, kHIWebViewClassID))
  613. result = SendEventToEventTargetWithOptions(inEvent, HIObjectGetEventTarget((HIObjectRef)view), kEventTargetDontPropagate);
  614. }
  615. }
  616. break;
  617. case kEventMouseUp:
  618. case kEventMouseDragged:
  619. case kEventMouseWheelMoved:
  620. {
  621. OSStatus err = noErr;
  622. HIViewRef view = NULL;
  623. err = HIViewGetViewForMouseEvent(HIViewGetRoot(window), inEvent, &view);
  624. if (err == noErr && view && HIObjectIsOfClass((HIObjectRef)view, kHIWebViewClassID))
  625. result = SendEventToEventTargetWithOptions(inEvent, HIObjectGetEventTarget((HIObjectRef)view), kEventTargetDontPropagate);
  626. }
  627. break;
  628. }
  629. break;
  630. }
  631. return result;
  632. }
  633. //----------------------------------------------------------------------------------
  634. // SyncFrame
  635. //----------------------------------------------------------------------------------
  636. //
  637. static void
  638. SyncFrame( HIWebView* inView )
  639. {
  640. HIViewRef parent = HIViewGetSuperview( inView->fViewRef );
  641. if ( parent )
  642. {
  643. if ( inView->fIsComposited )
  644. {
  645. HIRect frame;
  646. HIRect parentBounds;
  647. NSPoint origin;
  648. HIViewGetFrame( inView->fViewRef, &frame );
  649. HIViewGetBounds( parent, &parentBounds );
  650. origin.x = frame.origin.x;
  651. origin.y = parentBounds.size.height - CGRectGetMaxY( frame );
  652. // printf( "syncing to (%g %g) (%g %g)\n", origin.x, origin.y,
  653. // frame.size.width, frame.size.height );
  654. [inView->fWebView setFrameOrigin: origin];
  655. [inView->fWebView setFrameSize: *(NSSize*)&frame.size];
  656. }
  657. else
  658. {
  659. GrafPtr port = GetWindowPort( GetControlOwner( inView->fViewRef ) );
  660. PixMapHandle portPix = GetPortPixMap( port );
  661. Rect bounds;
  662. HIRect rootFrame;
  663. HIRect frame;
  664. GetControlBounds( inView->fViewRef, &bounds );
  665. OffsetRect( &bounds, -(**portPix).bounds.left, -(**portPix).bounds.top );
  666. // printf( "control lives at %d %d %d %d in window-coords\n", bounds.top, bounds.left,
  667. // bounds.bottom, bounds.right );
  668. HIViewGetFrame( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), &rootFrame );
  669. frame.origin.x = bounds.left;
  670. frame.origin.y = rootFrame.size.height - bounds.bottom;
  671. frame.size.width = bounds.right - bounds.left;
  672. frame.size.height = bounds.bottom - bounds.top;
  673. // printf( " before frame convert (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,
  674. // frame.size.width, frame.size.height );
  675. [inView->fWebView convertRect:*(NSRect*)&frame fromView:nil];
  676. // printf( " moving web view to (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,
  677. // frame.size.width, frame.size.height );
  678. [inView->fWebView setFrameOrigin: *(NSPoint*)&frame.origin];
  679. [inView->fWebView setFrameSize: *(NSSize*)&frame.size];
  680. }
  681. }
  682. }
  683. //----------------------------------------------------------------------------------
  684. // SetFocusPart
  685. //----------------------------------------------------------------------------------
  686. //
  687. static OSStatus
  688. SetFocusPart(
  689. HIWebView* view,
  690. ControlPartCode desiredFocus,
  691. RgnHandle invalidRgn,
  692. Boolean focusEverything,
  693. ControlPartCode* actualFocus )
  694. {
  695. NSView * freshlyMadeFirstResponderView;
  696. SInt32 partCodeToReturn;
  697. // Do what Carbon is telling us to do.
  698. if ( desiredFocus == kControlFocusNoPart )
  699. {
  700. // Relinquish the keyboard focus.
  701. RelinquishFocus( view, true ); //(autodisplay ? YES : NO));
  702. freshlyMadeFirstResponderView = nil;
  703. partCodeToReturn = kControlFocusNoPart;
  704. //NSLog(@"Relinquished the key focus because we have no choice.");
  705. }
  706. else if ( desiredFocus == kControlFocusNextPart || desiredFocus == kControlFocusPrevPart )
  707. {
  708. BOOL goForward = (desiredFocus == kControlFocusNextPart );
  709. // Advance the keyboard focus, maybe right off of this view. Maybe a subview of this one already has the keyboard focus, maybe not.
  710. freshlyMadeFirstResponderView = AdvanceFocus( view, goForward );
  711. if (freshlyMadeFirstResponderView)
  712. partCodeToReturn = desiredFocus;
  713. else
  714. partCodeToReturn = kControlFocusNoPart;
  715. //NSLog(freshlyMadeFirstResponderView ? @"Advanced the key focus." : @"Relinquished the key focus.");
  716. }
  717. else
  718. {
  719. // What's this?
  720. if (desiredFocus != kControlIndicatorPart) {
  721. check(false);
  722. }
  723. freshlyMadeFirstResponderView = nil;
  724. partCodeToReturn = desiredFocus;
  725. }
  726. view->fFirstResponder = freshlyMadeFirstResponderView;
  727. *actualFocus = partCodeToReturn;
  728. // Done.
  729. return noErr;
  730. }
  731. //----------------------------------------------------------------------------------
  732. // AdvanceFocus
  733. //----------------------------------------------------------------------------------
  734. //
  735. static NSView*
  736. AdvanceFocus( HIWebView* view, bool forward )
  737. {
  738. NSResponder* oldFirstResponder;
  739. NSView* currentKeyView;
  740. NSView* viewWeMadeFirstResponder;
  741. // Focus on some part (subview) of this control (view). Maybe
  742. // a subview of this one already has the keyboard focus, maybe not.
  743. oldFirstResponder = [view->fKitWindow firstResponder];
  744. // If we tab out of our NSView, it will no longer be the responder
  745. // when we get here. We'll try this trick for now. We might need to
  746. // tag the view appropriately.
  747. if ( view->fFirstResponder && ( (NSResponder*)view->fFirstResponder != oldFirstResponder ) )
  748. {
  749. return NULL;
  750. }
  751. if ( [oldFirstResponder isKindOfClass:[NSView class]] )
  752. {
  753. NSView* tentativeNewKeyView;
  754. // Some view in this window already has the keyboard focus. It better at least be a subview of this one.
  755. NSView* oldFirstResponderView = (NSView *)oldFirstResponder;
  756. check( [oldFirstResponderView isDescendantOf:view->fWebView] );
  757. if ( oldFirstResponderView != view->fFirstResponder
  758. && ![oldFirstResponderView isDescendantOf:view->fFirstResponder] )
  759. {
  760. // Despite our efforts to record what view we made the first responder
  761. // (for use in the next paragraph) we couldn't keep up because the user
  762. // has clicked in a text field to make it the key focus, instead of using
  763. // the tab key. Find a control on which it's reasonable to invoke
  764. // -[NSView nextValidKeyView], taking into account the fact that
  765. // NSTextFields always pass on first-respondership to a temporarily-
  766. // contained NSTextView.
  767. NSView *viewBeingTested;
  768. currentKeyView = oldFirstResponderView;
  769. viewBeingTested = currentKeyView;
  770. while ( viewBeingTested != view->fWebView )
  771. {
  772. if ( [viewBeingTested isKindOfClass:[NSTextField class]] )
  773. {
  774. currentKeyView = viewBeingTested;
  775. break;
  776. }
  777. else
  778. {
  779. viewBeingTested = [viewBeingTested superview];
  780. }
  781. }
  782. }
  783. else
  784. {
  785. // We recorded which view we made into the first responder the
  786. // last time the user hit the tab key, and nothing has invalidated
  787. // our recorded value since.
  788. currentKeyView = view->fFirstResponder;
  789. }
  790. // Try to move on to the next or previous key view. We use the laboriously
  791. // recorded/figured currentKeyView instead of just oldFirstResponder as the
  792. // jumping-off-point when searching for the next valid key view. This is so
  793. // we don't get fooled if we recently made some view the first responder, but
  794. // it passed on first-responder-ness to some temporary subview.
  795. // You can't put normal views in a window with Carbon-control-wrapped views.
  796. // Stuff like this would break. M.P. Notice - 12/2/00
  797. tentativeNewKeyView = forward ? [currentKeyView nextValidKeyView] : [currentKeyView previousValidKeyView];
  798. if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] )
  799. {
  800. // The user has tabbed to another subview of this control view. Change the keyboard focus.
  801. //NSLog(@"Tabbed to the next or previous key view.");
  802. [view->fKitWindow makeFirstResponder:tentativeNewKeyView];
  803. viewWeMadeFirstResponder = tentativeNewKeyView;
  804. }
  805. else
  806. {
  807. // The user has tabbed past the subviews of this control view. The window is the first responder now.
  808. //NSLog(@"Tabbed past the first or last key view.");
  809. [view->fKitWindow makeFirstResponder:view->fKitWindow];
  810. viewWeMadeFirstResponder = nil;
  811. }
  812. }
  813. else
  814. {
  815. // No view in this window has the keyboard focus. This view should
  816. // try to select one of its key subviews. We're not interested in
  817. // the subviews of sibling views here.
  818. //NSLog(@"No keyboard focus in window. Attempting to set...");
  819. NSView *tentativeNewKeyView;
  820. check(oldFirstResponder==fKitWindow);
  821. if ( [view->fWebView acceptsFirstResponder] )
  822. tentativeNewKeyView = view->fWebView;
  823. else
  824. tentativeNewKeyView = [view->fWebView nextValidKeyView];
  825. if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] )
  826. {
  827. // This control view has at least one subview that can take the keyboard focus.
  828. if ( !forward )
  829. {
  830. // The user has tabbed into this control view backwards. Find
  831. // and select the last subview of this one that can take the
  832. // keyboard focus. Watch out for loops of valid key views.
  833. NSView *firstTentativeNewKeyView = tentativeNewKeyView;
  834. NSView *nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView];
  835. while ( nextTentativeNewKeyView
  836. && [nextTentativeNewKeyView isDescendantOf:view->fWebView]
  837. && nextTentativeNewKeyView!=firstTentativeNewKeyView)
  838. {
  839. tentativeNewKeyView = nextTentativeNewKeyView;
  840. nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView];
  841. }
  842. }
  843. // Set the keyboard focus.
  844. //NSLog(@"Tabbed into the first or last key view.");
  845. [view->fKitWindow makeFirstResponder:tentativeNewKeyView];
  846. viewWeMadeFirstResponder = tentativeNewKeyView;
  847. }
  848. else
  849. {
  850. // This control view has no subviews that can take the keyboard focus.
  851. //NSLog(@"Can't tab into this view.");
  852. viewWeMadeFirstResponder = nil;
  853. }
  854. }
  855. // Done.
  856. return viewWeMadeFirstResponder;
  857. }
  858. //----------------------------------------------------------------------------------
  859. // RelinquishFocus
  860. //----------------------------------------------------------------------------------
  861. //
  862. static void
  863. RelinquishFocus( HIWebView* view, bool inAutodisplay )
  864. {
  865. NSResponder* firstResponder;
  866. // Apparently Carbon thinks that some subview of this control view has the keyboard focus,
  867. // or we wouldn't be being asked to relinquish focus.
  868. firstResponder = [view->fKitWindow firstResponder];
  869. if ( [firstResponder isKindOfClass:[NSView class]] )
  870. {
  871. // Some subview of this control view really is the first responder right now.
  872. check( [(NSView *)firstResponder isDescendantOf:view->fWebView] );
  873. // Make the window the first responder, so that no view is the key view.
  874. [view->fKitWindow makeFirstResponder:view->fKitWindow];
  875. // If this control is not allowed to do autodisplay, don't let
  876. // it autodisplay any just-changed focus rings or text on the
  877. // next go around the event loop. I'm probably clearing more
  878. // dirty rects than I have to, but it doesn't seem to hurt in
  879. // the print panel accessory view case, and I don't have time
  880. // to figure out exactly what -[NSCell _setKeyboardFocusRingNeedsDisplay]
  881. // is doing when invoked indirectly from -makeFirstResponder up above. M.P. Notice - 12/4/00
  882. if ( !inAutodisplay )
  883. [[view->fWebView opaqueAncestor] _clearDirtyRectsForTree];
  884. }
  885. else
  886. {
  887. // The Cocoa first responder does not correspond to the Carbon
  888. // control that has the keyboard focus. This can happen when
  889. // you've closed a dialog by hitting return in an NSTextView
  890. // that's a subview of this one; Cocoa closed the window, and
  891. // now Carbon is telling this control to relinquish the focus
  892. // as it's being disposed. There's nothing to do.
  893. check(firstResponder==window);
  894. }
  895. }
  896. //----------------------------------------------------------------------------------
  897. // ActiveStateChanged
  898. //----------------------------------------------------------------------------------
  899. //
  900. static void
  901. ActiveStateChanged( HIWebView* view )
  902. {
  903. if ( [view->fWebView respondsToSelector:@selector(setEnabled)] )
  904. {
  905. [(NSControl*)view->fWebView setEnabled: IsControlEnabled( view->fViewRef )];
  906. HIViewSetNeedsDisplay( view->fViewRef, true );
  907. }
  908. }
  909. //----------------------------------------------------------------------------------
  910. // ProcessCommand
  911. //----------------------------------------------------------------------------------
  912. //
  913. static OSStatus
  914. ProcessCommand( HIWebView* inView, const HICommand* inCommand )
  915. {
  916. OSStatus result = eventNotHandledErr;
  917. NSResponder* resp;
  918. resp = [inView->fKitWindow firstResponder];
  919. if ( [resp isKindOfClass:[NSView class]] )
  920. {
  921. NSView* respView = (NSView*)resp;
  922. if ( respView == inView->fWebView
  923. || [respView isDescendantOf: inView->fWebView] )
  924. {
  925. switch ( inCommand->commandID )
  926. {
  927. case kHICommandCut:
  928. case kHICommandCopy:
  929. case kHICommandPaste:
  930. case kHICommandClear:
  931. case kHICommandSelectAll:
  932. {
  933. SEL selector = _NSSelectorForHICommand( inCommand );
  934. if ( [respView respondsToSelector:selector] )
  935. {
  936. [respView performSelector:selector withObject:nil];
  937. result = noErr;
  938. }
  939. }
  940. break;
  941. }
  942. }
  943. }
  944. return result;
  945. }
  946. //----------------------------------------------------------------------------------
  947. // UpdateCommandStatus
  948. //----------------------------------------------------------------------------------
  949. //
  950. static OSStatus
  951. UpdateCommandStatus( HIWebView* inView, const HICommand* inCommand )
  952. {
  953. OSStatus result = eventNotHandledErr;
  954. MenuItemProxy* proxy = NULL;
  955. NSResponder* resp;
  956. resp = [inView->fKitWindow firstResponder];
  957. if ( [resp isKindOfClass:[NSView class]] )
  958. {
  959. NSView* respView = (NSView*)resp;
  960. if ( respView == inView->fWebView
  961. || [respView isDescendantOf: inView->fWebView] )
  962. {
  963. if ( inCommand->attributes & kHICommandFromMenu )
  964. {
  965. SEL selector = _NSSelectorForHICommand( inCommand );
  966. if ( selector )
  967. {
  968. if ( [resp respondsToSelector: selector] )
  969. {
  970. proxy = [[MenuItemProxy alloc] initWithAction: selector];
  971. // Can't use -performSelector:withObject: here because the method we're calling returns BOOL, while
  972. // -performSelector:withObject:'s return value is assumed to be an id.
  973. if (wtfObjcMsgSend<BOOL>(resp, @selector(validateUserInterfaceItem:), proxy))
  974. EnableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex );
  975. else
  976. DisableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex );
  977. result = noErr;
  978. }
  979. }
  980. }
  981. }
  982. }
  983. if ( proxy )
  984. [proxy release];
  985. return result;
  986. }
  987. // Blatantly stolen from AppKit and cropped a bit
  988. //----------------------------------------------------------------------------------
  989. // _NSSelectorForHICommand
  990. //----------------------------------------------------------------------------------
  991. //
  992. static SEL
  993. _NSSelectorForHICommand( const HICommand* inCommand )
  994. {
  995. switch ( inCommand->commandID )
  996. {
  997. case kHICommandUndo: return @selector(undo:);
  998. case kHICommandRedo: return @selector(redo:);
  999. case kHICommandCut : return @selector(cut:);
  1000. case kHICommandCopy : return @selector(copy:);
  1001. case kHICommandPaste: return @selector(paste:);
  1002. case kHICommandClear: return @selector(delete:);
  1003. case kHICommandSelectAll: return @selector(selectAll:);
  1004. default: return NULL;
  1005. }
  1006. return NULL;
  1007. }
  1008. //-----------------------------------------------------------------------------------
  1009. // HIWebViewEventHandler
  1010. //-----------------------------------------------------------------------------------
  1011. // Our object's virtual event handler method. I'm not sure if we need this these days.
  1012. // We used to do various things with it, but those days are long gone...
  1013. //
  1014. static OSStatus
  1015. HIWebViewEventHandler(
  1016. EventHandlerCallRef inCallRef,
  1017. EventRef inEvent,
  1018. void * inUserData )
  1019. {
  1020. OSStatus result = eventNotHandledErr;
  1021. HIPoint where;
  1022. OSType tag;
  1023. void * ptr;
  1024. Size size;
  1025. UInt32 features;
  1026. RgnHandle region = NULL;
  1027. ControlPartCode part;
  1028. HIWebView* view = (HIWebView*)inUserData;
  1029. // [NSApp setWindowsNeedUpdate:YES] must be called before events so that ActivateTSMDocument is called to set an active document.
  1030. // Without an active document, TSM will use a default document which uses a bottom-line input window which we don't want.
  1031. [NSApp setWindowsNeedUpdate:YES];
  1032. switch ( GetEventClass( inEvent ) )
  1033. {
  1034. case kEventClassHIObject:
  1035. switch ( GetEventKind( inEvent ) )
  1036. {
  1037. case kEventHIObjectConstruct:
  1038. {
  1039. HIObjectRef object;
  1040. result = GetEventParameter( inEvent, kEventParamHIObjectInstance,
  1041. typeHIObjectRef, NULL, sizeof( HIObjectRef ), NULL, &object );
  1042. require_noerr( result, MissingParameter );
  1043. // on entry for our construct event, we're passed the
  1044. // creation proc we registered with for this class.
  1045. // we use it now to create the instance, and then we
  1046. // replace the instance parameter data with said instance
  1047. // as type void.
  1048. view = HIWebViewConstructor( (HIViewRef)object );
  1049. if ( view )
  1050. {
  1051. SetEventParameter( inEvent, kEventParamHIObjectInstance,
  1052. typeVoidPtr, sizeof( void * ), &view );
  1053. }
  1054. }
  1055. break;
  1056. case kEventHIObjectDestruct:
  1057. HIWebViewDestructor( view );
  1058. // result is unimportant
  1059. break;
  1060. }
  1061. break;
  1062. case kEventClassKeyboard:
  1063. {
  1064. NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
  1065. [view->fKitWindow sendSuperEvent:kitEvent];
  1066. [kitEvent release];
  1067. result = noErr;
  1068. }
  1069. break;
  1070. case kEventClassMouse:
  1071. switch ( GetEventKind( inEvent ) )
  1072. {
  1073. case kEventMouseUp:
  1074. result = MouseUp( view, inEvent );
  1075. break;
  1076. case kEventMouseWheelMoved:
  1077. result = MouseWheelMoved( view, inEvent );
  1078. break;
  1079. case kEventMouseMoved:
  1080. result = MouseMoved( view, inEvent );
  1081. break;
  1082. case kEventMouseDragged:
  1083. result = MouseDragged( view, inEvent );
  1084. break;
  1085. }
  1086. break;
  1087. case kEventClassCommand:
  1088. {
  1089. HICommand command;
  1090. result = GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL,
  1091. sizeof( HICommand ), NULL, &command );
  1092. require_noerr( result, MissingParameter );
  1093. switch ( GetEventKind( inEvent ) )
  1094. {
  1095. case kEventCommandProcess:
  1096. result = ProcessCommand( view, &command );
  1097. break;
  1098. case kEventCommandUpdateStatus:
  1099. result = UpdateCommandStatus( view, &command );
  1100. break;
  1101. }
  1102. }
  1103. break;
  1104. case kEventClassControl:
  1105. switch ( GetEventKind( inEvent ) )
  1106. {
  1107. case kEventControlInitialize:
  1108. features = GetBehaviors();
  1109. SetEventParameter( inEvent, kEventParamControlFeatures, typeUInt32,
  1110. sizeof( UInt32 ), &features );
  1111. result = noErr;
  1112. break;
  1113. case kEventControlDraw:
  1114. {
  1115. CGContextRef context = NULL;
  1116. GetEventParameter( inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL,
  1117. sizeof( RgnHandle ), NULL, &region );
  1118. GetEventParameter( inEvent, kEventParamCGContextRef, typeCGContextRef, NULL,
  1119. sizeof( CGContextRef ), NULL, &context );
  1120. Draw( view, region, context );
  1121. result = noErr;
  1122. }
  1123. break;
  1124. case kEventControlHitTest:
  1125. GetEventParameter( inEvent, kEventParamMouseLocation, typeHIPoint, NULL,
  1126. sizeof( HIPoint ), NULL, &where );
  1127. part = HitTest( view, &where );
  1128. SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, sizeof( ControlPartCode ), &part );
  1129. result = noErr;
  1130. break;
  1131. case kEventControlGetPartRegion:
  1132. GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL,
  1133. sizeof( ControlPartCode ), NULL, &part );
  1134. GetEventParameter( inEvent, kEventParamControlRegion, typeQDRgnHandle, NULL,
  1135. sizeof( RgnHandle ), NULL, &region );
  1136. result = GetRegion( view, part, region );
  1137. break;
  1138. case kEventControlGetData:
  1139. GetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, NULL, sizeof(ControlPartCode), NULL, &part);
  1140. GetEventParameter(inEvent, kEventParamControlDataTag, typeEnumeration, NULL, sizeof(OSType), NULL, &tag);
  1141. GetEventParameter(inEvent, kEventParamControlDataBuffer, typePtr, NULL, sizeof(Ptr), NULL, &ptr);
  1142. GetEventParameter(inEvent, kEventParamControlDataBufferSize, typeByteCount, NULL, sizeof(Size), NULL, &size);
  1143. if (tag == kControlKindTag) {
  1144. Size outSize;
  1145. result = noErr;
  1146. if (ptr) {
  1147. if (size != sizeof(ControlKind))
  1148. result = errDataSizeMismatch;
  1149. else
  1150. (*(ControlKind *)ptr) = GetKind();
  1151. }
  1152. outSize = sizeof(ControlKind);
  1153. SetEventParameter(inEvent, kEventParamControlDataBufferSize, typeByteCount, sizeof(Size), &outSize);
  1154. }
  1155. break;
  1156. case kEventControlBoundsChanged:
  1157. {
  1158. HIRect prevRect, currRect;
  1159. UInt32 attrs;
  1160. GetEventParameter( inEvent, kEventParamAttributes, typeUInt32, NULL,
  1161. sizeof( UInt32 ), NULL, &attrs );
  1162. GetEventParameter( inEvent, kEventParamOriginalBounds, typeHIRect, NULL,
  1163. sizeof( HIRect ), NULL, &prevRect );
  1164. GetEventParameter( inEvent, kEventParamCurrentBounds, typeHIRect, NULL,
  1165. sizeof( HIRect ), NULL, &currRect );
  1166. BoundsChanged( view, attrs, &prevRect, &currRect );
  1167. result = noErr;
  1168. }
  1169. break;
  1170. case kEventControlActivate:
  1171. ActiveStateChanged( view );
  1172. result = noErr;
  1173. break;
  1174. case kEventControlDeactivate:
  1175. ActiveStateChanged( view );
  1176. result = noErr;
  1177. break;
  1178. case kEventControlOwningWindowChanged:
  1179. {
  1180. WindowRef fromWindow, toWindow;
  1181. result = GetEventParameter( inEvent, kEventParamControlOriginalOwningWindow, typeWindowRef, NULL,
  1182. sizeof( WindowRef ), NULL, &fromWindow );
  1183. require_noerr( result, MissingParameter );
  1184. result = GetEventParameter( inEvent, kEventParamControlCurrentOwningWindow, typeWindowRef, NULL,
  1185. sizeof( WindowRef ), NULL, &toWindow );
  1186. require_noerr( result, MissingParameter );
  1187. OwningWindowChanged( view, fromWindow, toWindow );
  1188. result = noErr;
  1189. }
  1190. break;
  1191. case kEventControlClick:
  1192. result = Click( view, inEvent );
  1193. break;
  1194. case kEventControlContextualMenuClick:
  1195. result = ContextMenuClick( view, inEvent );
  1196. break;
  1197. case kEventControlSetFocusPart:
  1198. {
  1199. ControlPartCode desiredFocus;
  1200. RgnHandle invalidRgn;
  1201. Boolean focusEverything;
  1202. ControlPartCode actualFocus;
  1203. result = GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL,
  1204. sizeof( ControlPartCode ), NULL, &desiredFocus );
  1205. require_noerr( result, MissingParameter );
  1206. GetEventParameter( inEvent, kEventParamControlInvalRgn, typeQDRgnHandle, NULL,
  1207. sizeof( RgnHandle ), NULL, &invalidRgn );
  1208. focusEverything = false; // a good default in case the parameter doesn't exist
  1209. GetEventParameter( inEvent, kEventParamControlFocusEverything, typeBoolean, NULL,
  1210. sizeof( Boolean ), NULL, &focusEverything );
  1211. result = SetFocusPart( view, desiredFocus, invalidRgn, focusEverything, &actualFocus );
  1212. if ( result == noErr )
  1213. verify_noerr( SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode,
  1214. sizeof( ControlPartCode ), &actualFocus ) );
  1215. }
  1216. break;
  1217. // some other kind of Control event
  1218. default:
  1219. break;
  1220. }
  1221. break;
  1222. // some other event class
  1223. default:
  1224. break;
  1225. }
  1226. MissingParameter:
  1227. return result;
  1228. }
  1229. static void UpdateObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info);
  1230. static void
  1231. StartUpdateObserver( HIWebView* view )
  1232. {
  1233. CFRunLoopObserverContext context;
  1234. CFRunLoopObserverRef observer;
  1235. CFRunLoopRef mainRunLoop;
  1236. check( view->fIsComposited == false );
  1237. check( view->fUpdateObserver == NULL );
  1238. context.version = 0;
  1239. context.info = view;
  1240. context.retain = NULL;
  1241. context.release = NULL;
  1242. context.copyDescription = NULL;
  1243. mainRunLoop = (CFRunLoopRef)GetCFRunLoopFromEventLoop( GetMainEventLoop() );
  1244. observer = CFRunLoopObserverCreate( NULL, kCFRunLoopEntry | kCFRunLoopBeforeWaiting, true, 0, UpdateObserver, &context );
  1245. CFRunLoopAddObserver( mainRunLoop, observer, kCFRunLoopCommonModes );
  1246. view->fUpdateObserver = observer;
  1247. // printf( "Update observer started\n" );
  1248. }
  1249. static void
  1250. StopUpdateObserver( HIWebView* view )
  1251. {
  1252. check( view->fIsComposited == false );
  1253. check( view->fUpdateObserver != NULL );
  1254. CFRunLoopObserverInvalidate( view->fUpdateObserver );
  1255. CFRelease( view->fUpdateObserver );
  1256. view->fUpdateObserver = NULL;
  1257. // printf( "Update observer removed\n" );
  1258. }
  1259. static void
  1260. UpdateObserver( CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info )
  1261. {
  1262. HIWebView* view = (HIWebView*)info;
  1263. RgnHandle region = NewRgn();
  1264. // printf( "Update observer called\n" );
  1265. if ( region )
  1266. {
  1267. GetWindowRegion( GetControlOwner( view->fViewRef ), kWindowUpdateRgn, region );
  1268. if ( !EmptyRgn( region ) )
  1269. {
  1270. RgnHandle ourRgn = NewRgn();
  1271. Rect rect;
  1272. GetWindowBounds( GetControlOwner( view->fViewRef ), kWindowStructureRgn, &rect );
  1273. // printf( "Update region is non-empty\n" );
  1274. if ( ourRgn )
  1275. {
  1276. Rect rect;
  1277. GrafPtr savePort, port;
  1278. Point offset = { 0, 0 };
  1279. port = GetWindowPort( GetControlOwner( view->fViewRef ) );
  1280. GetPort( &savePort );
  1281. SetPort( port );
  1282. GlobalToLocal( &offset );
  1283. OffsetRgn( region, offset.h, offset.v );
  1284. GetControlBounds( view->fViewRef, &rect );
  1285. RectRgn( ourRgn, &rect );
  1286. // printf( "our control is at %d %d %d %d\n",
  1287. // rect.top, rect.left, rect.bottom, rect.right );
  1288. GetRegionBounds( region, &rect );
  1289. // printf( "region is at %d %d %d %d\n",
  1290. // rect.top, rect.left, rect.bottom, rect.right );
  1291. SectRgn( ourRgn, region, ourRgn );
  1292. GetRegionBounds( ourRgn, &rect );
  1293. // printf( "intersection is %d %d %d %d\n",
  1294. // rect.top, rect.left, rect.bottom, rect.right );
  1295. if ( !EmptyRgn( ourRgn ) )
  1296. {
  1297. RgnHandle saveVis = NewRgn();
  1298. // printf( "looks like we should draw\n" );
  1299. if ( saveVis )
  1300. {
  1301. // RGBColor kRedColor = { 0xffff, 0, 0 };
  1302. GetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), saveVis );
  1303. SetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), ourRgn );
  1304. // RGBForeColor( &kRedColor );
  1305. // PaintRgn( ourRgn );
  1306. // QDFlushPortBuffer( port, NULL );
  1307. // Delay( 15, NULL );
  1308. Draw1Control( view->fViewRef );
  1309. ValidWindowRgn( GetControlOwner( view->fViewRef ), ourRgn );
  1310. SetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), saveVis );
  1311. DisposeRgn( saveVis );
  1312. }
  1313. }
  1314. SetPort( savePort );
  1315. DisposeRgn( ourRgn );
  1316. }
  1317. }
  1318. DisposeRgn( region );
  1319. }
  1320. }
  1321. #endif