#define Point OSXPoint#define Rect OSXRect#define Cursor OSXCursor#include <Carbon/Carbon.h>#undef Rect#undef Point#undef Cursor#undef offsetof#undef nil #include "u.h"#include "libc.h"#include <thread.h>#include <draw.h>#include <memdraw.h>#include <keyboard.h>#include "mouse.h"#include <cursor.h>#include "osx-screen.h"#include "osx-keycodes.h"#include "devdraw.h"#include "glendapng.h" AUTOFRAMEWORK(Carbon) #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} osx; 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); 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;} 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 }, { kEventClassCommand, kEventCommandProcess }, { kEventClassWindow, kEventWindowActivated }, { kEventClassWindow, kEventWindowDeactivated }, }; 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); InitCursor();} static Rendez scr;static QLock slock; voidscreeninit(void){ scr.l = &slock; qlock(scr.l); proccreate(screenproc, nil, 256*1024); while(osx.window == nil) rsleep(&scr); qunlock(scr.l);} static voidscreenproc(void *v){ qlock(scr.l); _screeninit(); rwakeup(&scr); qunlock(scr.l); RunApplicationEventLoop();} static OSStatus kbdevent(EventRef);static OSStatus mouseevent(EventRef); static OSStatuscmdhandler(EventHandlerCallRef next, EventRef event, void *arg){ return eventhandler(next, event, arg);} static OSStatusquithandler(EventHandlerCallRef next, EventRef event, void *arg){ exit(0); return 0;} static OSStatuseventhandler(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: eresized(1); break; case kEventWindowActivated: activated(1); return eventNotHandledErr; case kEventWindowDeactivated: activated(0); return eventNotHandledErr; default: return eventNotHandledErr; } break; } return result;} static ulongmsec(void){ return nsec()/1000000;} static OSStatusmouseevent(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(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 = mouseswap(but); // 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 OSStatuskbdevent(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) keystroke(k); else{ UniChar uc; OSStatus s; s = GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, nil, sizeof uc, nil, &uc); if(s == noErr) keystroke(uc); } break; Lines 1–500 of 911. Load more
#define Point OSXPoint #define Rect OSXRect #define Cursor OSXCursor #include <Carbon/Carbon.h> #undef Rect #undef Point #undef Cursor #undef offsetof #undef nil #include "u.h" #include "libc.h" #include <thread.h> #include <draw.h> #include <memdraw.h> #include <keyboard.h> #include "mouse.h" #include <cursor.h> #include "osx-screen.h" #include "osx-keycodes.h" #include "devdraw.h" #include "glendapng.h" AUTOFRAMEWORK(Carbon) #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 } osx; 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); 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; } 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 }, { kEventClassCommand, kEventCommandProcess }, { kEventClassWindow, kEventWindowActivated }, { kEventClassWindow, kEventWindowDeactivated }, }; 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); 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: eresized(1); break; case kEventWindowActivated: activated(1); return eventNotHandledErr; case kEventWindowDeactivated: activated(0); 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(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 = mouseswap(but); // 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) keystroke(k); else{ UniChar uc; OSStatus s; s = GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, nil, sizeof uc, nil, &uc); if(s == noErr) keystroke(uc); } break;