commit 3d6fc088f028e0267ecbc64e21eadbe9ca1bcb83 from: Jacob Vosmaer via: Russ Cox date: Fri Nov 16 03:03:27 2018 UTC devdraw: remove os x 10.5 compatibility code commit - 4e2ac7657b2ac3173bd4b23ecb7a7e8c4b74c00f commit + 3d6fc088f028e0267ecbc64e21eadbe9ca1bcb83 blob - 98d6799d9a1a6e463774a3542b7adc568791eb33 blob + e94afbd36e19fd03d1c60ade68cef98e0d76be70 --- src/cmd/devdraw/mkwsysrules.sh +++ src/cmd/devdraw/mkwsysrules.sh @@ -23,7 +23,8 @@ fi if [ "x$WSYSTYPE" = "x" ]; then if [ "x`uname`" = "xDarwin" ]; then if sw_vers | grep 'ProductVersion: 10\.[0-5]\.' >/dev/null; then - WSYSTYPE=osx + echo 1>&2 'OS X 10.5 and older are not supported' + exit 1 else #echo 1>&2 'WARNING: OS X Lion is not working. Copy binaries from a Snow Leopard system.' WSYSTYPE=osx-cocoa @@ -52,13 +53,6 @@ if [ $WSYSTYPE = x11 ]; then echo 'HFILES=$HFILES $XHFILES' XO=`ls x11-*.c 2>/dev/null | sed 's/\.c$/.o/'` echo 'WSYSOFILES=$WSYSOFILES '$XO -elif [ $WSYSTYPE = osx ]; then - if [ -d /System/Library/PrivateFrameworks/MultitouchSupport.framework ]; then - echo 'CFLAGS=$CFLAGS -DMULTITOUCH' - echo 'LDFLAGS=$LDFLAGS -F/System/Library/PrivateFrameworks' - fi - echo 'WSYSOFILES=$WSYSOFILES osx-screen-carbon-objc.o osx-draw.o osx-srv.o' - echo 'MACARGV=macargv.o' elif [ $WSYSTYPE = osx-cocoa ]; then if sw_vers|awk '/ProductVersion/{split($2,a,".");exit(a[2]<14)}' >/dev/null; then # 0 is true in sh. echo 'OBJCFLAGS=$OBJCFLAGS -fobjc-arc' blob - d41e9d10deef6b369588393e4e9eda063ee6592a (mode 644) blob + /dev/null --- src/cmd/devdraw/osx-screen-carbon.m +++ /dev/null @@ -1,1302 +0,0 @@ -#define Point OSXPoint -#define Rect OSXRect -#define Cursor OSXCursor -#include -#import -#ifdef MULTITOUCH -#include -#include -#endif -#undef Rect -#undef Point -#undef Cursor -#undef offsetof -#undef nil - -#include "u.h" -#include "libc.h" -#include -#include -#include -#include -#include "mouse.h" -#include -#include "osx-screen.h" -#include "osx-keycodes.h" -#include "devdraw.h" -#include "glendapng.h" - -AUTOFRAMEWORK(Carbon) -AUTOFRAMEWORK(Cocoa) - -#ifdef MULTITOUCH -AUTOFRAMEWORK(MultitouchSupport) -AUTOFRAMEWORK(IOKit) -#endif - -#define panic sysfatal - -extern Rectangle mouserect; - -struct { - char *label; - char *winsize; - QLock labellock; - - Rectangle fullscreenr; - Rectangle screenr; - Memimage *screenimage; - int isfullscreen; - ulong fullscreentime; - - Point xy; - int buttons; - int kbuttons; - - CGDataProviderRef provider; - MenuRef wmenu; - MenuRef vmenu; - WindowRef window; - CGImageRef image; - CGContextRef windowctx; - PasteboardRef snarf; - int needflush; - QLock flushlock; - int active; - int infullscreen; - int kalting; // last keystroke was Kalt - int touched; // last mouse event was touchCallback - int collapsed; // parked in dock - int flushing; // flushproc has started - NSMutableArray* devicelist; -} osx; - -/* - These structs are required, in order to handle some parameters returned from the - Support.framework - */ -typedef struct { - float x; - float y; -}mtPoint; - -typedef struct { - mtPoint position; - mtPoint velocity; -}mtReadout; - -/* - Some reversed engineered informations from MultiTouchSupport.framework - */ -typedef struct -{ - int frame; //the current frame - double timestamp; //event timestamp - int identifier; //identifier guaranteed unique for life of touch per device - int state; //the current state (not sure what the values mean) - int unknown1; //no idea what this does - int unknown2; //no idea what this does either - mtReadout normalized; //the normalized position and vector of the touch (0,0 to 1,1) - float size; //the size of the touch (the area of your finger being tracked) - int unknown3; //no idea what this does - float angle; //the angle of the touch -| - float majorAxis; //the major axis of the touch -|-- an ellipsoid. you can track the angle of each finger! - float minorAxis; //the minor axis of the touch -| - mtReadout unknown4; //not sure what this is for - int unknown5[2]; //no clue - float unknown6; //no clue -}Touch; - -//a reference pointer for the multitouch device -typedef void *MTDeviceRef; - -//the prototype for the callback function -typedef int (*MTContactCallbackFunction)(int,Touch*,int,double,int); - -//returns a pointer to the default device (the trackpad?) -MTDeviceRef MTDeviceCreateDefault(void); - -//returns a CFMutableArrayRef array of all multitouch devices -CFMutableArrayRef MTDeviceCreateList(void); - -//registers a device's frame callback to your callback function -void MTRegisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction); -void MTUnregisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction); - -//start sending events -void MTDeviceStart(MTDeviceRef, int); -void MTDeviceStop(MTDeviceRef); - -MTDeviceRef MTDeviceCreateFromService(io_service_t); -io_service_t MTDeviceGetService(MTDeviceRef); - -#define kNTracks 10 -struct TouchTrack { - int id; - float firstThreshTime; - mtPoint pos; -} tracks[kNTracks]; - -#define kSizeSensitivity 1.25f -#define kTimeSensitivity 0.03f /* seconds */ -#define kButtonLimit 0.6f /* percentage from base of pad */ - -int -findTrack(int id) -{ - int i; - for(i = 0; i < kNTracks; ++i) - if(tracks[i].id == id) - return i; - return -1; -} - -#define kMoveSensitivity 0.05f - -int -moved(mtPoint a, mtPoint b) -{ - if(fabs(a.x - b.x) > kMoveSensitivity) - return 1; - if(fabs(a.y - b.y) > kMoveSensitivity) - return 1; - return 0; -} - -int -classifyTouch(Touch *t) -{ - mtPoint p; - int i; - - p = t->normalized.position; - - i = findTrack(t->identifier); - if(i == -1) { - i = findTrack(-1); - if(i == -1) - return 0; // No empty tracks. - tracks[i].id = t->identifier; - tracks[i].firstThreshTime = t->timestamp; - tracks[i].pos = p; - // we don't have a touch yet - we wait kTimeSensitivity before reporting it. - return 0; - } - - if(t->size == 0) { // lost touch - tracks[i].id = -1; - return 0; - } - if(t->size < kSizeSensitivity) { - tracks[i].firstThreshTime = t->timestamp; - } - if((t->timestamp - tracks[i].firstThreshTime) < kTimeSensitivity) { - return 0; - } - if(p.y > kButtonLimit && t->size > kSizeSensitivity) { - if(p.x < 0.35) - return 1; - if(p.x > 0.65) - return 4; - if(p.x > 0.35 && p.x < 0.65) - return 2; - } - return 0; -} - -static ulong msec(void); - -int -touchCallback(int device, Touch *data, int nFingers, double timestamp, int frame) -{ -#ifdef MULTITOUCH - int buttons, delta, i; - static int obuttons; - CGPoint p; - CGEventRef e; - - p.x = osx.xy.x+osx.screenr.min.x; - p.y = osx.xy.y+osx.screenr.min.y; - if(!ptinrect(Pt(p.x, p.y), osx.screenr)) - return 0; - osx.touched = 1; - buttons = 0; - for(i = 0; i < nFingers; ++i) - buttons |= classifyTouch(data+i); - delta = buttons ^ obuttons; - obuttons = buttons; - if(delta & 1) { - e = CGEventCreateMouseEvent(NULL, - (buttons & 1) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp, - p, - 29); - CGEventPost(kCGSessionEventTap, e); - CFRelease(e); - } - if(delta & 2) { - e = CGEventCreateMouseEvent(NULL, - (buttons & 2) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp, - p, - 30); - CGEventPost(kCGSessionEventTap, e); - CFRelease(e); - } - if(delta & 4){ - e = CGEventCreateMouseEvent(NULL, - (buttons & 4) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp, - p, - 31); - CGEventPost(kCGSessionEventTap, e); - CFRelease(e); - } - return delta != 0; -#else - return 0; -#endif -} - -extern int multitouch; - -enum -{ - WindowAttrs = - kWindowCloseBoxAttribute | - kWindowCollapseBoxAttribute | - kWindowResizableAttribute | - kWindowStandardHandlerAttribute | - kWindowFullZoomAttribute -}; - -enum -{ - P9PEventLabelUpdate = 1 -}; - -static void screenproc(void*); -static void eresized(int); -static void fullscreen(int); -static void seticon(void); -static void activated(int); - -static OSStatus quithandler(EventHandlerCallRef, EventRef, void*); -static OSStatus eventhandler(EventHandlerCallRef, EventRef, void*); -static OSStatus cmdhandler(EventHandlerCallRef, EventRef, void*); - -enum -{ - CmdFullScreen = 1, -}; - -void screeninit(void); -void _flushmemscreen(Rectangle r); - -#ifdef MULTITOUCH -static void -RegisterMultitouch(void *ctx, io_iterator_t iter) -{ - io_object_t io; - MTDeviceRef dev; - - while((io = IOIteratorNext(iter)) != 0){ - dev = MTDeviceCreateFromService(io); - if (dev != nil){ - MTRegisterContactFrameCallback(dev, touchCallback); - [osx.devicelist addObject:dev]; - if(osx.active) - MTDeviceStart(dev, 0); - } - - IOObjectRelease(io); - } -} - -static void -UnregisterMultitouch(void *ctx, io_iterator_t iter) -{ - io_object_t io; - MTDeviceRef dev; - int i; - - while((io = IOIteratorNext(iter)) != 0){ - for(i = 0; i < [osx.devicelist count]; i++){ - dev = [osx.devicelist objectAtIndex:i]; - if(IOObjectIsEqualTo(MTDeviceGetService(dev), io)){ - if(osx.active) - MTDeviceStop(dev); - MTUnregisterContactFrameCallback(dev, touchCallback); - [osx.devicelist removeObjectAtIndex:i]; - break; - } - } - - IOObjectRelease(io); - } -} - -#endif /*MULTITOUCH*/ - -static void -InitMultiTouch() -{ -#ifdef MULTITOUCH - IONotificationPortRef port; - CFRunLoopSourceRef source; - io_iterator_t iter; - kern_return_t kr; - io_object_t obj; - int i; - - if(!multitouch) - return; - - osx.devicelist = [[NSMutableArray alloc] init]; - - for(i = 0; i < kNTracks; ++i) - tracks[i].id = -1; - - port = IONotificationPortCreate(kIOMasterPortDefault); - if(port == nil){ - fprint(2, "failed to get an IO notification port\n"); - return; - } - - source = IONotificationPortGetRunLoopSource(port); - if(source == nil){ - fprint(2, "failed to get loop source for port"); - return; - } - - CFRunLoopAddSource( - (CFRunLoopRef)GetCFRunLoopFromEventLoop(GetMainEventLoop()), - source, - kCFRunLoopDefaultMode); - - kr = IOServiceAddMatchingNotification( - port, kIOTerminatedNotification, - IOServiceMatching("AppleMultitouchDevice"), - &UnregisterMultitouch, - nil, &iter); - - if(kr != KERN_SUCCESS){ - fprint(2, "failed to add termination notification\n"); - return; - } - - /* Arm the notification */ - while((obj = IOIteratorNext(iter)) != 0) - IOObjectRelease(obj); - - kr = IOServiceAddMatchingNotification( - port, kIOMatchedNotification, - IOServiceMatching("AppleMultitouchDevice"), - &RegisterMultitouch, - nil, &iter); - - if(kr != KERN_SUCCESS){ - fprint(2, "failed to add matching notification\n"); - return; - } - - RegisterMultitouch(nil, iter); -#endif -} - -Memimage* -attachscreen(char *label, char *winsize) -{ - if(label == nil) - label = "gnot a label"; - osx.label = strdup(label); - osx.winsize = winsize; - if(osx.screenimage == nil){ - screeninit(); - if(osx.screenimage == nil) - panic("cannot create OS X screen"); - } - return osx.screenimage; -} - -extern int multitouch; - -void -_screeninit(void) -{ - CGRect cgr; - OSXRect or; - Rectangle r; - int havemin; - - memimageinit(); - - ProcessSerialNumber psn = { 0, kCurrentProcess }; - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); - - cgr = CGDisplayBounds(CGMainDisplayID()); - osx.fullscreenr = Rect(0, 0, cgr.size.width, cgr.size.height); - - InitCursor(); - - // Create minimal menu with full-screen option. - ClearMenuBar(); - CreateStandardWindowMenu(0, &osx.wmenu); - InsertMenu(osx.wmenu, 0); - MenuItemIndex ix; - CreateNewMenu(1004, 0, &osx.vmenu); // XXX 1004? - SetMenuTitleWithCFString(osx.vmenu, CFSTR("View")); - AppendMenuItemTextWithCFString(osx.vmenu, - CFSTR("Full Screen"), 0, CmdFullScreen, &ix); - SetMenuItemCommandKey(osx.vmenu, ix, 0, 'F'); - AppendMenuItemTextWithCFString(osx.vmenu, - CFSTR("Cmd-F exits full screen"), - kMenuItemAttrDisabled, CmdFullScreen, &ix); - InsertMenu(osx.vmenu, GetMenuID(osx.wmenu)); - DrawMenuBar(); - - // Create the window. - r = Rect(0, 0, Dx(osx.fullscreenr)*2/3, Dy(osx.fullscreenr)*2/3); - havemin = 0; - if(osx.winsize && osx.winsize[0]){ - if(parsewinsize(osx.winsize, &r, &havemin) < 0) - sysfatal("%r"); - } - if(!havemin) - r = rectaddpt(r, Pt((Dx(osx.fullscreenr)-Dx(r))/2, (Dy(osx.fullscreenr)-Dy(r))/2)); - or.left = r.min.x; - or.top = r.min.y; - or.right = r.max.x; - or.bottom = r.max.y; - CreateNewWindow(kDocumentWindowClass, WindowAttrs, &or, &osx.window); - setlabel(osx.label); - seticon(); - - // Set up the clip board. - if(PasteboardCreate(kPasteboardClipboard, &osx.snarf) != noErr) - panic("pasteboard create"); - - // Explain in great detail which events we want to handle. - // Why can't we just have one handler? - const EventTypeSpec quits[] = { - { kEventClassApplication, kEventAppQuit } - }; - const EventTypeSpec cmds[] = { - { kEventClassWindow, kEventWindowClosed }, - { kEventClassWindow, kEventWindowBoundsChanged }, - { kEventClassWindow, kEventWindowDrawContent }, - { kEventClassCommand, kEventCommandProcess }, - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowExpanded }, - }; - const EventTypeSpec events[] = { - { kEventClassApplication, kEventAppShown }, - { kEventClassKeyboard, kEventRawKeyDown }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { 'P9PE', P9PEventLabelUpdate} - }; - - InstallApplicationEventHandler( - NewEventHandlerUPP(quithandler), - nelem(quits), quits, nil, nil); - - InstallApplicationEventHandler( - NewEventHandlerUPP(eventhandler), - nelem(events), events, nil, nil); - - InstallWindowEventHandler(osx.window, - NewEventHandlerUPP(cmdhandler), - nelem(cmds), cmds, osx.window, nil); - - // Finally, put the window on the screen. - ShowWindow(osx.window); - ShowMenuBar(); - eresized(0); - SelectWindow(osx.window); - - if(multitouch) - InitMultiTouch(); - - // CoreGraphics pins mouse events to the destination point of a - // CGWarpMouseCursorPosition (see setmouse) for an interval of time - // following the move. Disable this by setting the interval to zero - // seconds. - CGSetLocalEventsSuppressionInterval(0.0); - - InitCursor(); -} - -static Rendez scr; -static QLock slock; - -void -screeninit(void) -{ - scr.l = &slock; - qlock(scr.l); - proccreate(screenproc, nil, 256*1024); - while(osx.window == nil) - rsleep(&scr); - qunlock(scr.l); -} - -static void -screenproc(void *v) -{ - qlock(scr.l); - _screeninit(); - rwakeup(&scr); - qunlock(scr.l); - RunApplicationEventLoop(); -} - -static OSStatus kbdevent(EventRef); -static OSStatus mouseevent(EventRef); - -static OSStatus -cmdhandler(EventHandlerCallRef next, EventRef event, void *arg) -{ - return eventhandler(next, event, arg); -} - -static OSStatus -quithandler(EventHandlerCallRef next, EventRef event, void *arg) -{ - exit(0); - return 0; -} - -static OSStatus -eventhandler(EventHandlerCallRef next, EventRef event, void *arg) -{ - OSStatus result; - - result = CallNextEventHandler(next, event); - - switch(GetEventClass(event)){ - - case 'P9PE': - if(GetEventKind(event) == P9PEventLabelUpdate) { - qlock(&osx.labellock); - setlabel(osx.label); - qunlock(&osx.labellock); - return noErr; - } else - return eventNotHandledErr; - - case kEventClassApplication:; - Rectangle r = Rect(0, 0, Dx(osx.screenr), Dy(osx.screenr)); - _flushmemscreen(r); - return eventNotHandledErr; - - case kEventClassKeyboard: - return kbdevent(event); - - case kEventClassMouse: - return mouseevent(event); - - case kEventClassCommand:; - HICommand cmd; - GetEventParameter(event, kEventParamDirectObject, - typeHICommand, nil, sizeof cmd, nil, &cmd); - switch(cmd.commandID){ - case kHICommandQuit: - exit(0); - - case CmdFullScreen: - fullscreen(1); - break; - - default: - return eventNotHandledErr; - } - break; - - case kEventClassWindow: - switch(GetEventKind(event)){ - case kEventWindowClosed: - exit(0); - - case kEventWindowBoundsChanged:; - // We see kEventWindowDrawContent - // if we grow a window but not if we shrink it. - UInt32 flags; - GetEventParameter(event, kEventParamAttributes, - typeUInt32, 0, sizeof flags, 0, &flags); - int new = (flags & kWindowBoundsChangeSizeChanged) != 0; - eresized(new); - break; - - case kEventWindowDrawContent: - // Tried using just flushmemimage here, but - // it causes an odd artifact in which making a window - // bigger in both width and height can then only draw - // on the new border: it's like the old window is stuck - // floating on top. Doing a full "get a new window" - // seems to solve the problem. - eresized(1); - break; - - case kEventWindowActivated: - if(!osx.collapsed) - activated(1); - return eventNotHandledErr; - - case kEventWindowDeactivated: - activated(0); - return eventNotHandledErr; - - case kEventWindowCollapsed: - osx.collapsed = 1; - activated(0); - return eventNotHandledErr; - - case kEventWindowExpanded: - osx.collapsed = 0; - activated(1); - return eventNotHandledErr; - - default: - return eventNotHandledErr; - } - break; - } - - return result; -} - -static ulong -msec(void) -{ - return nsec()/1000000; -} - -static OSStatus -mouseevent(EventRef event) -{ - int wheel; - OSXPoint op; - - GetEventParameter(event, kEventParamMouseLocation, - typeQDPoint, 0, sizeof op, 0, &op); - - osx.xy = subpt(Pt(op.h, op.v), osx.screenr.min); - wheel = 0; - - switch(GetEventKind(event)){ - case kEventMouseWheelMoved:; - SInt32 delta; - GetEventParameter(event, kEventParamMouseWheelDelta, - typeSInt32, 0, sizeof delta, 0, &delta); - - // if I have any active touches in my region, I need to ignore the wheel motion. - //int i; - //for(i = 0; i < kNTracks; ++i) { - // if(tracks[i].id != -1 && tracks[i].pos.y > kButtonLimit) break; - //} - //if(i == kNTracks) { // No active touches, go ahead and scroll. - if(delta > 0) - wheel = 8; - else - wheel = 16; - //} - break; - - case kEventMouseDown: - case kEventMouseUp:; - UInt32 but, mod; - GetEventParameter(event, kEventParamMouseChord, - typeUInt32, 0, sizeof but, 0, &but); - GetEventParameter(event, kEventParamKeyModifiers, - typeUInt32, 0, sizeof mod, 0, &mod); - - // OS X swaps button 2 and 3 - but = (but & ~6) | ((but & 4)>>1) | ((but&2)<<1); - but = (but & ~((1<<10)-1)) | mouseswap(but & ((1<<10)-1)); - if(osx.touched) { - // in multitouch we use the clicks down to enable our - // virtual buttons. - if(but & 0x7) { - if(but>>29) - but = but >> 29; - } else - but = 0; - osx.touched = 0; - } - - // Apply keyboard modifiers and pretend it was a real mouse button. - // (Modifiers typed while holding the button go into kbuttons, - // but this one does not.) - if(but == 1){ - if(mod & optionKey) { - // Take the ALT away from the keyboard handler. - if(osx.kalting) { - osx.kalting = 0; - keystroke(Kalt); - } - but = 2; - } - else if(mod & cmdKey) - but = 4; - } - osx.buttons = but; - break; - - case kEventMouseMoved: - case kEventMouseDragged: - break; - - default: - return eventNotHandledErr; - } - - mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons|wheel, msec()); - return noErr; -} - -static int keycvt[] = -{ - [QZ_IBOOK_ENTER] '\n', - [QZ_RETURN] '\n', - [QZ_ESCAPE] 27, - [QZ_BACKSPACE] '\b', - [QZ_LALT] Kalt, - [QZ_LCTRL] Kctl, - [QZ_LSHIFT] Kshift, - [QZ_F1] KF+1, - [QZ_F2] KF+2, - [QZ_F3] KF+3, - [QZ_F4] KF+4, - [QZ_F5] KF+5, - [QZ_F6] KF+6, - [QZ_F7] KF+7, - [QZ_F8] KF+8, - [QZ_F9] KF+9, - [QZ_F10] KF+10, - [QZ_F11] KF+11, - [QZ_F12] KF+12, - [QZ_INSERT] Kins, - [QZ_DELETE] 0x7F, - [QZ_HOME] Khome, - [QZ_END] Kend, - [QZ_KP_PLUS] '+', - [QZ_KP_MINUS] '-', - [QZ_TAB] '\t', - [QZ_PAGEUP] Kpgup, - [QZ_PAGEDOWN] Kpgdown, - [QZ_UP] Kup, - [QZ_DOWN] Kdown, - [QZ_LEFT] Kleft, - [QZ_RIGHT] Kright, - [QZ_KP_MULTIPLY] '*', - [QZ_KP_DIVIDE] '/', - [QZ_KP_ENTER] '\n', - [QZ_KP_PERIOD] '.', - [QZ_KP0] '0', - [QZ_KP1] '1', - [QZ_KP2] '2', - [QZ_KP3] '3', - [QZ_KP4] '4', - [QZ_KP5] '5', - [QZ_KP6] '6', - [QZ_KP7] '7', - [QZ_KP8] '8', - [QZ_KP9] '9', -}; - -static OSStatus -kbdevent(EventRef event) -{ - char ch; - UInt32 code; - UInt32 mod; - int k; - - GetEventParameter(event, kEventParamKeyMacCharCodes, - typeChar, nil, sizeof ch, nil, &ch); - GetEventParameter(event, kEventParamKeyCode, - typeUInt32, nil, sizeof code, nil, &code); - GetEventParameter(event, kEventParamKeyModifiers, - typeUInt32, nil, sizeof mod, nil, &mod); - - switch(GetEventKind(event)){ - case kEventRawKeyDown: - case kEventRawKeyRepeat: - osx.kalting = 0; - if(mod == cmdKey){ - if(ch == 'F' || ch == 'f'){ - if(osx.isfullscreen && msec() - osx.fullscreentime > 500) - fullscreen(0); - return noErr; - } - - // Pass most Cmd keys through as Kcmd + ch. - // OS X interprets a few no matter what we do, - // so it is useless to pass them through as keystrokes too. - switch(ch) { - case 'm': // minimize window - case 'h': // hide window - case 'H': // hide others - case 'q': // quit - return eventNotHandledErr; - } - if(' ' <= ch && ch <= '~') { - keystroke(Kcmd + ch); - return noErr; - } - return eventNotHandledErr; - } - k = ch; - if(code < nelem(keycvt) && keycvt[code]) - k = keycvt[code]; - if(k == 0) - return noErr; - if(k > 0) - keystroke(k); - else{ - UniChar uc; - OSStatus s; - - s = GetEventParameter(event, kEventParamKeyUnicodes, - typeUnicodeText, nil, sizeof uc, nil, &uc); - if(s == noErr) - keystroke(uc); - } - break; - - case kEventRawKeyModifiersChanged: - if(!osx.buttons && !osx.kbuttons){ - if(mod == optionKey) { - osx.kalting = 1; - keystroke(Kalt); - } - break; - } - - // If the mouse button is being held down, treat - // changes in the keyboard modifiers as changes - // in the mouse buttons. - osx.kbuttons = 0; - if(mod & optionKey) - osx.kbuttons |= 2; - if(mod & cmdKey) - osx.kbuttons |= 4; - mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec()); - break; - } - return noErr; -} - -static void -eresized(int new) -{ - Memimage *m; - OSXRect or; - ulong chan; - Rectangle r; - int bpl; - CGDataProviderRef provider; - CGImageRef image; - CGColorSpaceRef cspace; - - GetWindowBounds(osx.window, kWindowContentRgn, &or); - r = Rect(or.left, or.top, or.right, or.bottom); - if(Dx(r) == Dx(osx.screenr) && Dy(r) == Dy(osx.screenr) && !new){ - // No need to make new image. - osx.screenr = r; - return; - } - - chan = XBGR32; - m = allocmemimage(Rect(0, 0, Dx(r), Dy(r)), chan); - if(m == nil) - panic("allocmemimage: %r"); - if(m->data == nil) - panic("m->data == nil"); - bpl = bytesperline(r, 32); - provider = CGDataProviderCreateWithData(0, - m->data->bdata, Dy(r)*bpl, 0); - //cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - cspace = CGColorSpaceCreateDeviceRGB(); - image = CGImageCreate(Dx(r), Dy(r), 8, 32, bpl, - cspace, - kCGImageAlphaNoneSkipLast, - provider, 0, 0, kCGRenderingIntentDefault); - CGColorSpaceRelease(cspace); - CGDataProviderRelease(provider); // CGImageCreate did incref - - mouserect = m->r; - if(new){ - mouseresized = 1; - mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec()); - } -// termreplacescreenimage(m); - _drawreplacescreenimage(m); // frees old osx.screenimage if any - if(osx.image) - CGImageRelease(osx.image); - osx.image = image; - osx.screenimage = m; - osx.screenr = r; - - if(new){ - qlock(&osx.flushlock); - QDEndCGContext(GetWindowPort(osx.window), &osx.windowctx); - osx.windowctx = nil; - qunlock(&osx.flushlock); - } -} - -void -flushproc(void *v) -{ - for(;;){ - if(osx.needflush && osx.windowctx && canqlock(&osx.flushlock)){ - if(osx.windowctx){ - CGContextFlush(osx.windowctx); - osx.needflush = 0; - } - qunlock(&osx.flushlock); - } - usleep(33333); - } -} - -void -_flushmemscreen(Rectangle r) -{ - CGRect cgr; - CGImageRef subimg; - - qlock(&osx.flushlock); - if(osx.windowctx == nil){ - QDBeginCGContext(GetWindowPort(osx.window), &osx.windowctx); - if(!osx.flushing) { - proccreate(flushproc, nil, 256*1024); - osx.flushing = 1; - } - } - - cgr.origin.x = r.min.x; - cgr.origin.y = r.min.y; - cgr.size.width = Dx(r); - cgr.size.height = Dy(r); - subimg = CGImageCreateWithImageInRect(osx.image, cgr); - cgr.origin.y = Dy(osx.screenr) - r.max.y; // XXX how does this make any sense? - CGContextDrawImage(osx.windowctx, cgr, subimg); - osx.needflush = 1; - qunlock(&osx.flushlock); - CGImageRelease(subimg); -} - -void -activated(int active) -{ -#ifdef MULTITOUCH - int i; - if(active) { - for(i = 0; i<[osx.devicelist count]; i++) { //iterate available devices - MTDeviceStart([osx.devicelist objectAtIndex:i], 0); //start sending events - } - } else { - osx.xy.x = -10000; - for(i = 0; i<[osx.devicelist count]; i++) { //iterate available devices - MTDeviceStop([osx.devicelist objectAtIndex:i]); //stop sending events - } - for(i = 0; igdRect; - if(dr.top == 0 && dr.left == 0) - HideMenuBar(); - GetWindowBounds(osx.window, kWindowContentRgn, &oldrect); - ChangeWindowAttributes(osx.window, - kWindowNoTitleBarAttribute, - kWindowResizableAttribute); - MoveWindow(osx.window, 0, 0, 1); - MoveWindow(osx.window, dr.left, dr.top, 0); - SizeWindow(osx.window, - dr.right - dr.left, - dr.bottom - dr.top, 0); - osx.isfullscreen = 1; - }else{ - ShowMenuBar(); - ChangeWindowAttributes(osx.window, - kWindowResizableAttribute, - kWindowNoTitleBarAttribute); - SizeWindow(osx.window, - oldrect.right - oldrect.left, - oldrect.bottom - oldrect.top, 0); - MoveWindow(osx.window, oldrect.left, oldrect.top, 0); - osx.isfullscreen = 0; - } - eresized(1); -} - -void -setmouse(Point p) -{ - CGPoint cgp; - - cgp.x = p.x + osx.screenr.min.x; - cgp.y = p.y + osx.screenr.min.y; - CGWarpMouseCursorPosition(cgp); - osx.xy = p; -} - -void -setcursor(Cursor *c) -{ - OSXCursor oc; - int i; - - if(c == nil){ - InitCursor(); - return; - } - - // SetCursor is deprecated, but what replaces it? - for(i=0; i<16; i++){ - oc.data[i] = ((ushort*)c->set)[i]; - oc.mask[i] = oc.data[i] | ((ushort*)c->clr)[i]; - } - oc.hotSpot.h = - c->offset.x; - oc.hotSpot.v = - c->offset.y; - SetCursor(&oc); -} - -void -getcolor(ulong i, ulong *r, ulong *g, ulong *b) -{ - ulong v; - - v = 0; - *r = (v>>16)&0xFF; - *g = (v>>8)&0xFF; - *b = v&0xFF; -} - -int -setcolor(ulong i, ulong r, ulong g, ulong b) -{ - /* no-op */ - return 0; -} - - -int -hwdraw(Memdrawparam *p) -{ - return 0; -} - -struct { - QLock lk; - char buf[SnarfSize]; - Rune rbuf[SnarfSize]; - PasteboardRef apple; -} clip; - -char* -getsnarf(void) -{ - char *s; - CFArrayRef flavors; - CFDataRef data; - CFIndex nflavor, ndata, j; - CFStringRef type; - ItemCount nitem; - PasteboardItemID id; - PasteboardSyncFlags flags; - UInt32 i; - u16int *u; - Fmt fmt; - Rune r; - -/* fprint(2, "applegetsnarf\n"); */ - qlock(&clip.lk); - clip.apple = osx.snarf; - if(clip.apple == nil){ - if(PasteboardCreate(kPasteboardClipboard, &clip.apple) != noErr){ - fprint(2, "apple pasteboard create failed\n"); - qunlock(&clip.lk); - return nil; - } - } - flags = PasteboardSynchronize(clip.apple); - if(flags&kPasteboardClientIsOwner){ - s = strdup(clip.buf); - qunlock(&clip.lk); - return s; - } - if(PasteboardGetItemCount(clip.apple, &nitem) != noErr){ - fprint(2, "apple pasteboard get item count failed\n"); - qunlock(&clip.lk); - return nil; - } - for(i=1; i<=nitem; i++){ - if(PasteboardGetItemIdentifier(clip.apple, i, &id) != noErr) - continue; - if(PasteboardCopyItemFlavors(clip.apple, id, &flavors) != noErr) - continue; - nflavor = CFArrayGetCount(flavors); - for(j=0; j= SnarfSize) - return; - qlock(&clip.lk); - strcpy(clip.buf, s); - runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s); - clip.apple = osx.snarf; - if(PasteboardClear(clip.apple) != noErr){ - fprint(2, "apple pasteboard clear failed\n"); - qunlock(&clip.lk); - return; - } - flags = PasteboardSynchronize(clip.apple); - if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){ - fprint(2, "apple pasteboard cannot assert ownership\n"); - qunlock(&clip.lk); - return; - } - u = malloc(runestrlen(clip.rbuf)*4); - p = u; - for(i=0; clip.rbuf[i]; i++) { - r = clip.rbuf[i]; - // convert to utf-16 - if(0xd800 <= r && r < 0xe000) - r = Runeerror; - if(r >= 0x10000) { - r -= 0x10000; - *p++ = 0xd800 + (r>>10); - *p++ = 0xdc00 + (r & ((1<<10)-1)); - } else - *p++ = r; - } - cfdata = CFDataCreate(kCFAllocatorDefault, - (uchar*)u, (p-u)*2); - free(u); - if(cfdata == nil){ - fprint(2, "apple pasteboard cfdatacreate failed\n"); - qunlock(&clip.lk); - return; - } - if(PasteboardPutItemFlavor(clip.apple, (PasteboardItemID)1, - CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){ - fprint(2, "apple pasteboard putitem failed\n"); - CFRelease(cfdata); - qunlock(&clip.lk); - return; - } - CFRelease(cfdata); - qunlock(&clip.lk); -} - -void -setlabel(char *label) -{ - CFStringRef cs; - - cs = CFStringCreateWithBytes(nil, (uchar*)label, strlen(label), kCFStringEncodingUTF8, false); - SetWindowTitleWithCFString(osx.window, cs); - CFRelease(cs); -} - -void -kicklabel(char *label) -{ - char *p; - EventRef e; - - p = strdup(label); - if(p == nil) - return; - qlock(&osx.labellock); - free(osx.label); - osx.label = p; - qunlock(&osx.labellock); - - CreateEvent(nil, 'P9PE', P9PEventLabelUpdate, 0, kEventAttributeUserEvent, &e); - PostEventToQueue(GetMainEventQueue(), e, kEventPriorityStandard); - -} - -static void -seticon(void) -{ - CGImageRef im; - CGDataProviderRef d; - - d = CGDataProviderCreateWithData(nil, glenda_png, sizeof glenda_png, nil); - im = CGImageCreateWithPNGDataProvider(d, nil, true, kCGRenderingIntentDefault); - if(im) - SetApplicationDockTileImage(im); - CGImageRelease(im); - CGDataProviderRelease(d); -} - blob - d5ba3dd24c6a00ba845250087caf07a50a8cd864 (mode 644) blob + /dev/null --- src/cmd/devdraw/osx-screen.h +++ /dev/null @@ -1,18 +0,0 @@ -void zlock(void); -void zunlock(void); - -#define setcursor dsetcursor - -Memimage *attachscreen(char*, char*); -void setmouse(Point); -void setcursor(Cursor*, Cursor2*); -void setlabel(char*); -char* getsnarf(void); -void putsnarf(char*); - -void mousetrack(int, int, int, int); -void keystroke(int); -void kicklabel(char*); - -extern Rectangle mouserect; -extern int mouseresized; blob - d0a1c2d311ae87adb231fc10ac4379fb0d5f82b7 (mode 644) blob + /dev/null --- src/cmd/devdraw/osx-srv.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Window system protocol server. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "osx-screen.h" -#include "devdraw.h" - -#undef time - -#define MouseMask (\ - ButtonPressMask|\ - ButtonReleaseMask|\ - PointerMotionMask|\ - Button1MotionMask|\ - Button2MotionMask|\ - Button3MotionMask) - -#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask - -typedef struct Kbdbuf Kbdbuf; -typedef struct Mousebuf Mousebuf; -typedef struct Fdbuf Fdbuf; -typedef struct Tagbuf Tagbuf; - -struct Kbdbuf -{ - Rune r[32]; - int ri; - int wi; - int stall; -}; - -struct Mousebuf -{ - Mouse m[32]; - Mouse last; - int ri; - int wi; - int stall; -}; - -struct Tagbuf -{ - int t[32]; - int ri; - int wi; -}; - -Kbdbuf kbd; -Mousebuf mouse; -Tagbuf kbdtags; -Tagbuf mousetags; - -void fdslide(Fdbuf*); -void runmsg(Wsysmsg*); -void replymsg(Wsysmsg*); -void matchkbd(void); -void matchmouse(void); -int fdnoblock(int); -Rectangle mouserect; -int mouseresized; - - -QLock lk; -void -zlock(void) -{ - qlock(&lk); -} - -void -zunlock(void) -{ - qunlock(&lk); -} - -int chatty; -int drawsleep; -int trace; -int multitouch = 1; - -void -usage(void) -{ - fprint(2, "usage: devdraw (don't run directly)\n"); - threadexitsall("usage"); -} - -void -bell(void *v, char *msg) -{ - if(strcmp(msg, "alarm") == 0) - drawsleep = drawsleep ? 0 : 1000; - noted(NCONT); -} - -void -threadmain(int argc, char **argv) -{ - uchar buf[4], *mbuf; - int nmbuf, n, nn; - Wsysmsg m; - - /* - * Move the protocol off stdin/stdout so that - * any inadvertent prints don't screw things up. - */ - dup(0, 3); - dup(1, 4); - close(0); - close(1); - open("/dev/null", OREAD); - open("/dev/null", OWRITE); - -//trace = 1; - fmtinstall('W', drawfcallfmt); - - ARGBEGIN{ - case 'D': - chatty++; - break; - case 'M': - multitouch = 0; - break; - default: - usage(); - }ARGEND - - /* - * Ignore arguments. They're only for good ps -a listings. - */ - - notify(bell); - - mbuf = nil; - nmbuf = 0; - while((n = read(3, buf, 4)) == 4){ - GET(buf, n); - if(n > nmbuf){ - free(mbuf); - mbuf = malloc(4+n); - if(mbuf == nil) - sysfatal("malloc: %r"); - nmbuf = n; - } - memmove(mbuf, buf, 4); - nn = readn(3, mbuf+4, n-4); - if(nn != n-4) - sysfatal("eof during message"); - - /* pick off messages one by one */ - if(convM2W(mbuf, nn+4, &m) <= 0) - sysfatal("cannot convert message"); - if(trace) fprint(2, "<- %W\n", &m); - runmsg(&m); - } - threadexitsall(0); -} - -void -replyerror(Wsysmsg *m) -{ - char err[256]; - - rerrstr(err, sizeof err); - m->type = Rerror; - m->error = err; - replymsg(m); -} - -/* - * Handle a single wsysmsg. - * Might queue for later (kbd, mouse read) - */ -void -runmsg(Wsysmsg *m) -{ - static uchar buf[65536]; - int n; - Memimage *i; - - switch(m->type){ - case Tinit: - memimageinit(); - i = attachscreen(m->label, m->winsize); - _initdisplaymemimage(i); - replymsg(m); - break; - - case Trdmouse: - zlock(); - mousetags.t[mousetags.wi++] = m->tag; - if(mousetags.wi == nelem(mousetags.t)) - mousetags.wi = 0; - if(mousetags.wi == mousetags.ri) - sysfatal("too many queued mouse reads"); - mouse.stall = 0; - matchmouse(); - zunlock(); - break; - - case Trdkbd: - zlock(); - kbdtags.t[kbdtags.wi++] = m->tag; - if(kbdtags.wi == nelem(kbdtags.t)) - kbdtags.wi = 0; - if(kbdtags.wi == kbdtags.ri) - sysfatal("too many queued keyboard reads"); - kbd.stall = 0; - matchkbd(); - zunlock(); - break; - - case Tmoveto: - setmouse(m->mouse.xy); - replymsg(m); - break; - - case Tcursor: - if(m->arrowcursor) - setcursor(nil, nil); - else - setcursor(&m->cursor, &m->cursor2); - replymsg(m); - break; - - case Tbouncemouse: - // _xbouncemouse(&m->mouse); - replymsg(m); - break; - - case Tlabel: - kicklabel(m->label); - replymsg(m); - break; - - case Trdsnarf: - m->snarf = getsnarf(); - replymsg(m); - free(m->snarf); - break; - - case Twrsnarf: - putsnarf(m->snarf); - replymsg(m); - break; - - case Trddraw: - n = m->count; - if(n > sizeof buf) - n = sizeof buf; - n = _drawmsgread(buf, n); - if(n < 0) - replyerror(m); - else{ - m->count = n; - m->data = buf; - replymsg(m); - } - break; - - case Twrdraw: - if(_drawmsgwrite(m->data, m->count) < 0) - replyerror(m); - else - replymsg(m); - break; - - case Ttop: - // _xtopwindow(); - replymsg(m); - break; - - case Tresize: - // _xresizewindow(m->rect); - replymsg(m); - break; - } -} - -/* - * Reply to m. - */ -QLock replylock; -void -replymsg(Wsysmsg *m) -{ - int n; - static uchar *mbuf; - static int nmbuf; - - /* T -> R msg */ - if(m->type%2 == 0) - m->type++; - - if(trace) fprint(2, "-> %W\n", m); - /* copy to output buffer */ - n = sizeW2M(m); - - qlock(&replylock); - if(n > nmbuf){ - free(mbuf); - mbuf = malloc(n); - if(mbuf == nil) - sysfatal("out of memory"); - nmbuf = n; - } - convW2M(m, mbuf, n); - if(write(4, mbuf, n) != n) - sysfatal("write: %r"); - qunlock(&replylock); -} - -/* - * Match queued kbd reads with queued kbd characters. - */ -void -matchkbd(void) -{ - Wsysmsg m; - - if(kbd.stall) - return; - while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){ - m.type = Rrdkbd; - m.tag = kbdtags.t[kbdtags.ri++]; - if(kbdtags.ri == nelem(kbdtags.t)) - kbdtags.ri = 0; - m.rune = kbd.r[kbd.ri++]; - if(kbd.ri == nelem(kbd.r)) - kbd.ri = 0; - replymsg(&m); - } -} - -/* - * Match queued mouse reads with queued mouse events. - */ -void -matchmouse(void) -{ - Wsysmsg m; - - while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){ - m.type = Rrdmouse; - m.tag = mousetags.t[mousetags.ri++]; - if(mousetags.ri == nelem(mousetags.t)) - mousetags.ri = 0; - m.mouse = mouse.m[mouse.ri]; - m.resized = mouseresized; - /* - if(m.resized) - fprint(2, "sending resize\n"); - */ - mouseresized = 0; - mouse.ri++; - if(mouse.ri == nelem(mouse.m)) - mouse.ri = 0; - replymsg(&m); - } -} - -void -mousetrack(int x, int y, int b, int ms) -{ - Mouse *m; - - if(x < mouserect.min.x) - x = mouserect.min.x; - if(x > mouserect.max.x) - x = mouserect.max.x; - if(y < mouserect.min.y) - y = mouserect.min.y; - if(y > mouserect.max.y) - y = mouserect.max.y; - - zlock(); - // If reader has stopped reading, don't bother. - // If reader is completely caught up, definitely queue. - // Otherwise, queue only button change events. - if(!mouse.stall) - if(mouse.wi == mouse.ri || mouse.last.buttons != b){ - m = &mouse.last; - m->xy.x = x; - m->xy.y = y; - m->buttons = b; - m->msec = ms; - - mouse.m[mouse.wi] = *m; - if(++mouse.wi == nelem(mouse.m)) - mouse.wi = 0; - if(mouse.wi == mouse.ri){ - mouse.stall = 1; - mouse.ri = 0; - mouse.wi = 1; - mouse.m[0] = *m; - } - matchmouse(); - } - zunlock(); -} - -void -kputc(int c) -{ - zlock(); - kbd.r[kbd.wi++] = c; - if(kbd.wi == nelem(kbd.r)) - kbd.wi = 0; - if(kbd.ri == kbd.wi) - kbd.stall = 1; - matchkbd(); - zunlock(); -} - -void -keystroke(int c) -{ - static Rune k[10]; - static int alting, nk; - int i; - - if(c == Kalt){ - alting = !alting; - return; - } - if(!alting){ - kputc(c); - return; - } - if(nk >= nelem(k)) // should not happen - nk = 0; - k[nk++] = c; - c = _latin1(k, nk); - if(c > 0){ - alting = 0; - kputc(c); - nk = 0; - return; - } - if(c == -1){ - alting = 0; - for(i=0; i