9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: "Michaelian Ennis" <michaelian.ennis@gmail.com>
To: "Fans of the OS Plan 9 from Bell Labs" <9fans@9fans.net>
Subject: Re: [9fans] MacOS X drawterm doesn't toggle
Date: Tue,  9 Dec 2008 14:38:03 -0500	[thread overview]
Message-ID: <bb9aee10812091138i324bfb2cq31decbd5d991c6dd@mail.gmail.com> (raw)
In-Reply-To: <bb9aee10812091137x1082261cg3d9ebbb7c27038f0@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 320 bytes --]

On Tue, Dec 9, 2008 at 2:37 PM, Michaelian Ennis
<michaelian.ennis@gmail.com> wrote:
> Attached is my merge of the two versions.  Yes I am a monkey.  No I
> don't know what I am doing.  Now that said,  can you point me to why
> the application exits when I try to toggle full screen with command-F?
>
>
> Ian
>

[-- Attachment #2: screen.c --]
[-- Type: application/octet-stream, Size: 20454 bytes --]

// 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;
static Ptr fullScreenRestore;
static int amFullScreen;
static int fromMenu;
static WindowRef oldWindow = NULL;

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;

Boolean altPressed = false;
Boolean button2 = false;
Boolean button3 = false;

static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
void winproc(void *a);

static int
isready(void*a)
{
	return readybit;
}

CGContextRef QuartzContext;

/* get the dimensions of the largest screen */

Point
get_largest_screen()
{
	CGDirectDisplayID 	*displaylist;
	CGDisplayCount 		displaycount;
	OSErr 				err;
	int i;
	Point max = Pt(0, 0);
	Point curr;
	err = CGGetActiveDisplayList(0, NULL, &displaycount);
	if(err != noErr)
		sysfatal("can not enumerate active displays");

	displaylist = (CGDirectDisplayID *)malloc(displaycount * sizeof(CGDirectDisplayID));
	if(displaylist == NULL)
		sysfatal("can not allocate memory for display list");

	err = CGGetActiveDisplayList(displaycount, displaylist, &displaycount);
	if(err != noErr)
		sysfatal("can not obtain active display list");

	for(i = 0; i < displaycount; i++) {
		curr.x = CGDisplayPixelsWide(displaylist[i]);
		curr.y = CGDisplayPixelsHigh(displaylist[i]);

		if(max.x < curr.x)
			max.x = curr.x;
		if(max.y < curr.y)
			max.y = curr.y;
	}

	free(displaylist);

	return max;

}


void 
screeninit(void)
{
	Point max;	/* the largest screen, if we have multiple */
	int fmt;

	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;
	max = get_largest_screen();
	devRect = CGDisplayBounds(CGMainDisplayID());

	gscreen = allocmemimage(Rect(0, 0, max.x, max.y), fmt);
	dataProviderRef = CGDataProviderCreateWithData(0, gscreen->data->bdata,
						max.x * max.y * 4, 0);
	fullScreenImage = CGImageCreate(max.x, max.y, 8, 32, max.x * 4,
				CGColorSpaceCreateDeviceRGB(),
				kCGImageAlphaNoneSkipLast,
				dataProviderRef, 0, 0, kCGRenderingIntentDefault);

	kproc("osxscreen", winproc, 0);
	ksleep(&rend, isready, 0);
}


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);
 	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 quit_events[] = {
		{ kEventClassWindow, kEventWindowClosed },
		{ kEventClassWindow, kEventWindowBoundsChanged },
		{ kEventClassCommand, kEventCommandProcess }
	};
	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 (ApplicationQuitEventHandler),
								GetEventTypeCount(quit_events),
								quit_events,
								NULL,
								NULL);

 	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 0x7F;
		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 '\n';
		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 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} };
		drawqlock();
 		flushmemscreen(rect);
 		drawqunlock();
	}
}


static void
full_screen()
{
	GDHandle device;
	if (!amFullScreen) {
		oldWindow = theWindow;
		HideWindow(theWindow);
		GetWindowGreatestAreaDevice(theWindow, kWindowTitleBarRgn, &device, NULL);
		BeginFullScreen(&fullScreenRestore, device, 0, 0, &theWindow, 0, 0);
		amFullScreen = 1;
		window_resized();
		Rectangle rect =  { { 0, 0 },
 							{ bounds.size.width,
 							  bounds.size.height} };
		drawqlock();
 		flushmemscreen(rect);
 		drawqunlock();
	} else leave_full_screen();
	
}

// catch quit events to handle quits from menu, Cmd+Q, applescript, and task switcher
static OSStatus 
ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
{
	fprintf(stderr,"ApplicationQuitEventHandler called");
	exit(0);
//	QuitApplicationEventLoop();
	return noErr;
}
 
static OSStatus 
MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
{
	OSStatus result = noErr;
	result = CallNextEventHandler(nextHandler, event);
	UInt32 class = GetEventClass (event);
	UInt32 kind = GetEventKind (event);
	static uint32_t mousebuttons = 0; // bitmask of buttons currently down
	static uint32_t mouseX = 0; 
	static uint32_t mouseY = 0; 

	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:
			switch(macKeyModifiers & (optionKey | cmdKey)) {
			case (optionKey | cmdKey):
				/* due to chording we need to handle the case when both
				 * modifier keys are pressed at the same time. 
				 * currently it's only 2-3 snarf and the 3-2 noop
				 */
				altPressed = true;
				if(mousebuttons & 1 || mousebuttons & 2 || mousebuttons & 4) {
					mousebuttons |= 2;	/* set button 2 */
					mousebuttons |= 4;	/* set button 3 */
					button2 = true;
					button3 = true;
					sendbuttons(mousebuttons, mouseX, mouseY);
				} 
				break;
			case optionKey:
				altPressed = true;
				if(mousebuttons & 1 || mousebuttons & 4) {
					mousebuttons |= 2;	/* set button 2 */
					button2 = true;
					sendbuttons(mousebuttons, mouseX, mouseY);
				} 
				break;
			case cmdKey:
				if(mousebuttons & 1 || mousebuttons & 2) {
					mousebuttons |= 4;	/* set button 3 */
					button3 = true;
					sendbuttons(mousebuttons, mouseX, mouseY);
				}
				break;
			case 0:
			default:
				if(button2 || button3) {
					if(button2) {
						mousebuttons &= ~2;	/* clear button 2 */
						button2 = false;
						altPressed = false;
					} 
					if(button3) {
						mousebuttons &= ~4;	/* clear button 3 */
						button3 = false;
					}
					sendbuttons(mousebuttons, mouseX, mouseY);
				}
				if(altPressed) {
					kbdputc(kbdq, Kalt);
					altPressed = false;
				} 
				break;
			}
			break;
		case kEventRawKeyDown:
		case kEventRawKeyRepeat:
			if(macKeyModifiers != cmdKey) {
				UniChar uc;
				int key = convert_key(macKeyCode, macCharCodes);
				GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, NULL, sizeof(uc), NULL, &uc);

				if(key != -1)
					kbdputc(kbdq, key);
				else
					kbdputc(kbdq, uc);
				} 
			else {
				if(macCharCodes == 'f' || macCharCodes == 'F') {
					full_screen();
					} 
				else if(macCharCodes == 'q' || macCharCodes == 'Q') {
						exit(0);
					} 
				}
				break;
		}
	}
	else if(class == kEventClassMouse) {
		_Point mousePos;

		GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
							0, sizeof mousePos, 0, &mousePos);
		
		switch (kind) {
			case kEventMouseWheelMoved:
			{
			    int32_t wheeldelta;
				GetEventParameter(event,kEventParamMouseWheelDelta,typeSInt32,
									0,sizeof(wheeldelta), 0, &wheeldelta);
				mouseX = mousePos.h - winRect.left;
				mouseY = mousePos.v - winRect.top;
				sendbuttons(wheeldelta>0 ? 8 : 16, mouseX, mouseY);
				break;
			}
			case kEventMouseUp:
			case kEventMouseDown:
			{
				uint32_t buttons;
				uint32_t modifiers;
				GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 
									0, sizeof(modifiers), 0, &modifiers);
				GetEventParameter(event, kEventParamMouseChord, typeUInt32, 
									0, sizeof buttons, 0, &buttons);
				/* simulate other buttons via alt/apple key. like x11 */
				if(modifiers & optionKey) {
					mousebuttons = ((buttons & 1) ? 2 : 0);
					altPressed = false;
				} else if(modifiers & cmdKey)
					mousebuttons = ((buttons & 1) ? 4 : 0);
				else
					mousebuttons = (buttons & 1);

				mousebuttons |= ((buttons & 2)<<1);
				mousebuttons |= ((buttons & 4)>>1);

			} /* Fallthrough */
			case kEventMouseMoved:
			case kEventMouseDragged:
				mouseX = mousePos.h - winRect.left;
				mouseY = mousePos.v - winRect.top;
				sendbuttons(mousebuttons, mouseX, mouseY);
				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:
				if(amFullScreen)
					leave_full_screen();
				else 
					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:
				// send a quit carbon event instead of directly calling cleanexit 
				// so that all quits are done in ApplicationQuitEventHandler
				{
				EventRef quitEvent;
				CreateEvent(NULL,
							kEventClassApplication,
							kEventAppQuit,
							0,
							kEventAttributeNone,
							&quitEvent);
				EventTargetRef target;
				target = GetApplicationEventTarget();
				SendEventToEventTarget(quitEvent, target);
				}
 				break;

			//resize window
			case kEventWindowBoundsChanged:
				window_resized();
				Rectangle rect =  { { 0, 0 },
 									{ bounds.size.width,
 									  bounds.size.height} };
				drawqlock();
 				flushmemscreen(rect);
 				drawqunlock();
				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", length/sizeof(Rune), 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){
		fprintf(stderr, "apple pasteboard clear failed\n");
		return 0;
	}
	flags = PasteboardSynchronize(appleclip);
	if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
		fprintf(stderr, "apple pasteboard cannot assert ownership\n");
		return 0;
	}
	cfdata = CFDataCreate(kCFAllocatorDefault, 
		(uchar*)rsnarf, runestrlen(rsnarf)*2);
	if(cfdata == nil){
		fprintf(stderr, "apple pasteboard cfdatacreate failed\n");
		return 0;
	}
	if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1,
		CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
		fprintf(stderr, "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();
}

  reply	other threads:[~2008-12-09 19:38 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-18  3:47 Michaelian Ennis
2008-10-18  4:15 ` andrey mirtchovski
2008-10-18  8:48   ` Steve Simon
2008-10-18 16:29     ` andrey mirtchovski
2008-12-09 18:48   ` Michaelian Ennis
2008-12-09 19:12     ` andrey mirtchovski
2008-12-09 19:28       ` Michaelian Ennis
2008-12-09 19:35         ` andrey mirtchovski
2008-12-09 19:37         ` Michaelian Ennis
2008-12-09 19:38           ` Michaelian Ennis [this message]
2008-12-09 19:49             ` Uriel
2008-12-09 20:06               ` Rodolfo kix Garcia
2008-12-09 20:39               ` erik quanstrom
2008-12-09 22:03                 ` matt
2008-12-11  4:40                   ` Adrian Tritschler
2008-12-11  5:22                     ` Russ Cox
2008-12-11  5:39                       ` Roman Zhukov
2008-12-11  9:30                         ` Fernan Bolando

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bb9aee10812091138i324bfb2cq31decbd5d991c6dd@mail.gmail.com \
    --to=michaelian.ennis@gmail.com \
    --cc=9fans@9fans.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).