Updates for 386 OS X, add native OS X graphics from Paul Lalonde
This commit is contained in:
666
gui-osx/screen.c
Normal file
666
gui-osx/screen.c
Normal file
@ -0,0 +1,666 @@
|
||||
// in this file, _Rect is os x Rect,
|
||||
// _Point is os x Point
|
||||
#undef Point
|
||||
#define Point _Point
|
||||
#undef Rect
|
||||
#define Rect _Rect
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <QuickTime/QuickTime.h> // for full screen
|
||||
|
||||
#undef Rect
|
||||
#undef Point
|
||||
|
||||
#undef nil
|
||||
|
||||
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "kern/dat.h"
|
||||
#include "kern/fns.h"
|
||||
#include "error.h"
|
||||
#include "user.h"
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "screen.h"
|
||||
#include "keyboard.h"
|
||||
#include "keycodes.h"
|
||||
|
||||
#define rWindowResource 128
|
||||
|
||||
#define topLeft(r) (((Point *) &(r))[0])
|
||||
#define botRight(r) (((Point *) &(r))[1])
|
||||
|
||||
extern int mousequeue;
|
||||
static int depth;
|
||||
Boolean gDone;
|
||||
RgnHandle gCursorRegionHdl;
|
||||
|
||||
Memimage *gscreen;
|
||||
Screeninfo screen;
|
||||
|
||||
static int readybit;
|
||||
static Rendez rend;
|
||||
|
||||
///
|
||||
// menu
|
||||
//
|
||||
static MenuRef windMenu;
|
||||
static MenuRef viewMenu;
|
||||
|
||||
enum {
|
||||
kQuitCmd = 1,
|
||||
kFullScreenCmd = 2,
|
||||
};
|
||||
|
||||
static WindowGroupRef winGroup = NULL;
|
||||
static WindowRef theWindow = NULL;
|
||||
static CGContextRef context;
|
||||
static CGDataProviderRef dataProviderRef;
|
||||
static CGImageRef fullScreenImage;
|
||||
static CGRect devRect;
|
||||
static CGRect bounds;
|
||||
static PasteboardRef appleclip;
|
||||
static _Rect winRect;
|
||||
|
||||
|
||||
static int
|
||||
isready(void*a)
|
||||
{
|
||||
return readybit;
|
||||
}
|
||||
|
||||
CGContextRef QuartzContext;
|
||||
|
||||
void winproc(void *a);
|
||||
|
||||
void screeninit(void)
|
||||
{
|
||||
int fmt;
|
||||
int dx, dy;
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
|
||||
memimageinit();
|
||||
depth = 32; // That's all this code deals with for now
|
||||
screen.depth = 32;
|
||||
fmt = XBGR32; //XRGB32;
|
||||
|
||||
devRect = CGDisplayBounds(CGMainDisplayID());
|
||||
// devRect.origin.x = 0;
|
||||
// devRect.origin.y = 0;
|
||||
// devRect.size.width = 1024;
|
||||
// devRect.size.height = 768;
|
||||
dx = devRect.size.width;
|
||||
dy = devRect.size.height;
|
||||
|
||||
gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
|
||||
dataProviderRef = CGDataProviderCreateWithData(0, gscreen->data->bdata,
|
||||
dx * dy * 4, 0);
|
||||
fullScreenImage = CGImageCreate(dx, dy, 8, 32, dx * 4,
|
||||
CGColorSpaceCreateDeviceRGB(),
|
||||
kCGImageAlphaNoneSkipLast,
|
||||
dataProviderRef, 0, 0, kCGRenderingIntentDefault);
|
||||
|
||||
kproc("osxscreen", winproc, 0);
|
||||
ksleep(&rend, isready, 0);
|
||||
}
|
||||
|
||||
static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
|
||||
static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
|
||||
|
||||
void
|
||||
window_resized()
|
||||
{
|
||||
GetWindowBounds(theWindow, kWindowContentRgn, &winRect );
|
||||
|
||||
bounds = CGRectMake(0, 0, winRect.right-winRect.left, winRect.bottom - winRect.top);
|
||||
}
|
||||
|
||||
|
||||
void winproc(void *a)
|
||||
{
|
||||
winRect.left = 30;
|
||||
winRect.top = 60;
|
||||
winRect.bottom = (devRect.size.height * 0.75) + winRect.top;
|
||||
winRect.right = (devRect.size.width * 0.75) + winRect.left;
|
||||
|
||||
ClearMenuBar();
|
||||
InitCursor();
|
||||
|
||||
CreateStandardWindowMenu(0, &windMenu);
|
||||
InsertMenu(windMenu, 0);
|
||||
|
||||
MenuItemIndex index;
|
||||
CreateNewMenu(1004, 0, &viewMenu);
|
||||
SetMenuTitleWithCFString(viewMenu, CFSTR("View"));
|
||||
AppendMenuItemTextWithCFString(viewMenu, CFSTR("Full Screen"), 0,
|
||||
kFullScreenCmd, &index);
|
||||
SetMenuItemCommandKey(viewMenu, index, 0, 'F');
|
||||
AppendMenuItemTextWithCFString(viewMenu, CFSTR("ctrl-opt to return"),
|
||||
kMenuItemAttrDisabled,
|
||||
kFullScreenCmd, &index);
|
||||
InsertMenu(viewMenu, GetMenuID(windMenu));
|
||||
|
||||
DrawMenuBar();
|
||||
uint32_t windowAttrs = 0
|
||||
| kWindowCloseBoxAttribute
|
||||
| kWindowCollapseBoxAttribute
|
||||
| kWindowResizableAttribute
|
||||
| kWindowStandardHandlerAttribute
|
||||
| kWindowFullZoomAttribute
|
||||
;
|
||||
|
||||
CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
|
||||
CreateWindowGroup(0, &winGroup);
|
||||
SetWindowGroup(theWindow, winGroup);
|
||||
|
||||
SetWindowTitleWithCFString(theWindow, CFSTR("Drawterm"));
|
||||
|
||||
if(PasteboardCreate(kPasteboardClipboard, &appleclip) != noErr)
|
||||
sysfatal("pasteboard create failed");
|
||||
|
||||
const EventTypeSpec commands[] = {
|
||||
{ kEventClassWindow, kEventWindowClosed },
|
||||
{ kEventClassWindow, kEventWindowBoundsChanged },
|
||||
{ kEventClassCommand, kEventCommandProcess }
|
||||
};
|
||||
const EventTypeSpec events[] = {
|
||||
{ kEventClassKeyboard, kEventRawKeyDown },
|
||||
{ kEventClassKeyboard, kEventRawKeyModifiersChanged },
|
||||
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseUp },
|
||||
{ kEventClassMouse, kEventMouseMoved },
|
||||
{ kEventClassMouse, kEventMouseDragged },
|
||||
{ kEventClassMouse, kEventMouseWheelMoved },
|
||||
};
|
||||
|
||||
InstallApplicationEventHandler (
|
||||
NewEventHandlerUPP (MainWindowEventHandler),
|
||||
GetEventTypeCount(events),
|
||||
events,
|
||||
NULL,
|
||||
NULL);
|
||||
InstallWindowEventHandler (
|
||||
theWindow,
|
||||
NewEventHandlerUPP (MainWindowCommandHandler),
|
||||
GetEventTypeCount(commands),
|
||||
commands,
|
||||
theWindow,
|
||||
NULL);
|
||||
|
||||
ShowWindow(theWindow);
|
||||
ShowMenuBar();
|
||||
window_resized();
|
||||
SelectWindow(theWindow);
|
||||
terminit();
|
||||
// Run the event loop
|
||||
readybit = 1;
|
||||
wakeup(&rend);
|
||||
RunApplicationEventLoop();
|
||||
|
||||
}
|
||||
|
||||
static inline int convert_key(UInt32 key, UInt32 charcode)
|
||||
{
|
||||
switch(key) {
|
||||
case QZ_IBOOK_ENTER:
|
||||
case QZ_RETURN: return '\n';
|
||||
case QZ_ESCAPE: return 27;
|
||||
case QZ_BACKSPACE: return '\b';
|
||||
case QZ_LALT: return Kalt;
|
||||
case QZ_LCTRL: return Kctl;
|
||||
case QZ_LSHIFT: return Kshift;
|
||||
case QZ_F1: return KF+1;
|
||||
case QZ_F2: return KF+2;
|
||||
case QZ_F3: return KF+3;
|
||||
case QZ_F4: return KF+4;
|
||||
case QZ_F5: return KF+5;
|
||||
case QZ_F6: return KF+6;
|
||||
case QZ_F7: return KF+7;
|
||||
case QZ_F8: return KF+8;
|
||||
case QZ_F9: return KF+9;
|
||||
case QZ_F10: return KF+10;
|
||||
case QZ_F11: return KF+11;
|
||||
case QZ_F12: return KF+12;
|
||||
case QZ_INSERT: return Kins;
|
||||
case QZ_DELETE: return '0';
|
||||
case QZ_HOME: return Khome;
|
||||
case QZ_END: return Kend;
|
||||
case QZ_KP_PLUS: return '+';
|
||||
case QZ_KP_MINUS: return '-';
|
||||
case QZ_TAB: return '\t';
|
||||
case QZ_PAGEUP: return Kpgup;
|
||||
case QZ_PAGEDOWN: return Kpgdown;
|
||||
case QZ_UP: return Kup;
|
||||
case QZ_DOWN: return Kdown;
|
||||
case QZ_LEFT: return Kleft;
|
||||
case QZ_RIGHT: return Kright;
|
||||
case QZ_KP_MULTIPLY: return '*';
|
||||
case QZ_KP_DIVIDE: return '/';
|
||||
case QZ_KP_ENTER: return '\b';
|
||||
case QZ_KP_PERIOD: return '.';
|
||||
case QZ_KP0: return '0';
|
||||
case QZ_KP1: return '1';
|
||||
case QZ_KP2: return '2';
|
||||
case QZ_KP3: return '3';
|
||||
case QZ_KP4: return '4';
|
||||
case QZ_KP5: return '5';
|
||||
case QZ_KP6: return '6';
|
||||
case QZ_KP7: return '7';
|
||||
case QZ_KP8: return '8';
|
||||
case QZ_KP9: return '9';
|
||||
default: return charcode;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sendbuttons(int b, int x, int y)
|
||||
{
|
||||
int i;
|
||||
lock(&mouse.lk);
|
||||
i = mouse.wi;
|
||||
if(mousequeue) {
|
||||
if(i == mouse.ri || mouse.lastb != b || mouse.trans) {
|
||||
mouse.wi = (i+1)%Mousequeue;
|
||||
if(mouse.wi == mouse.ri)
|
||||
mouse.ri = (mouse.ri+1)%Mousequeue;
|
||||
mouse.trans = mouse.lastb != b;
|
||||
} else {
|
||||
i = (i-1+Mousequeue)%Mousequeue;
|
||||
}
|
||||
} else {
|
||||
mouse.wi = (i+1)%Mousequeue;
|
||||
mouse.ri = i;
|
||||
}
|
||||
mouse.queue[i].xy.x = x;
|
||||
mouse.queue[i].xy.y = y;
|
||||
mouse.queue[i].buttons = b;
|
||||
mouse.queue[i].msec = ticks();
|
||||
mouse.lastb = b;
|
||||
unlock(&mouse.lk);
|
||||
wakeup(&mouse.r);
|
||||
}
|
||||
|
||||
static Ptr fullScreenRestore;
|
||||
static int amFullScreen = 0;
|
||||
static WindowRef oldWindow = NULL;
|
||||
|
||||
static void
|
||||
leave_full_screen()
|
||||
{
|
||||
if (amFullScreen) {
|
||||
EndFullScreen(fullScreenRestore, 0);
|
||||
theWindow = oldWindow;
|
||||
ShowWindow(theWindow);
|
||||
amFullScreen = 0;
|
||||
window_resized();
|
||||
Rectangle rect = { { 0, 0 },
|
||||
{ bounds.size.width,
|
||||
bounds.size.height} };
|
||||
flushmemscreen(rect);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
full_screen()
|
||||
{
|
||||
if (!amFullScreen) {
|
||||
oldWindow = theWindow;
|
||||
HideWindow(theWindow);
|
||||
BeginFullScreen(&fullScreenRestore, 0, 0, 0, &theWindow, 0, 0);
|
||||
amFullScreen = 1;
|
||||
window_resized();
|
||||
Rectangle rect = { { 0, 0 },
|
||||
{ bounds.size.width,
|
||||
bounds.size.height} };
|
||||
flushmemscreen(rect);
|
||||
}
|
||||
}
|
||||
|
||||
static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
result = CallNextEventHandler(nextHandler, event);
|
||||
UInt32 class = GetEventClass (event);
|
||||
UInt32 kind = GetEventKind (event);
|
||||
if(class == kEventClassKeyboard) {
|
||||
char macCharCodes;
|
||||
UInt32 macKeyCode;
|
||||
UInt32 macKeyModifiers;
|
||||
|
||||
GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar,
|
||||
NULL, sizeof(macCharCodes), NULL, &macCharCodes);
|
||||
GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL,
|
||||
sizeof(macKeyCode), NULL, &macKeyCode);
|
||||
GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
|
||||
sizeof(macKeyModifiers), NULL, &macKeyModifiers);
|
||||
switch(kind) {
|
||||
case kEventRawKeyModifiersChanged:
|
||||
if ( macKeyModifiers == 0x1800 ) leave_full_screen();
|
||||
break;
|
||||
case kEventRawKeyDown:
|
||||
case kEventRawKeyRepeat: {
|
||||
if(macKeyModifiers != 256) {
|
||||
if (kind == kEventRawKeyRepeat || kind == kEventRawKeyDown) {
|
||||
int key = convert_key(macKeyCode, macCharCodes);
|
||||
if (key != -1) kbdputc(kbdq, key);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(class == kEventClassMouse) {
|
||||
_Point mousePos;
|
||||
|
||||
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
|
||||
0, sizeof mousePos, 0, &mousePos);
|
||||
|
||||
static uint32_t mousebuttons = 0; // bitmask of buttons currently down
|
||||
|
||||
switch (kind) {
|
||||
case kEventMouseWheelMoved:
|
||||
{
|
||||
int32_t wheeldelta;
|
||||
GetEventParameter(event,kEventParamMouseWheelDelta,typeSInt32,
|
||||
0,sizeof(EventMouseButton), 0, &wheeldelta);
|
||||
sendbuttons((int16_t)wheeldelta>0 ? 8 : 16,
|
||||
mousePos.h - winRect.left,
|
||||
mousePos.v - winRect.top);
|
||||
break;
|
||||
}
|
||||
case kEventMouseUp:
|
||||
case kEventMouseDown:
|
||||
{
|
||||
uint32_t buttons;
|
||||
GetEventParameter(event, kEventParamMouseChord,
|
||||
typeUInt32, 0, sizeof buttons, 0, &buttons);
|
||||
mousebuttons = (buttons & 1)
|
||||
| ((buttons & 2)<<1)
|
||||
| ((buttons & 4)>>1);
|
||||
} /* Fallthrough */
|
||||
case kEventMouseMoved:
|
||||
case kEventMouseDragged:
|
||||
{
|
||||
sendbuttons(mousebuttons,
|
||||
mousePos.h - winRect.left,
|
||||
mousePos.v - winRect.top);
|
||||
}
|
||||
break;
|
||||
|
||||
default:result = eventNotHandledErr;break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//default window command handler (from menus)
|
||||
static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler,
|
||||
EventRef event, void *userData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
UInt32 class = GetEventClass (event);
|
||||
UInt32 kind = GetEventKind (event);
|
||||
|
||||
result = CallNextEventHandler(nextHandler, event);
|
||||
|
||||
if(class == kEventClassCommand)
|
||||
{
|
||||
HICommand theHICommand;
|
||||
GetEventParameter( event, kEventParamDirectObject, typeHICommand,
|
||||
NULL, sizeof( HICommand ), NULL, &theHICommand );
|
||||
|
||||
switch ( theHICommand.commandID )
|
||||
{
|
||||
case kHICommandQuit:
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case kFullScreenCmd:
|
||||
full_screen();
|
||||
break;
|
||||
|
||||
default:
|
||||
result = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(class == kEventClassWindow)
|
||||
{
|
||||
WindowRef window;
|
||||
_Rect rectPort = {0,0,0,0};
|
||||
|
||||
GetEventParameter(event, kEventParamDirectObject, typeWindowRef,
|
||||
NULL, sizeof(WindowRef), NULL, &window);
|
||||
|
||||
if(window)
|
||||
{
|
||||
GetPortBounds(GetWindowPort(window), &rectPort);
|
||||
}
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case kEventWindowClosed:
|
||||
theWindow = NULL;
|
||||
exit(0); // only one window
|
||||
break;
|
||||
|
||||
//resize window
|
||||
case kEventWindowBoundsChanged:
|
||||
window_resized();
|
||||
Rectangle rect = { { 0, 0 },
|
||||
{ bounds.size.width,
|
||||
bounds.size.height} };
|
||||
flushmemscreen(rect);
|
||||
break;
|
||||
|
||||
default:
|
||||
result = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
flushmemscreen(Rectangle r)
|
||||
{
|
||||
// sanity check. Trips from the initial "terminal"
|
||||
if (r.max.x < r.min.x || r.max.y < r.min.y) return;
|
||||
|
||||
screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP,
|
||||
gscreen->width*sizeof(ulong));
|
||||
}
|
||||
|
||||
uchar*
|
||||
attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X)
|
||||
{
|
||||
*r = gscreen->r;
|
||||
*chan = gscreen->chan;
|
||||
*depth = gscreen->depth;
|
||||
*width = gscreen->width;
|
||||
*softscreen = 1;
|
||||
|
||||
return gscreen->data->bdata;
|
||||
}
|
||||
|
||||
// PAL - no palette handling. Don't intend to either.
|
||||
void
|
||||
getcolor(ulong i, ulong *r, ulong *g, ulong *b)
|
||||
{
|
||||
|
||||
// PAL: Certainly wrong to return a grayscale.
|
||||
*r = i;
|
||||
*g = i;
|
||||
*b = i;
|
||||
}
|
||||
|
||||
void
|
||||
setcolor(ulong index, ulong red, ulong green, ulong blue)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
static char snarf[3*SnarfSize+1];
|
||||
static Rune rsnarf[SnarfSize+1];
|
||||
|
||||
char*
|
||||
clipread(void)
|
||||
{
|
||||
CFDataRef cfdata;
|
||||
OSStatus err = noErr;
|
||||
ItemCount nItems;
|
||||
|
||||
// Wow. This is ridiculously complicated.
|
||||
PasteboardSynchronize(appleclip);
|
||||
if((err = PasteboardGetItemCount(appleclip, &nItems)) != noErr) {
|
||||
fprint(2, "apple pasteboard GetItemCount failed - Error %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
// Yes, based at 1. Silly API.
|
||||
for(i = 1; i <= nItems; ++i) {
|
||||
PasteboardItemID itemID;
|
||||
CFArrayRef flavorTypeArray;
|
||||
CFIndex flavorCount;
|
||||
|
||||
if((err = PasteboardGetItemIdentifier(appleclip, i, &itemID)) != noErr){
|
||||
fprint(2, "Can't get pasteboard item identifier: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((err = PasteboardCopyItemFlavors(appleclip, itemID, &flavorTypeArray))!=noErr){
|
||||
fprint(2, "Can't copy pasteboard item flavors: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
flavorCount = CFArrayGetCount(flavorTypeArray);
|
||||
CFIndex flavorIndex;
|
||||
for(flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex){
|
||||
CFStringRef flavorType;
|
||||
flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
|
||||
if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))){
|
||||
if((err = PasteboardCopyItemFlavorData(appleclip, itemID,
|
||||
CFSTR("public.utf16-plain-text"), &cfdata)) != noErr){
|
||||
fprint(2, "apple pasteboard CopyItem failed - Error %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
CFIndex length = CFDataGetLength(cfdata);
|
||||
if (length > sizeof rsnarf) length = sizeof rsnarf;
|
||||
CFDataGetBytes(cfdata, CFRangeMake(0, length), (uint8_t *)rsnarf);
|
||||
snprint(snarf, sizeof snarf, "%S", rsnarf);
|
||||
char *s = snarf;
|
||||
while (*s) {
|
||||
if (*s == '\r') *s = '\n';
|
||||
s++;
|
||||
}
|
||||
CFRelease(cfdata);
|
||||
return strdup(snarf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
clipwrite(char *snarf)
|
||||
{
|
||||
CFDataRef cfdata;
|
||||
PasteboardSyncFlags flags;
|
||||
|
||||
runesnprint(rsnarf, nelem(rsnarf), "%s", snarf);
|
||||
if(PasteboardClear(appleclip) != noErr){
|
||||
fprint(2, "apple pasteboard clear failed\n");
|
||||
return 0;
|
||||
}
|
||||
flags = PasteboardSynchronize(appleclip);
|
||||
if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
|
||||
fprint(2, "apple pasteboard cannot assert ownership\n");
|
||||
return 0;
|
||||
}
|
||||
cfdata = CFDataCreate(kCFAllocatorDefault,
|
||||
(uchar*)rsnarf, runestrlen(rsnarf)*2);
|
||||
if(cfdata == nil){
|
||||
fprint(2, "apple pasteboard cfdatacreate failed\n");
|
||||
return 0;
|
||||
}
|
||||
if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1,
|
||||
CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
|
||||
fprint(2, "apple pasteboard putitem failed\n");
|
||||
CFRelease(cfdata);
|
||||
return 0;
|
||||
}
|
||||
CFRelease(cfdata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mouseset(Point xy)
|
||||
{
|
||||
CGPoint pnt;
|
||||
pnt.x = xy.x + winRect.left;
|
||||
pnt.y = xy.y + winRect.top;
|
||||
CGWarpMouseCursorPosition(pnt);
|
||||
}
|
||||
|
||||
void
|
||||
screenload(Rectangle r, int depth, uchar *p, Point pt, int step)
|
||||
{
|
||||
CGRect rbounds;
|
||||
rbounds.size.width = r.max.x - r.min.x;
|
||||
rbounds.size.height = r.max.y - r.min.y;
|
||||
rbounds.origin.x = r.min.x;
|
||||
rbounds.origin.y = r.min.y;
|
||||
|
||||
if(depth != gscreen->depth)
|
||||
panic("screenload: bad ldepth");
|
||||
|
||||
QDBeginCGContext( GetWindowPort(theWindow), &context);
|
||||
|
||||
// The sub-image is relative to our whole screen image.
|
||||
CGImageRef subimg = CGImageCreateWithImageInRect(fullScreenImage, rbounds);
|
||||
|
||||
// Drawing the sub-image is relative to the window.
|
||||
rbounds.origin.y = winRect.bottom - winRect.top - r.min.y - rbounds.size.height;
|
||||
CGContextDrawImage(context, rbounds, subimg);
|
||||
CGContextFlush(context);
|
||||
CGImageRelease(subimg);
|
||||
QDEndCGContext( GetWindowPort(theWindow), &context);
|
||||
|
||||
}
|
||||
|
||||
// PAL: these don't work.
|
||||
// SetCursor and InitCursor are marked as deprecated in 10.4, and I can't for the
|
||||
// life of me find out what has replaced them.
|
||||
void
|
||||
setcursor(void)
|
||||
{
|
||||
Cursor crsr;
|
||||
int i;
|
||||
|
||||
for(i=0; i<16; i++){
|
||||
crsr.data[i] = ((ushort*)cursor.set)[i];
|
||||
crsr.mask[i] = crsr.data[i] | ((ushort*)cursor.clr)[i];
|
||||
}
|
||||
crsr.hotSpot.h = -cursor.offset.x;
|
||||
crsr.hotSpot.v = -cursor.offset.y;
|
||||
SetCursor(&crsr);
|
||||
}
|
||||
|
||||
void
|
||||
cursorarrow(void)
|
||||
{
|
||||
InitCursor();
|
||||
}
|
Reference in New Issue
Block a user