1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // Authors: Brian Alliet and Evan Jones
13 #include <java/lang/Object.h>
14 #include <java/lang/Error.h>
16 #include <org/xwt/plat/Darwin.h>
17 #include <org/xwt/plat/Darwin$CarbonSurface.h>
18 #include <org/xwt/plat/Darwin$GLCarbonSurface.h>
19 #include <org/xwt/plat/Darwin$GLCarbonDoubleBuffer.h>
20 #include <org/xwt/plat/Darwin$CarbonMessage.h>
21 #include <org/xwt/plat/Darwin$CarbonOpenGL.h>
22 #include <org/xwt/plat/Darwin$FileDialogHelper.h>
23 #include <org/xwt/plat/GCJ$Retainer.h>
24 #include <org/xwt/Proxy.h>
25 #include <org/xwt/util/Semaphore.h>
27 #include <Carbon/Carbon.h>
28 #include <CoreFoundation/CoreFoundation.h>
30 #include <SystemConfiguration/SystemConfiguration.h>
32 #include <ApplicationServices/ApplicationServices.h>
38 using namespace org::xwt::plat;
39 using gnu::gcj::RawData;
40 using org::xwt::util::Semaphore;
41 using java::lang::Object;
43 namespace org { namespace xwt { namespace plat {
46 using namespace darwin;
48 #pragma mark ------ Carbon Namespace ------
50 // We put everything that isn't in org.xwt.plat.Darwin in
51 // org.xwt.plat.darwin to prevent namespace conflicts
53 template <bool CHECK> static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; }
54 template <> static inline int CompileTimeCheck<true>() { return 0; }
55 const static int unichar_check = CompileTimeCheck<sizeof(jchar)==sizeof(UniChar)>();
57 void funcFailed(char *func,int r);
58 static inline void checkStatus(OSStatus r, char *func) { if(r != noErr) funcFailed(func,r); }
59 static inline void checkStatus(GLboolean b, char *func) { if(!b) funcFailed(func,-1); }
60 static inline void checkStatus(void *p, char *func) { if(!p) funcFailed(func,-1); }
62 jstring cfStringToJString(CFStringRef s) {
63 CFIndex length = CFStringGetLength(s);
64 CFRange range = CFRangeMake(0,length);
65 jstring js = JvAllocString(length);
66 UniChar *buf = (UniChar*)JvGetStringChars(js);
67 CFStringGetCharacters(s,range,buf);
71 #pragma mark ------ SmartCFString ------
75 void release() { if(p) CFRelease(p); }
76 void checkNull() { if(!p) throw new java::lang::Error(JvNewStringLatin1("CFString function failed")); }
79 SmartCFString() : p(0) { }
80 SmartCFString(const char *s) : p(0) { *this = s; }
81 SmartCFString(jstring js) : p(0) { *this = js; }
82 SmartCFString(CFStringRef cf) : p(0) { *this = cf; }
84 ~SmartCFString() { release(); }
86 SmartCFString& operator= (const char *s) {
89 p = CFStringCreateWithCString(kCFAllocatorDefault,s,kCFStringEncodingISOLatin1);
93 SmartCFString& operator= (jstring js) {
94 if(!js) return *this = "(null)";
96 UniChar *buf = (UniChar*) JvGetStringChars(js);
97 CFIndex length = js->length();
98 p = CFStringCreateWithCharacters(kCFAllocatorDefault,buf,length);
102 SmartCFString& operator= (CFStringRef cf) {
103 if(cf == NULL) return *this = "(null)";
108 operator CFStringRef() { return p; }
109 operator jstring() { return getJString(); }
111 jstring getJString() { return cfStringToJString(p); }
113 bool equals(const char *s) {
114 SmartCFString cfs(s);
118 bool equals(CFStringRef cfs) {
119 return CFStringCompare(p,cfs,0) == kCFCompareEqualTo;
123 // CHECKME: Is just making up your own four char codes really correct?
124 const static UInt32 kEventClassCarbonMessage = 'xwta';
125 const static UInt32 kEventCarbonMessage = 'xwtb';
126 const static UInt32 kEventParamCarbonMessage = 'xwtc';
128 pascal OSStatus darwin::carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
129 void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
133 jboolean Darwin::isJaguar() {
135 OSStatus r = Gestalt(gestaltSystemVersion, &version);
136 checkStatus(r,"Gestalt");
137 return version >= 0x1020;
140 void Darwin$CarbonMessage::natInit() {
143 EventHandlerUPP upp = NewEventHandlerUPP(carbonMessageEventHandler);
144 EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
145 r = InstallEventHandler(GetApplicationEventTarget(),upp,1,&eventTypes,NULL,NULL);
146 checkStatus(r,"InstallEventHandler");
149 void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) {
153 GCJ$Retainer::retain(msg);
155 r = CreateEvent(kCFAllocatorDefault,kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
156 checkStatus(r,"CreateEvent");
157 r = SetEventParameter(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
158 checkStatus(r,"SetEventParameter");
159 r = PostEventToQueue(GetMainEventQueue(),event,kEventPriorityHigh);
160 checkStatus(r,"PostEventToQueue");
165 pascal OSStatus darwin::carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
166 UInt32 eKind = GetEventKind(e);
167 UInt32 eClass = GetEventClass(e);
169 Darwin$CarbonMessage *msg;
170 if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
171 return eventNotHandledErr;
172 r = GetEventParameter(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
173 checkStatus(r,"GetEventParameter");
175 GCJ$Retainer::release(msg);
180 #pragma mark ------ Utility Functions ------
182 void darwin::funcFailed(char *func,int r){
183 fprintf(stderr,"%s() failed (%d)\n",func,r);
187 #pragma mark ------ CarbonPicture Methods ------
189 #pragma mark ----- Carbon Surface Methods ----
192 void Darwin$CarbonSurface::natSyncCursor(jint n) {
194 // see Carbon.java for what these numbers mean
196 case 1: c = kThemeWatchCursor;
197 case 2: c = kThemePlusCursor;
198 case 3: c = kThemeIBeamCursor;
199 case 4: c = kThemePointingHandCursor;
200 case 5: c = kThemeOpenHandCursor;
201 case 6: c = kThemeResizeLeftRightCursor;
202 default: c = kThemeArrowCursor;
207 void Darwin$CarbonSurface::natSetInvisible(jboolean b) {
208 WindowRef window = (WindowRef) rawWindowRef;
209 fprintf(stderr,"Making window %s\n",b?"invisible":"visible");
210 if(b) HideWindow(window);
211 else ShowWindow(window);
214 void Darwin$CarbonSurface::nat_setMaximized(jboolean b) {
215 WindowRef window = (WindowRef) rawWindowRef;
216 Point ideal = { 10000, 10000 };
217 OSStatus r = ZoomWindowIdeal(window,(b?inZoomOut:inZoomIn),&ideal);
218 checkStatus(r,"ZoomWindowIdeal");
221 void Darwin$CarbonSurface::nat_setMinimized(jboolean b) {
222 WindowRef window = (WindowRef) rawWindowRef;
223 if((IsWindowCollapsed(window) ? 1 : 0) == (b ? 1 : 0)) return;
224 OSStatus r = CollapseWindow(window,b);
225 checkStatus(r,"CollapseWindow");
228 void Darwin$CarbonSurface::natSetTitleBarText(jstring js) {
229 SmartCFString s = js;
230 WindowRef window = (WindowRef) rawWindowRef;
231 SetWindowTitleWithCFString(window,s);
234 void Darwin$CarbonSurface::natToBack() {
235 WindowRef window = (WindowRef) rawWindowRef;
236 SendBehind(window,NULL);
239 void Darwin$CarbonSurface::natToFront() {
240 WindowRef window = (WindowRef) rawWindowRef;
241 fprintf(stderr,"SelectWindow()\n");
242 SelectWindow(window);
245 #pragma mark ---- Window Event Handler ----
247 static const EventTypeSpec eventTypeSpecs[] = {
248 // kEventClassCommand
249 // { kEventClassCommand, ??? },
252 { kEventClassWindow, kEventWindowUpdate },
253 { kEventClassWindow, kEventWindowBoundsChanged },
254 { kEventClassWindow, kEventWindowActivated },
255 { kEventClassWindow, kEventWindowDeactivated },
256 { kEventClassWindow, kEventWindowZoomed },
257 { kEventClassWindow, kEventWindowCollapsed },
258 { kEventClassWindow, kEventWindowExpanded },
259 { kEventClassWindow, kEventWindowClose },
260 { kEventClassWindow, kEventWindowClosed },
262 // kEventClassKeyboard
263 { kEventClassKeyboard, kEventRawKeyDown },
264 { kEventClassKeyboard, kEventRawKeyRepeat },
265 { kEventClassKeyboard, kEventRawKeyUp },
266 { kEventClassKeyboard, kEventRawKeyModifiersChanged },
269 { kEventClassMouse, kEventMouseDown },
270 { kEventClassMouse, kEventMouseUp },
271 { kEventClassMouse, kEventMouseMoved },
272 { kEventClassMouse, kEventMouseDragged },
273 { kEventClassMouse, kEventMouseWheelMoved },
276 pascal OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
277 Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*) userData;
278 UInt32 eKind = GetEventKind(e);
279 UInt32 eClass = GetEventClass(e);
283 case kEventClassCommand:
285 // TODO: handle menu items
288 case kEventClassKeyboard:
290 case kEventRawKeyDown:
291 case kEventRawKeyRepeat:
292 case kEventRawKeyUp: {
296 r = GetEventParameter(e,kEventParamKeyCode,typeUInt32,NULL,sizeof(keyCode),NULL,&keyCode);
297 checkStatus(r,"GetEventParameter");
300 // These values were obtained by experimentation. I can't find any constants for them
301 // in the header files
302 case 126: js = JvNewStringLatin1("up"); break;
303 case 125: js = JvNewStringLatin1("down"); break;
304 case 124: js = JvNewStringLatin1("right"); break;
305 case 123: js = JvNewStringLatin1("left"); break;
306 case 122: js = JvNewStringLatin1("f1"); break;
307 case 120: js = JvNewStringLatin1("f2"); break;
308 case 99: js = JvNewStringLatin1("f3"); break;
309 case 118: js = JvNewStringLatin1("f4"); break;
310 case 96: js = JvNewStringLatin1("f5"); break;
311 case 97: js = JvNewStringLatin1("f6"); break;
312 case 98: js = JvNewStringLatin1("f7"); break;
313 case 100: js = JvNewStringLatin1("f8"); break;
314 case 101: js = JvNewStringLatin1("f9"); break;
315 case 109: js = JvNewStringLatin1("f10"); break;
316 case 103: js = JvNewStringLatin1("f11"); break;
317 case 111: js = JvNewStringLatin1("f12"); break;
318 case 105: js = JvNewStringLatin1("f13"); break;
319 case 114: js = JvNewStringLatin1("insert"); break;
320 case 117: js = JvNewStringLatin1("delete"); break;
321 case 116: js = JvNewStringLatin1("page_up"); break;
322 case 121: js = JvNewStringLatin1("page_down"); break;
323 case 115: js = JvNewStringLatin1("home"); break;
324 case 119: js = JvNewStringLatin1("end"); break;
325 case 71: js = JvNewStringLatin1("num_lock"); break;
326 case 53: js = JvNewStringLatin1("escape"); break;
327 case 51: js = JvNewStringLatin1("back_space"); break;
328 case 36: js = JvNewStringLatin1("enter"); break;
329 case 48: js = JvNewStringLatin1("tab"); break;
330 case 76: js = JvNewStringLatin1("enter"); break; // number pad enter
333 UInt32 modifiers = surface->modifiers;
334 r = GetEventParameter(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,0,&size,NULL);
335 checkStatus(r,"GetEventParameter");
336 if(size == 0 || (modifiers & controlKey && size>sizeof(UniChar))) return eventNotHandledErr;
338 js = JvAllocString(size/sizeof(UniChar));
339 UniChar *buf = (UniChar*)JvGetStringChars(js);
340 r = GetEventParameter(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,size,NULL,buf);
341 checkStatus(r,"GetEventParameter");
343 if(!buf[0]) return eventNotHandledErr; // shouldn't happen
344 // odd, when the ctrl key is pressed a-"`" become 1-31, this brings them back to the corect values
345 if(modifiers & controlKey && buf[0] < 32) buf[0] += 0x60;
350 if(eKind == kEventRawKeyUp)
351 surface->KeyReleased(js);
353 surface->KeyPressed(js);
356 case kEventRawKeyModifiersChanged: {
357 const static struct {
360 } modifiersTable[] = {
361 { shiftKey, JvNewStringLatin1("shift") },
362 { alphaLock, JvNewStringLatin1("caps_lock") },
363 { controlKey, JvNewStringLatin1("control") },
364 { optionKey, JvNewStringLatin1("alt") },
365 { kEventKeyModifierNumLockMask, JvNewStringLatin1("num_lock") },
369 UInt32 oldModifiers = (UInt32) surface->modifiers;
371 r = GetEventParameter(e,kEventParamKeyModifiers,typeUInt32,NULL,sizeof(newModifiers),NULL,&newModifiers);
372 checkStatus(r,"GetEventParameter");
373 surface->modifiers = (jint) newModifiers;
374 UInt32 changedModifiers = oldModifiers ^ newModifiers;
376 for(int i=0;modifiersTable[i].mask;i++) {
377 UInt32 mask = modifiersTable[i].mask;
378 if(!(changedModifiers & mask)) continue;
379 if(newModifiers & mask)
380 surface->KeyPressed(modifiersTable[i].xwtKey);
382 surface->KeyReleased(modifiersTable[i].xwtKey);
388 case kEventClassMouse:
389 // The default handler gets first dibs on mouse events
390 // (this catches the titlebar, resize box, etc)
391 r = CallNextEventHandler(handler, e);
392 if(r != eventNotHandledErr && eKind != kEventMouseMoved && eKind != kEventMouseDragged) return r;
395 case kEventMouseMoved:
396 case kEventMouseDragged: {
397 WindowRef window = (WindowRef) surface->rawWindowRef;
401 r = GetEventParameter(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
402 checkStatus(r,"GetEventParameter");
403 r = GetWindowBounds(window,kWindowContentRgn,&rect);
404 checkStatus(r,"GetWindowBounds");
405 surface->Move(p.h-rect.left,p.v-rect.top);
408 case kEventMouseDown:
409 case kEventMouseUp: {
410 EventMouseButton button;
413 r = GetEventParameter(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
414 checkStatus(r,"GetEventParameter");
415 r = GetEventParameter(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount);
416 checkStatus(r,"GetEventParameter");
419 case kEventMouseButtonPrimary: xwtButton = 1; break;
420 case kEventMouseButtonSecondary: xwtButton = 2; break;
421 case kEventMouseButtonTertiary: xwtButton = 3; break;
422 default: return noErr;
424 if(eKind == kEventMouseDown) {
425 surface->Press(xwtButton);
427 surface->Release(xwtButton);
428 while(clickCount > 1) {
429 surface->DoubleClick(xwtButton);
432 if(clickCount) surface->Click(xwtButton);
436 case kEventMouseWheelMoved: {
437 EventMouseWheelAxis axis;
439 r = GetEventParameter(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
440 checkStatus(r,"GetEventParameter");
441 if(axis != kEventMouseWheelAxisY) break;
442 r = GetEventParameter(e,kEventParamMouseWheelDelta,typeSInt32,NULL,sizeof(delta),NULL,&delta);
443 checkStatus(r,"GetEventParameter");
444 fprintf(stderr,"kEventMouseWheelMoved: delta: %d",delta);
445 // surface->MouseWheelMoved(...) IMPROVMENT: mouse wheel support in xwt
451 case kEventClassWindow: {
453 r = GetEventParameter(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
454 checkStatus(r,"kEventClassWindow/GetEventParameter");
456 if((RawData*)window != surface->rawWindowRef) Darwin::abort(JvNewStringLatin1("window != surface->window"));
459 case kEventWindowUpdate: {
460 surface->Dirty(0,0,surface->root->width,surface->root->height);
463 case kEventWindowBoundsChanged: {
466 r = GetEventParameter(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
467 checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
468 r = GetWindowBounds(window,kWindowContentRgn,&rect);
469 checkStatus(r,"GetWindowBounds");
470 if(attr & kWindowBoundsChangeSizeChanged) {
471 jint w = rect.right-rect.left;
472 jint h = rect.bottom-rect.top;
473 if(attr & kWindowBoundsChangeUserResize && surface->maximized)
474 surface->Maximized(false);
475 surface->reshape(w,h);
476 surface->SizeChange(w,h);
477 surface->Dirty(0,0,w,h);
478 surface->blitDirtyScreenRegions();
480 if(attr & kWindowBoundsChangeOriginChanged) {
481 surface->PosChange(rect.left,rect.top);
485 case kEventWindowActivated:
486 case kEventWindowDeactivated: {
487 surface->Focused(eKind == kEventWindowActivated);
490 case kEventWindowZoomed: {
491 fprintf(stderr,"Zoomed....\n");
492 surface->Maximized(true);
495 case kEventWindowCollapsed: {
496 surface->Minimized(true);
499 case kEventWindowExpanded: {
500 surface->Minimized(false);
503 case kEventWindowClose: {
507 case kEventWindowClosed: {
508 DisposeEventHandlerUPP((EventHandlerUPP)surface->rawEventHandlerUPP);
509 GCJ$Retainer::release(surface);
516 return eventNotHandledErr;
520 void Darwin$CarbonSurface::natInit(jboolean framed) {
523 WindowClass wc = framed ? kDocumentWindowClass : kPlainWindowClass;
524 // FIXME: unframed windows should appear in the window menu
525 // This probably needs a hack similar to whats in Cocoa.mm
526 WindowAttributes attr = kWindowStandardHandlerAttribute|
527 (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0);
530 rect.top = 0; rect.left = 0; rect.bottom = 10; rect.right=10;
531 r = CreateNewWindow(wc,attr,&rect,&window);
532 checkStatus(r,"CreateNewWindow");
534 GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
535 EventHandlerUPP upp = NewEventHandlerUPP(windowEventHandler);
537 r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
538 checkStatus(r,"InstallWindowEventHandler");
540 rawWindowRef = (RawData*) window;
541 rawEventHandlerUPP = (RawData*) upp;
544 void Darwin$CarbonSurface::natDispose() {
545 WindowRef window = (WindowRef) rawWindowRef;
546 DisposeWindow(window);
549 void Darwin$CarbonSurface::natSetIcon(org::xwt::Picture *_p) {
552 void Darwin$CarbonSurface::natSetLocation(jint x, jint y) {
553 WindowRef window = (WindowRef) rawWindowRef;
555 OSStatus r = GetWindowBounds(window,kWindowStructureRgn,&rect);
556 checkStatus(r,"GetWindowBounds");
557 rect.bottom = y + (rect.bottom - rect.top);
558 rect.right = x + (rect.right - rect.left);
561 r = SetWindowBounds(window,kWindowStructureRgn,&rect);
562 checkStatus(r,"SetWindowBounds");
563 r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
564 checkStatus(r,"ConstrainWindowToScreen");
567 void Darwin$CarbonSurface::natSetSize(jint w, jint h) {
568 WindowRef window = (WindowRef) rawWindowRef;
570 OSStatus r = GetWindowBounds(window,kWindowStructureRgn,&rect);
571 checkStatus(r,"GetWindowBounds");
572 rect.bottom = rect.top + h;
573 rect.right = rect.left + w;
574 r = SetWindowBounds(window,kWindowStructureRgn,&rect);
575 checkStatus(r,"SetWindowBounds");
576 r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
577 checkStatus(r,"ConstrainWindowToScreen");
580 void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) {
581 WindowRef window = (WindowRef) rawWindowRef;
582 const int maxMax = 32767;
583 const int minMinW = 80;
584 const int minMinH = 20;
586 min.width = minw > maxMax ? maxMax : (minw < minMinW ? minMinW : minw);
587 min.height = minh > maxMax ? maxMax : (minh < minMinH ? minMinH : minh);
588 max.width = maxw > maxMax ? maxMax : (maxw < minMinW ? minMinW : maxw);
589 max.height = maxh > maxMax ? maxMax : (maxh < minMinH ? minMinH : maxh);
590 OSStatus r = SetWindowResizeLimits(window,&min,&max);
591 checkStatus(r,"SetWindowResizeLimits");
595 #pragma mark ------ Carbon Methods ------
596 void darwin::fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
597 Darwin$FileDialogHelper *helper = (Darwin$FileDialogHelper*) userData;
598 NavDialogRef dialog = callBackParms->context;
600 switch(callBackSelector) {
601 case kNavCBUserAction: {
602 NavUserAction action = NavDialogGetUserAction(dialog);
603 if(action == kNavUserActionNone || action == kNavUserActionCancel) {
604 helper->fileName = 0;
606 NavReplyRecord reply;
607 r = NavDialogGetReply(dialog,&reply);
608 checkStatus(r,"NavDialogGetReply");
613 r = AEGetNthPtr(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
614 checkStatus(r,"AEGetNthPtr");
615 r = FSRefMakePath(&ref,(UInt8*)buf,sizeof(buf)-1);
616 checkStatus(r,"FSRefMakePath");
617 helper->fileName = JvNewStringLatin1(buf);
618 if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
619 r = NavDisposeReply(&reply);
620 checkStatus(r,"NavDialogGetReply");
622 helper->sem->release();
625 case kNavCBTerminate:
626 DisposeNavEventUPP((NavEventUPP)helper->rawUPP);
627 NavDialogDispose(dialog);
632 void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_, jboolean write) {
634 SmartCFString suggestion = suggestion_;
635 CFStringRef message = CFSTR("By selecting a file in this dialog you are giving this XWT application permission to access that file.");
637 WindowRef window = FrontWindow();
638 NavDialogCreationOptions options;
640 NavEventUPP handler = NewNavEventUPP(darwin::fileDialogEventHandler);
642 NavGetDefaultDialogCreationOptions(&options);
643 options.optionFlags =
644 (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement)
645 &~(kNavAllowStationery|kNavAllowMultipleFiles);
646 options.clientName = CFSTR("XWT");
648 options.saveFileName = suggestion;
649 options.message = message;
650 options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal;
651 options.parentWindow = window;
654 r = NavCreatePutFileDialog(&options,0,0,handler,helper,&dlg);
656 r = NavCreateGetFileDialog(&options,NULL,handler,NULL,NULL,helper,&dlg);
657 checkStatus(r,"NavCreate(Get/Put)FileDialog");
659 helper->rawUPP = (RawData*)handler;
663 jstring Darwin::natGetClipBoard() {
668 r = GetCurrentScrap(&scrap);
669 checkStatus(r,"GetCurrentScrap");
671 r = GetScrapFlavorSize( scrap, kScrapFlavorTypeUnicode, &size);
672 if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1("");
673 checkStatus(r,"GetScrapFlavorSize");
675 unsigned int length = size/sizeof(UniChar);
677 jstring js = JvAllocString(length);
678 UniChar *buf = (UniChar*) JvGetStringChars(js);
680 r = GetScrapFlavorData(scrap,kScrapFlavorTypeUnicode,&size2,buf);
681 if(r == scrapFlavorNotFoundErr);
682 checkStatus(r,"GetScrapFlavorData");
683 if(size2 != size) return JvNewStringLatin1("");
688 void Darwin::natSetClipBoard(jstring js) {
689 unsigned int length = js->length();
693 r = GetCurrentScrap(&scrap);
694 checkStatus(r,"GetCurrentScrap");
696 r = PutScrapFlavor(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
697 checkStatus(r,"PutScrapFlavor");
700 Proxy *Darwin::natDetectProxy() {
701 using org::xwt::Proxy;
705 SmartCFString smartString;
706 CFArrayRef exceptionList;
709 CFDictionaryRef proxyInfo = SCDynamicStoreCopyProxies(NULL);
710 if(proxyInfo == NULL) return 0;
712 #define doproto(proto,var) \
713 number = (CFNumberRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxies ## proto ## Enable); \
714 if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL; \
715 if(number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) { \
716 string = (CFStringRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
717 if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL; \
718 number = (CFNumberRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Port); \
719 if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL; \
720 if(string && number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) { \
721 if(!p) p = new Proxy(); \
722 p->var ## ProxyHost = cfStringToJString(string); \
723 p->var ## ProxyPort = i; \
731 exceptionList = (CFArrayRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxiesExceptionsList);
732 if(exceptionList != NULL && CFGetTypeID(exceptionList) != CFArrayGetTypeID()) exceptionList = NULL;
733 if(p && exceptionList && CFArrayGetCount(exceptionList)) {
734 CFIndex count = CFArrayGetCount(exceptionList);
735 p->excluded = (JArray<java::lang::String*>*)
736 JvNewObjectArray(count,&java::lang::String::class$,0);
737 for(i=0;i<count;i++) {
738 string = (CFStringRef) CFArrayGetValueAtIndex(exceptionList,i);
739 if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL;
740 elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
743 CFRelease(proxyInfo);
747 exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
748 if(p && exceptionList && [exceptionList count]) {
749 NSLog(@"excl: %@",exceptionList);
750 p->excluded = (JArray<java::lang::String*>*)
751 JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
752 for(i=0;i<[exceptionList count];i++)
753 elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
759 using org::xwt::Proxy;
764 NSArray *exceptionList;
766 NSDictionary *proxyInfo = (NSDictionary*)SCDynamicStoreCopyProxies(NULL);
768 if(proxyInfo == NULL) return 0;
769 if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPEnable] boolValue]) {
770 host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPProxy];
771 port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPPort];
772 if(host && [port intValue]) {
773 if(!p) p = new Proxy();
774 p->httpProxyHost = [host jstring];
775 p->httpProxyPort = [port intValue];
778 if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSEnable] boolValue]) {
779 host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSProxy];
780 port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSPort];
781 if(host && [port intValue]) {
782 if(!p) p = new Proxy();
783 p->httpsProxyHost = [host jstring];
784 p->httpsProxyPort = [port intValue];
787 if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSEnable] boolValue]) {
788 host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSProxy];
789 port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSPort];
790 if(host && [port intValue]) {
791 if(!p) p = new Proxy();
792 p->socksProxyHost = [host jstring];
793 p->socksProxyPort = [port intValue];
797 exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
798 if(p && exceptionList && [exceptionList count]) {
799 NSLog(@"excl: %@",exceptionList);
800 p->excluded = (JArray<java::lang::String*>*)
801 JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
802 for(i=0;i<[exceptionList count];i++)
803 elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
809 jint Darwin::cgScreenWidth() {
810 return CGDisplayPixelsWide(kCGDirectMainDisplay);
813 jint Darwin::cgScreenHeight() {
814 return CGDisplayPixelsHigh(kCGDirectMainDisplay);
817 void Darwin::_newBrowserWindow(jstring js) {
818 SmartCFString cfs = js;
819 CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,cfs,NULL);
820 SmartCFString scheme = CFURLCopyScheme(url);
821 if(scheme.equals(CFStringRef("http")))
822 LSOpenCFURLRef(url,NULL);
826 void Darwin::_exit() {
827 QuitApplicationEventLoop();
830 #define XWT_CARBON_NO_BUNDLE_HACK
831 #ifdef XWT_CARBON_NO_BUNDLE_HACK
833 OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn);
834 OSErr CPSSetFrontProcess(ProcessSerialNumber *psn);
837 void Darwin::natInit() {
839 #ifdef XWT_CARBON_NO_BUNDLE_HACK
841 ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
843 ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
844 r = GetCurrentProcess(¤tProcess);
845 checkStatus(r,"GetCurrentProcess");
846 r = CPSEnableForegroundOperation( ¤tProcess );
847 checkStatus(r,"CPSEnableForegroundOperation");
848 r = CPSSetFrontProcess(¤tProcess);
849 checkStatus(r,"CPSSetFrontProcess");
854 r = CreateNibReference(CFSTR("MainMenu"), &nib);
855 checkStatus(r,"CreateNibReference");
856 r = SetMenuBarFromNib(nib, CFSTR("MenuBar"));
857 checkStatus(r,"SetMenuBarFromNib");
858 DisposeNibReference(nib);
860 // FIXME: Install menu event handler
865 void Darwin::_running() {
866 RunApplicationEventLoop();
870 #pragma mark ------ OpenGL Functions -----
872 void Darwin$CarbonOpenGL::activateSharedContext() {
873 AGLContext ctx = (AGLContext) rawSharedContext;
874 aglSetCurrentContext(ctx);
877 jboolean Darwin$CarbonOpenGL::initPixelFormat() {
889 rawPixelFormat = (RawData*) aglChoosePixelFormat(NULL,0,attr);
890 return rawPixelFormat != 0;
893 void Darwin$CarbonOpenGL::initSharedContext() {
894 AGLPixelFormat fmt = (AGLPixelFormat) rawPixelFormat;
895 rawSharedContext = (RawData*) aglCreateContext(fmt,NULL);
896 checkStatus(rawSharedContext,"aglCreateContext");
899 void Darwin$GLCarbonDoubleBuffer::natInit() {
900 WindowClass wc = kPlainWindowClass;
901 WindowAttributes attr = 0;
905 AGLContext ctx,shared;
911 rect.top = rect.left = 0;
912 rect.right = width + rect.left;
913 rect.bottom = height + rect.top;
915 r = CreateNewWindow(wc,attr,&rect,&window);
916 checkStatus(r,"CreateNewWindow");
918 shared = (AGLContext) gl->rawSharedContext;
919 fmt = (AGLPixelFormat) gl->rawPixelFormat;
920 ctx = aglCreateContext(fmt,shared);
921 checkStatus(ctx, "aglCreateContext");
923 b = aglSetDrawable(ctx,GetWindowPort(window));
924 checkStatus(b,"aglSetDrawable");
926 aglSetCurrentContext(ctx);
927 aglUpdateContext(ctx);
928 drawableInit(width,height);
929 glClear(GL_COLOR_BUFFER_BIT);
931 aglSetCurrentContext(shared);
932 target = rectTexture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
934 glGenTextures(1,&tex);
935 glBindTexture(target,tex);
936 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
937 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
938 aglSurfaceTexture (shared, target, GL_RGBA, ctx);
942 //ShowWindow(window);
943 textureName = (jint) tex;
944 rawWindowRef = (RawData*) window;
945 rawCTX = (RawData*) ctx;
948 void Darwin$GLCarbonDoubleBuffer::activateContext() {
949 AGLContext ctx = (AGLContext) rawCTX;
950 aglSetCurrentContext(ctx);
953 void Darwin$GLCarbonDoubleBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
954 WindowRef window = (WindowRef) rawWindowRef;
955 AGLContext ctx = (AGLContext) rawCTX;
956 aglDestroyContext(ctx);
957 DisposeWindow(window);
960 void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonDoubleBuffer *db, jint sx1, jint sy1, jint dx1, jint dy1, jint dx2, jint dy2) {
961 AGLContext ctx = (AGLContext) rawCTX;
962 int sx2 = sx1 + (dx2-dx1);
963 int sy2 = sy1 + (dy2-dy1);
964 db->activateContext();
967 aglSetCurrentContext(ctx);
969 if(db->rectTexture) {
970 glEnable(GL_TEXTURE_RECTANGLE_EXT);
972 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, db->textureName);
975 glTexCoord2i (sx1, sy1 );
976 glVertex3i (dx1, dy1, 0);
977 glTexCoord2i (sx2, sy1 );
978 glVertex3i (dx2, dy1, 0);
979 glTexCoord2i (sx2, sy2 );
980 glVertex3i (dx2, dy2, 0);
981 glTexCoord2i (sx1, sy2 );
982 glVertex3i (dx1, dy2, 0);
985 glDisable(GL_TEXTURE_RECTANGLE_EXT);
988 float tx1,ty1,tx2,ty2; // normalized texture coords
989 tx1 = (float) sx1 / (float) db->width;
990 ty1 = (float) sy1 / (float) db->height;
991 tx2 = (float) sx2 / (float) db->width;
992 ty2 = (float) sy2 / (float) db->height;
994 glColor4f(1.0f,1.0f,1.0f,1.0f);
995 glEnable(GL_TEXTURE_2D);
996 glBindTexture(GL_TEXTURE_2D, db->textureName);
999 glTexCoord2f (tx1, ty1 );
1000 glVertex3i (dx1, dy1, 0);
1001 glTexCoord2f (tx2, ty1 );
1002 glVertex3i (dx2, dy1, 0);
1003 glTexCoord2f (tx2, ty2 );
1004 glVertex3i (dx2, dy2, 0);
1005 glTexCoord2f (tx1, ty2 );
1006 glVertex3i (dx1, dy2, 0);
1008 glDisable(GL_TEXTURE_2D);
1014 void Darwin$GLCarbonSurface::natReshape(jint w, jint h) {
1015 AGLContext ctx = (AGLContext) rawCTX;
1017 aglSetCurrentContext (ctx);
1018 aglUpdateContext(ctx);
1020 glViewport(0, 0, w, h);
1021 glMatrixMode(GL_PROJECTION);
1023 glOrtho(0, w, h, 0, -1, 1);
1024 glMatrixMode(GL_MODELVIEW);
1026 glTranslatef (0.375, 0.375, 0.0);
1030 void Darwin$GLCarbonSurface::natInit() {
1031 WindowRef window = (WindowRef) rawWindowRef;
1032 AGLContext ctx,shared;
1036 shared = (AGLContext) gl->rawSharedContext;
1037 fmt = (AGLPixelFormat) gl->rawPixelFormat;
1038 ctx = aglCreateContext(fmt,shared);
1039 checkStatus(ctx, "aglCreateContext");
1041 b = aglSetDrawable(ctx,GetWindowPort(window));
1042 checkStatus(b,"aglSetDrawable");
1044 aglSetCurrentContext(ctx);
1047 rawCTX = (RawData*)ctx;
1051 aglSetCurrentContext(ctx);
1052 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1055 void Darwin$GLCarbonSurface::natDispose() {
1056 AGLContext ctx = (AGLContext) rawCTX;
1057 aglDestroyContext(ctx);
1058 Darwin$CarbonSurface::natDispose();
1061 } } } // end namepsace org::xwt::plat