1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // Authors: Brian Alliet and Evan Jones
10 #define __private_extern__
11 #include <mach-o/dyld.h>
16 #include <java/lang/Object.h>
17 #include <java/lang/Error.h>
19 #include <org/xwt/plat/Darwin.h>
20 #include <org/xwt/plat/Darwin$CarbonSurface.h>
21 #include <org/xwt/plat/Darwin$GLCarbonSurface.h>
22 #include <org/xwt/plat/Darwin$GLCarbonPixelBuffer.h>
23 #include <org/xwt/plat/Darwin$CarbonMessage.h>
24 #include <org/xwt/plat/Darwin$CarbonOpenGL.h>
25 #include <org/xwt/plat/Darwin$FileDialogHelper.h>
26 #include <org/xwt/plat/GCJ$Retainer.h>
27 #include <org/xwt/HTTP$Proxy.h>
28 #include <org/xwt/util/Semaphore.h>
31 #include <objc/objc.h>
33 #include "DarwinCarbonHeaders.h"
35 #define XWT_CARBON_NO_BUNDLE_HACK
36 #ifdef XWT_CARBON_NO_BUNDLE_HACK
38 OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn);
39 OSErr CPSSetFrontProcess(ProcessSerialNumber *psn);
43 #include "DarwinWeakSymbols.h"
45 using namespace org::xwt::plat;
46 using gnu::gcj::RawData;
47 using org::xwt::util::Semaphore;
48 using java::lang::Object;
50 namespace org { namespace xwt { namespace plat {
53 using namespace darwin;
55 #pragma mark ------ Darwin Namespace ------
57 // We put everything that isn't in org.xwt.plat.Darwin in
58 // org.xwt.plat.darwin to prevent namespace conflicts
60 template <bool CHECK> static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; }
61 template <> static inline int CompileTimeCheck<true>() { return 0; }
62 const static int unichar_check = CompileTimeCheck<sizeof(jchar)==sizeof(UniChar)>();
64 void funcFailed(char *func,int r);
65 static inline void checkStatus(OSStatus r, char *func) { if(r != noErr) funcFailed(func,r); }
66 static inline void checkStatus(GLboolean b, char *func) { if(!b) funcFailed(func,-1); }
67 static inline void checkStatus(void *p, char *func) { if(!p) funcFailed(func,-1); }
69 jstring cfStringToJString(CFStringRef s) {
70 CFIndex length = CFStringGetLength(s);
71 CFRange range = CFRangeMake(0,length);
72 jstring js = JvAllocString(length);
73 UniChar *buf = (UniChar*)JvGetStringChars(js);
74 CFStringGetCharacters(s,range,buf);
78 #pragma mark ------ SmartCFString ------
82 void release() { if(p) CFRelease(p); }
83 void checkNull() { if(!p) throw new java::lang::Error(JvNewStringLatin1("CFString function failed")); }
86 SmartCFString() : p(0) { }
87 SmartCFString(const char *s) : p(0) { *this = s; }
88 SmartCFString(jstring js) : p(0) { *this = js; }
89 SmartCFString(CFStringRef cf) : p(0) { *this = cf; }
91 ~SmartCFString() { release(); }
93 SmartCFString& operator= (const char *s) {
96 p = CFStringCreateWithCString(kCFAllocatorDefault,s,kCFStringEncodingISOLatin1);
100 SmartCFString& operator= (jstring js) {
101 if(!js) return *this = "(null)";
103 UniChar *buf = (UniChar*) JvGetStringChars(js);
104 CFIndex length = js->length();
105 p = CFStringCreateWithCharacters(kCFAllocatorDefault,buf,length);
109 SmartCFString& operator= (CFStringRef cf) {
110 if(cf == NULL) return *this = "(null)";
115 operator CFStringRef() { return p; }
116 operator jstring() { return getJString(); }
118 jstring getJString() { return cfStringToJString(p); }
120 bool equals(const char *s) {
121 SmartCFString cfs(s);
125 bool equals(CFStringRef cfs) {
126 return CFStringCompare(p,cfs,0) == kCFCompareEqualTo;
130 // CHECKME: Is just making up your own four char codes really correct?
131 const static UInt32 kEventClassCarbonMessage = 'xwta';
132 const static UInt32 kEventCarbonMessage = 'xwtb';
133 const static UInt32 kEventParamCarbonMessage = 'xwtc';
135 OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
136 void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
140 jboolean Darwin::isJaguar() {
142 OSStatus r = Gestalt(gestaltSystemVersion, &version);
143 checkStatus(r,"Gestalt");
144 return version >= 0x1020;
147 void Darwin::linkMe() {
151 void Darwin$CarbonMessage::natInit() {
154 EventHandlerUPP upp = NewEventHandlerUPP(our_carbonMessageEventHandler);
155 EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
156 r = InstallEventHandler(GetApplicationEventTarget(),upp,1,&eventTypes,NULL,NULL);
157 checkStatus(r,"InstallEventHandler");
160 void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) {
164 GCJ$Retainer::retain(msg);
166 r = CreateEvent(kCFAllocatorDefault,kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
167 checkStatus(r,"CreateEvent");
168 r = SetEventParameter(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
169 checkStatus(r,"SetEventParameter");
170 r = PostEventToQueue(GetMainEventQueue(),event,kEventPriorityHigh);
171 checkStatus(r,"PostEventToQueue");
176 OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
177 UInt32 eKind = GetEventKind(e);
178 UInt32 eClass = GetEventClass(e);
180 Darwin$CarbonMessage *msg;
181 if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
182 return eventNotHandledErr;
183 r = GetEventParameter(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
184 checkStatus(r,"GetEventParameter");
186 GCJ$Retainer::release(msg);
191 #pragma mark ------ Utility Functions ------
193 void funcFailed(char *func,int r){
194 fprintf(stderr,"%s() failed (%d)\n",func,r);
198 #pragma mark ------ CarbonPicture Methods ------
200 #pragma mark ----- Carbon Surface Methods ----
203 void Darwin$CarbonSurface::natSyncCursor(jint n) {
205 // see Carbon.java for what these numbers mean
207 case 1: c = kThemeWatchCursor;
208 case 2: c = kThemePlusCursor;
209 case 3: c = kThemeIBeamCursor;
210 case 4: c = kThemePointingHandCursor;
211 case 5: c = kThemeOpenHandCursor;
212 case 6: c = kThemeResizeLeftRightCursor;
213 default: c = kThemeArrowCursor;
218 void Darwin$CarbonSurface::natSetInvisible(jboolean b) {
219 WindowRef window = (WindowRef) rawWindowRef;
220 fprintf(stderr,"Making window %s\n",b?"invisible":"visible");
221 if(b) HideWindow(window);
222 else ShowWindow(window);
225 void Darwin$CarbonSurface::nat_setMaximized(jboolean b) {
226 WindowRef window = (WindowRef) rawWindowRef;
227 Point ideal = { 10000, 10000 };
228 OSStatus r = ZoomWindowIdeal(window,(b?inZoomOut:inZoomIn),&ideal);
229 checkStatus(r,"ZoomWindowIdeal");
232 void Darwin$CarbonSurface::nat_setMinimized(jboolean b) {
233 WindowRef window = (WindowRef) rawWindowRef;
234 if((IsWindowCollapsed(window) ? 1 : 0) == (b ? 1 : 0)) return;
235 OSStatus r = CollapseWindow(window,b);
236 checkStatus(r,"CollapseWindow");
239 void Darwin$CarbonSurface::natSetTitleBarText(jstring js) {
240 SmartCFString s = js;
241 WindowRef window = (WindowRef) rawWindowRef;
242 SetWindowTitleWithCFString(window,s);
245 void Darwin$CarbonSurface::natToBack() {
246 WindowRef window = (WindowRef) rawWindowRef;
247 SendBehind(window,NULL);
250 void Darwin$CarbonSurface::natToFront() {
251 WindowRef window = (WindowRef) rawWindowRef;
252 fprintf(stderr,"SelectWindow()\n");
253 SelectWindow(window);
256 #pragma mark ---- Window Event Handler ----
258 static const EventTypeSpec eventTypeSpecs[] = {
259 // kEventClassCommand
260 // { kEventClassCommand, ??? },
263 { kEventClassWindow, kEventWindowUpdate },
264 { kEventClassWindow, kEventWindowBoundsChanged },
265 { kEventClassWindow, kEventWindowActivated },
266 { kEventClassWindow, kEventWindowDeactivated },
267 { kEventClassWindow, kEventWindowZoomed },
268 { kEventClassWindow, kEventWindowCollapsed },
269 { kEventClassWindow, kEventWindowExpanded },
270 { kEventClassWindow, kEventWindowClose },
271 { kEventClassWindow, kEventWindowClosed },
273 // kEventClassKeyboard
274 { kEventClassKeyboard, kEventRawKeyDown },
275 { kEventClassKeyboard, kEventRawKeyRepeat },
276 { kEventClassKeyboard, kEventRawKeyUp },
277 { kEventClassKeyboard, kEventRawKeyModifiersChanged },
280 { kEventClassMouse, kEventMouseDown },
281 { kEventClassMouse, kEventMouseUp },
282 { kEventClassMouse, kEventMouseMoved },
283 { kEventClassMouse, kEventMouseDragged },
284 { kEventClassMouse, kEventMouseWheelMoved },
287 OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
288 Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*) userData;
289 UInt32 eKind = GetEventKind(e);
290 UInt32 eClass = GetEventClass(e);
294 case kEventClassCommand:
296 // TODO: handle menu items
299 case kEventClassKeyboard:
301 case kEventRawKeyDown:
302 case kEventRawKeyRepeat:
303 case kEventRawKeyUp: {
307 r = GetEventParameter(e,kEventParamKeyCode,typeUInt32,NULL,sizeof(keyCode),NULL,&keyCode);
308 checkStatus(r,"GetEventParameter");
311 // These values were obtained by experimentation. I can't find any constants for them
312 // in the header files
313 case 126: js = JvNewStringLatin1("up"); break;
314 case 125: js = JvNewStringLatin1("down"); break;
315 case 124: js = JvNewStringLatin1("right"); break;
316 case 123: js = JvNewStringLatin1("left"); break;
317 case 122: js = JvNewStringLatin1("f1"); break;
318 case 120: js = JvNewStringLatin1("f2"); break;
319 case 99: js = JvNewStringLatin1("f3"); break;
320 case 118: js = JvNewStringLatin1("f4"); break;
321 case 96: js = JvNewStringLatin1("f5"); break;
322 case 97: js = JvNewStringLatin1("f6"); break;
323 case 98: js = JvNewStringLatin1("f7"); break;
324 case 100: js = JvNewStringLatin1("f8"); break;
325 case 101: js = JvNewStringLatin1("f9"); break;
326 case 109: js = JvNewStringLatin1("f10"); break;
327 case 103: js = JvNewStringLatin1("f11"); break;
328 case 111: js = JvNewStringLatin1("f12"); break;
329 case 105: js = JvNewStringLatin1("f13"); break;
330 case 114: js = JvNewStringLatin1("insert"); break;
331 case 117: js = JvNewStringLatin1("delete"); break;
332 case 116: js = JvNewStringLatin1("page_up"); break;
333 case 121: js = JvNewStringLatin1("page_down"); break;
334 case 115: js = JvNewStringLatin1("home"); break;
335 case 119: js = JvNewStringLatin1("end"); break;
336 case 71: js = JvNewStringLatin1("num_lock"); break;
337 case 53: js = JvNewStringLatin1("escape"); break;
338 case 51: js = JvNewStringLatin1("back_space"); break;
339 case 36: js = JvNewStringLatin1("enter"); break;
340 case 48: js = JvNewStringLatin1("tab"); break;
341 case 76: js = JvNewStringLatin1("enter"); break; // number pad enter
344 UInt32 modifiers = surface->modifiers;
345 r = GetEventParameter(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,0,&size,NULL);
346 checkStatus(r,"GetEventParameter");
347 if(size == 0 || (modifiers & controlKey && size>sizeof(UniChar))) return eventNotHandledErr;
349 js = JvAllocString(size/sizeof(UniChar));
350 UniChar *buf = (UniChar*)JvGetStringChars(js);
351 r = GetEventParameter(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,size,NULL,buf);
352 checkStatus(r,"GetEventParameter");
354 if(!buf[0]) return eventNotHandledErr; // shouldn't happen
355 // odd, when the ctrl key is pressed a-"`" become 1-31, this brings them back to the corect values
356 if(modifiers & controlKey && buf[0] < 32) buf[0] += 0x60;
361 if(eKind == kEventRawKeyUp)
362 surface->KeyReleased(js);
364 surface->KeyPressed(js);
367 case kEventRawKeyModifiersChanged: {
368 const static struct {
371 } modifiersTable[] = {
372 { shiftKey, JvNewStringLatin1("shift") },
373 { alphaLock, JvNewStringLatin1("caps_lock") },
374 { controlKey, JvNewStringLatin1("control") },
375 { optionKey, JvNewStringLatin1("alt") },
376 { kEventKeyModifierNumLockMask, JvNewStringLatin1("num_lock") },
380 UInt32 oldModifiers = (UInt32) surface->modifiers;
382 r = GetEventParameter(e,kEventParamKeyModifiers,typeUInt32,NULL,sizeof(newModifiers),NULL,&newModifiers);
383 checkStatus(r,"GetEventParameter");
384 surface->modifiers = (jint) newModifiers;
385 UInt32 changedModifiers = oldModifiers ^ newModifiers;
387 for(int i=0;modifiersTable[i].mask;i++) {
388 UInt32 mask = modifiersTable[i].mask;
389 if(!(changedModifiers & mask)) continue;
390 if(newModifiers & mask)
391 surface->KeyPressed(modifiersTable[i].xwtKey);
393 surface->KeyReleased(modifiersTable[i].xwtKey);
399 case kEventClassMouse:
400 // The default handler gets first dibs on mouse events
401 // (this catches the titlebar, resize box, etc)
402 r = CallNextEventHandler(handler, e);
403 if(r != eventNotHandledErr && eKind != kEventMouseMoved && eKind != kEventMouseDragged) return r;
406 case kEventMouseMoved:
407 case kEventMouseDragged: {
408 WindowRef window = (WindowRef) surface->rawWindowRef;
412 r = GetEventParameter(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
413 checkStatus(r,"GetEventParameter");
414 r = GetWindowBounds(window,kWindowContentRgn,&rect);
415 checkStatus(r,"GetWindowBounds");
416 surface->Move(p.h-rect.left,p.v-rect.top);
419 case kEventMouseDown:
420 case kEventMouseUp: {
421 EventMouseButton button;
424 r = GetEventParameter(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
425 checkStatus(r,"GetEventParameter");
426 r = GetEventParameter(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount);
427 checkStatus(r,"GetEventParameter");
430 case kEventMouseButtonPrimary: xwtButton = 1; break;
431 case kEventMouseButtonSecondary: xwtButton = 2; break;
432 case kEventMouseButtonTertiary: xwtButton = 3; break;
433 default: return noErr;
435 if(eKind == kEventMouseDown) {
436 surface->Press(xwtButton);
438 surface->Release(xwtButton);
439 while(clickCount > 1) {
440 surface->DoubleClick(xwtButton);
443 if(clickCount) surface->Click(xwtButton);
447 case kEventMouseWheelMoved: {
448 EventMouseWheelAxis axis;
450 r = GetEventParameter(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
451 checkStatus(r,"GetEventParameter");
452 if(axis != kEventMouseWheelAxisY) break;
453 r = GetEventParameter(e,kEventParamMouseWheelDelta,typeSInt32,NULL,sizeof(delta),NULL,&delta);
454 checkStatus(r,"GetEventParameter");
455 fprintf(stderr,"kEventMouseWheelMoved: delta: %d",delta);
456 // surface->MouseWheelMoved(...) IMPROVMENT: mouse wheel support in xwt
462 case kEventClassWindow: {
464 r = GetEventParameter(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
465 checkStatus(r,"kEventClassWindow/GetEventParameter");
467 if((RawData*)window != surface->rawWindowRef) Darwin::abort(JvNewStringLatin1("window != surface->window"));
470 case kEventWindowUpdate: {
471 surface->Dirty(0,0,surface->root->width,surface->root->height);
474 case kEventWindowBoundsChanged: {
477 r = GetEventParameter(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
478 checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
479 r = GetWindowBounds(window,kWindowContentRgn,&rect);
480 checkStatus(r,"GetWindowBounds");
481 if(attr & kWindowBoundsChangeSizeChanged) {
482 jint w = rect.right-rect.left;
483 jint h = rect.bottom-rect.top;
484 if(attr & kWindowBoundsChangeUserResize && surface->maximized)
485 surface->Maximized(false);
486 surface->reshape(w,h);
487 surface->SizeChange(w,h);
488 surface->Dirty(0,0,w,h);
489 surface->blitDirtyScreenRegions();
491 if(attr & kWindowBoundsChangeOriginChanged) {
492 surface->PosChange(rect.left,rect.top);
496 case kEventWindowActivated:
497 case kEventWindowDeactivated: {
498 surface->Focused(eKind == kEventWindowActivated);
501 case kEventWindowZoomed: {
502 fprintf(stderr,"Zoomed....\n");
503 surface->Maximized(true);
506 case kEventWindowCollapsed: {
507 surface->Minimized(true);
510 case kEventWindowExpanded: {
511 surface->Minimized(false);
514 case kEventWindowClose: {
518 case kEventWindowClosed: {
519 DisposeEventHandlerUPP((EventHandlerUPP)surface->rawEventHandlerUPP);
520 GCJ$Retainer::release(surface);
527 return eventNotHandledErr;
531 void Darwin$CarbonSurface::natInit(jboolean framed) {
534 WindowClass wc = framed ? kDocumentWindowClass : kPlainWindowClass;
535 // FIXME: unframed windows should appear in the window menu
536 // This probably needs a hack similar to whats in Cocoa.mm
537 WindowAttributes attr = kWindowStandardHandlerAttribute|
538 (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0);
541 rect.top = 0; rect.left = 0; rect.bottom = 10; rect.right=10;
542 r = CreateNewWindow(wc,attr,&rect,&window);
543 checkStatus(r,"CreateNewWindow");
545 id NSWindowClass = objc_getClass("NSWindow");
546 printf("nswindowclass is %x\n", NSWindowClass);
547 SEL selector = sel_registerName("initWithWindowRef");
548 printf("selector is %s\n", selector);
549 objc_method method = class_getClassMethod(NSWindowClass, selector);
550 printf("method is %x\n", method);
551 id windowInstance = objc_msgSend(NSWindowClass, selector, window);
552 printf("instance is %x\n", windowInstance);
554 GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
555 EventHandlerUPP upp = NewEventHandlerUPP(our_windowEventHandler);
557 r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
558 checkStatus(r,"InstallWindowEventHandler");
560 rawWindowRef = (RawData*) window;
561 rawEventHandlerUPP = (RawData*) upp;
564 void Darwin$CarbonSurface::natDispose() {
565 WindowRef window = (WindowRef) rawWindowRef;
566 DisposeWindow(window);
569 void Darwin$CarbonSurface::natSetIcon(org::xwt::Picture *_p) {
572 void Darwin$CarbonSurface::natSetLocation(jint x, jint y) {
573 WindowRef window = (WindowRef) rawWindowRef;
575 OSStatus r = GetWindowBounds(window,kWindowStructureRgn,&rect);
576 checkStatus(r,"GetWindowBounds");
577 rect.bottom = y + (rect.bottom - rect.top);
578 rect.right = x + (rect.right - rect.left);
581 r = SetWindowBounds(window,kWindowStructureRgn,&rect);
582 checkStatus(r,"SetWindowBounds");
583 r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
584 checkStatus(r,"ConstrainWindowToScreen");
587 void Darwin$CarbonSurface::natSetSize(jint w, jint h) {
588 WindowRef window = (WindowRef) rawWindowRef;
590 OSStatus r = GetWindowBounds(window,kWindowStructureRgn,&rect);
591 checkStatus(r,"GetWindowBounds");
592 rect.bottom = rect.top + h;
593 rect.right = rect.left + w;
594 r = SetWindowBounds(window,kWindowStructureRgn,&rect);
595 checkStatus(r,"SetWindowBounds");
596 r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
597 checkStatus(r,"ConstrainWindowToScreen");
600 void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) {
601 WindowRef window = (WindowRef) rawWindowRef;
602 const int maxMax = 32767;
603 const int minMinW = 80;
604 const int minMinH = 20;
606 min.width = minw > maxMax ? maxMax : (minw < minMinW ? minMinW : minw);
607 min.height = minh > maxMax ? maxMax : (minh < minMinH ? minMinH : minh);
608 max.width = maxw > maxMax ? maxMax : (maxw < minMinW ? minMinW : maxw);
609 max.height = maxh > maxMax ? maxMax : (maxh < minMinH ? minMinH : maxh);
610 OSStatus r = SetWindowResizeLimits(window,&min,&max);
611 checkStatus(r,"SetWindowResizeLimits");
615 #pragma mark ------ Carbon Methods ------
616 void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
617 Darwin$FileDialogHelper *helper = (Darwin$FileDialogHelper*) userData;
618 NavDialogRef dialog = callBackParms->context;
620 switch(callBackSelector) {
621 case kNavCBUserAction: {
622 NavUserAction action = NavDialogGetUserAction(dialog);
623 if(action == kNavUserActionNone || action == kNavUserActionCancel) {
624 helper->fileName = 0;
626 NavReplyRecord reply;
627 r = NavDialogGetReply(dialog,&reply);
628 checkStatus(r,"NavDialogGetReply");
633 r = AEGetNthPtr(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
634 checkStatus(r,"AEGetNthPtr");
635 r = FSRefMakePath(&ref,(UInt8*)buf,sizeof(buf)-1);
636 checkStatus(r,"FSRefMakePath");
637 helper->fileName = JvNewStringLatin1(buf);
638 if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
639 r = NavDisposeReply(&reply);
640 checkStatus(r,"NavDialogGetReply");
642 helper->sem->release();
645 case kNavCBTerminate:
646 DisposeNavEventUPP((NavEventUPP)helper->rawUPP);
647 NavDialogDispose(dialog);
652 void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_, jboolean write) {
654 SmartCFString suggestion = suggestion_;
655 CFStringRef message = CFSTR("By selecting a file in this dialog you are giving this XWT application permission to access that file.");
657 WindowRef window = FrontWindow();
658 NavDialogCreationOptions options;
660 NavEventUPP handler = NewNavEventUPP(fileDialogEventHandler);
662 NavGetDefaultDialogCreationOptions(&options);
663 options.optionFlags =
664 (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement)
665 &~(kNavAllowStationery|kNavAllowMultipleFiles);
666 options.clientName = CFSTR("XWT");
668 options.saveFileName = suggestion;
669 options.message = message;
670 options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal;
671 options.parentWindow = window;
674 r = NavCreatePutFileDialog(&options,0,0,handler,helper,&dlg);
676 r = NavCreateGetFileDialog(&options,NULL,handler,NULL,NULL,helper,&dlg);
677 checkStatus(r,"NavCreate(Get/Put)FileDialog");
679 helper->rawUPP = (RawData*)handler;
683 jstring Darwin::natGetClipBoard() {
688 r = GetCurrentScrap(&scrap);
689 checkStatus(r,"GetCurrentScrap");
691 r = GetScrapFlavorSize( scrap, kScrapFlavorTypeUnicode, &size);
692 if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1("");
693 checkStatus(r,"GetScrapFlavorSize");
695 unsigned int length = size/sizeof(UniChar);
697 jstring js = JvAllocString(length);
698 UniChar *buf = (UniChar*) JvGetStringChars(js);
700 r = GetScrapFlavorData(scrap,kScrapFlavorTypeUnicode,&size2,buf);
701 if(r == scrapFlavorNotFoundErr);
702 checkStatus(r,"GetScrapFlavorData");
703 if(size2 != size) return JvNewStringLatin1("");
708 void Darwin::natSetClipBoard(jstring js) {
709 unsigned int length = js->length();
713 r = GetCurrentScrap(&scrap);
714 checkStatus(r,"GetCurrentScrap");
716 r = PutScrapFlavor(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
717 checkStatus(r,"PutScrapFlavor");
720 HTTP$Proxy *Darwin::natDetectProxy() {
721 using org::xwt::HTTP$Proxy;
725 SmartCFString smartString;
726 CFArrayRef exceptionList;
729 CFDictionaryRef proxyInfo = SCDynamicStoreCopyProxies(NULL);
730 if(proxyInfo == NULL) return 0;
732 #define doproto(proto,var) \
733 number = (CFNumberRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxies ## proto ## Enable); \
734 if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL; \
735 if(number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) { \
736 string = (CFStringRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
737 if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL; \
738 number = (CFNumberRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Port); \
739 if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL; \
740 if(string && number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) { \
741 if(!p) p = new HTTP$Proxy(); \
742 p->var ## ProxyHost = cfStringToJString(string); \
743 p->var ## ProxyPort = i; \
751 exceptionList = (CFArrayRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxiesExceptionsList);
752 if(exceptionList != NULL && CFGetTypeID(exceptionList) != CFArrayGetTypeID()) exceptionList = NULL;
753 if(p && exceptionList && CFArrayGetCount(exceptionList)) {
754 CFIndex count = CFArrayGetCount(exceptionList);
755 p->excluded = (JArray<java::lang::String*>*)
756 JvNewObjectArray(count,&java::lang::String::class$,0);
757 for(i=0;i<count;i++) {
758 string = (CFStringRef) CFArrayGetValueAtIndex(exceptionList,i);
759 if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL;
760 elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
763 CFRelease(proxyInfo);
767 exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
768 if(p && exceptionList && [exceptionList count]) {
769 NSLog(@"excl: %@",exceptionList);
770 p->excluded = (JArray<java::lang::String*>*)
771 JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
772 for(i=0;i<[exceptionList count];i++)
773 elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
779 using org::xwt::Proxy;
784 NSArray *exceptionList;
786 NSDictionary *proxyInfo = (NSDictionary*)SCDynamicStoreCopyProxies(NULL);
788 if(proxyInfo == NULL) return 0;
789 if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPEnable] boolValue]) {
790 host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPProxy];
791 port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPPort];
792 if(host && [port intValue]) {
793 if(!p) p = new Proxy();
794 p->httpProxyHost = [host jstring];
795 p->httpProxyPort = [port intValue];
798 if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSEnable] boolValue]) {
799 host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSProxy];
800 port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSPort];
801 if(host && [port intValue]) {
802 if(!p) p = new Proxy();
803 p->httpsProxyHost = [host jstring];
804 p->httpsProxyPort = [port intValue];
807 if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSEnable] boolValue]) {
808 host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSProxy];
809 port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSPort];
810 if(host && [port intValue]) {
811 if(!p) p = new Proxy();
812 p->socksProxyHost = [host jstring];
813 p->socksProxyPort = [port intValue];
817 exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
818 if(p && exceptionList && [exceptionList count]) {
819 NSLog(@"excl: %@",exceptionList);
820 p->excluded = (JArray<java::lang::String*>*)
821 JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
822 for(i=0;i<[exceptionList count];i++)
823 elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
829 jint Darwin::cgScreenWidth() {
830 return CGDisplayPixelsWide(((CGDirectDisplayID)0));
833 jint Darwin::cgScreenHeight() {
834 return CGDisplayPixelsHigh(((CGDirectDisplayID)0));
837 void Darwin::_newBrowserWindow(jstring js) {
838 SmartCFString cfs = js;
839 CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,cfs,NULL);
840 SmartCFString scheme = CFURLCopyScheme(url);
841 if(scheme.equals(CFStringRef("http")))
842 LSOpenCFURLRef(url,NULL);
846 void Darwin::_exit() {
847 QuitApplicationEventLoop();
850 void Darwin::natInit() {
852 #ifdef XWT_CARBON_NO_BUNDLE_HACK
854 ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
856 ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
857 r = GetCurrentProcess(¤tProcess);
858 checkStatus(r,"GetCurrentProcess");
859 r = CPSEnableForegroundOperation( ¤tProcess );
860 checkStatus(r,"CPSEnableForegroundOperation");
861 r = CPSSetFrontProcess(¤tProcess);
862 checkStatus(r,"CPSSetFrontProcess");
867 r = CreateNibReference(CFSTR("MainMenu"), &nib);
868 checkStatus(r,"CreateNibReference");
869 r = SetMenuBarFromNib(nib, CFSTR("MenuBar"));
870 checkStatus(r,"SetMenuBarFromNib");
871 DisposeNibReference(nib);
873 // FIXME: Install menu event handler
878 void Darwin::_running() {
879 RunApplicationEventLoop();
883 #pragma mark ------ OpenGL Functions -----
885 void Darwin$CarbonOpenGL::activateSharedContext() {
886 AGLContext ctx = (AGLContext) rawSharedContext;
887 aglSetCurrentContext(ctx);
890 jboolean Darwin$CarbonOpenGL::initPixelFormat() {
902 rawPixelFormat = (RawData*) aglChoosePixelFormat(NULL,0,attr);
903 return rawPixelFormat != 0;
906 void Darwin$CarbonOpenGL::initSharedContext() {
907 AGLPixelFormat fmt = (AGLPixelFormat) rawPixelFormat;
908 rawSharedContext = (RawData*) aglCreateContext(fmt,NULL);
909 checkStatus(rawSharedContext,"aglCreateContext");
912 void Darwin$GLCarbonPixelBuffer::natInit() {
913 WindowClass wc = kPlainWindowClass;
914 WindowAttributes attr = 0;
918 AGLContext ctx,shared;
924 rect.top = rect.left = 0;
925 rect.right = width + rect.left;
926 rect.bottom = height + rect.top;
928 r = CreateNewWindow(wc,attr,&rect,&window);
929 checkStatus(r,"CreateNewWindow");
931 shared = (AGLContext) gl->rawSharedContext;
932 fmt = (AGLPixelFormat) gl->rawPixelFormat;
933 ctx = aglCreateContext(fmt,shared);
934 checkStatus(ctx, "aglCreateContext");
936 b = aglSetDrawable(ctx,GetWindowPort(window));
937 checkStatus(b,"aglSetDrawable");
939 aglSetCurrentContext(ctx);
940 aglUpdateContext(ctx);
941 drawableInit(width,height);
942 glClear(GL_COLOR_BUFFER_BIT);
944 aglSetCurrentContext(shared);
945 target = rectTexture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
947 glGenTextures(1,&tex);
948 glBindTexture(target,tex);
949 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
950 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
951 aglSurfaceTexture (shared, target, GL_RGBA, ctx);
955 //ShowWindow(window);
956 textureName = (jint) tex;
957 rawWindowRef = (RawData*) window;
958 rawCTX = (RawData*) ctx;
961 void Darwin$GLCarbonPixelBuffer::activateContext() {
962 AGLContext ctx = (AGLContext) rawCTX;
963 aglSetCurrentContext(ctx);
966 void Darwin$GLCarbonPixelBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
967 WindowRef window = (WindowRef) rawWindowRef;
968 AGLContext ctx = (AGLContext) rawCTX;
969 aglDestroyContext(ctx);
970 DisposeWindow(window);
973 void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonPixelBuffer *db, jint sx1, jint sy1, jint dx1, jint dy1, jint dx2, jint dy2) {
974 AGLContext ctx = (AGLContext) rawCTX;
975 int sx2 = sx1 + (dx2-dx1);
976 int sy2 = sy1 + (dy2-dy1);
977 db->activateContext();
980 aglSetCurrentContext(ctx);
982 if(db->rectTexture) {
983 glEnable(GL_TEXTURE_RECTANGLE_EXT);
985 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, db->textureName);
988 glTexCoord2i (sx1, sy1 );
989 glVertex3i (dx1, dy1, 0);
990 glTexCoord2i (sx2, sy1 );
991 glVertex3i (dx2, dy1, 0);
992 glTexCoord2i (sx2, sy2 );
993 glVertex3i (dx2, dy2, 0);
994 glTexCoord2i (sx1, sy2 );
995 glVertex3i (dx1, dy2, 0);
998 glDisable(GL_TEXTURE_RECTANGLE_EXT);
1001 float tx1,ty1,tx2,ty2; // normalized texture coords
1002 tx1 = (float) sx1 / (float) db->width;
1003 ty1 = (float) sy1 / (float) db->height;
1004 tx2 = (float) sx2 / (float) db->width;
1005 ty2 = (float) sy2 / (float) db->height;
1007 glColor4f(1.0f,1.0f,1.0f,1.0f);
1008 glEnable(GL_TEXTURE_2D);
1009 glBindTexture(GL_TEXTURE_2D, db->textureName);
1012 glTexCoord2f (tx1, ty1 );
1013 glVertex3i (dx1, dy1, 0);
1014 glTexCoord2f (tx2, ty1 );
1015 glVertex3i (dx2, dy1, 0);
1016 glTexCoord2f (tx2, ty2 );
1017 glVertex3i (dx2, dy2, 0);
1018 glTexCoord2f (tx1, ty2 );
1019 glVertex3i (dx1, dy2, 0);
1021 glDisable(GL_TEXTURE_2D);
1027 void Darwin$GLCarbonSurface::natReshape(jint w, jint h) {
1028 AGLContext ctx = (AGLContext) rawCTX;
1030 aglSetCurrentContext (ctx);
1031 aglUpdateContext(ctx);
1033 glViewport(0, 0, w, h);
1034 glMatrixMode(GL_PROJECTION);
1036 glOrtho(0, w, h, 0, -1, 1);
1037 glMatrixMode(GL_MODELVIEW);
1039 glTranslatef (0.375, 0.375, 0.0);
1043 void Darwin$GLCarbonSurface::natInit() {
1044 WindowRef window = (WindowRef) rawWindowRef;
1045 AGLContext ctx,shared;
1049 shared = (AGLContext) gl->rawSharedContext;
1050 fmt = (AGLPixelFormat) gl->rawPixelFormat;
1051 ctx = aglCreateContext(fmt,shared);
1052 checkStatus(ctx, "aglCreateContext");
1054 b = aglSetDrawable(ctx,GetWindowPort(window));
1055 checkStatus(b,"aglSetDrawable");
1057 aglSetCurrentContext(ctx);
1060 rawCTX = (RawData*)ctx;
1064 aglSetCurrentContext(ctx);
1065 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1068 void Darwin$GLCarbonSurface::natDispose() {
1069 AGLContext ctx = (AGLContext) rawCTX;
1070 aglDestroyContext(ctx);
1071 Darwin$CarbonSurface::natDispose();
1074 } } } // end namepsace org::xwt::plat