21
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
Todo : x miniaturize window
28
- save window position
29
- handle keyboard event
34
x simple graphical prompt to demo
35
- better graphical prompt
25
38
#import <Cocoa/Cocoa.h>
27
#include "qemu-common.h"
35
#define COCOA_DEBUG(...) { (void) fprintf (stdout, __VA_ARGS__); }
37
#define COCOA_DEBUG(...) ((void) 0)
40
#define cgrect(nsrect) (*(CGRect *)&(nsrect))
41
#define COCOA_MOUSE_EVENT \
42
if (isTabletEnabled) { \
43
kbd_mouse_event((int)(p.x * 0x7FFF / (screen.width - 1)), (int)((screen.height - p.y) * 0x7FFF / (screen.height - 1)), 0, buttons); \
44
} else if (isMouseGrabed) { \
45
kbd_mouse_event((int)[event deltaX], (int)[event deltaY], 0, buttons); \
47
[NSApp sendEvent:event]; \
57
int qemu_main(int argc, char **argv); // main defined in qemu/vl.c
58
NSWindow *normalWindow;
60
static void *screenBuffer;
42
NSWindow *window = NULL;
43
NSQuickDrawView *qd_view = NULL;
48
DisplayState current_ds;
51
int modifiers_state[256];
53
/* main defined in qemu/vl.c */
54
int qemu_main(int argc, char **argv);
56
/* To deal with miniaturization */
57
@interface QemuWindow : NSWindow
63
------------------------------------------------------
65
------------------------------------------------------
69
------------------------------------------------------
71
------------------------------------------------------
73
static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
75
//printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
77
/* Use QDFlushPortBuffer() to flush content to display */
78
RgnHandle dirty = NewRgn ();
79
RgnHandle temp = NewRgn ();
83
/* Build the region of dirty rectangles */
84
MacSetRectRgn (temp, x, y,
86
MacUnionRgn (dirty, temp, dirty);
88
/* Flush the dirty region */
89
QDFlushPortBuffer ( [ qd_view qdPort ], dirty );
95
------------------------------------------------------
97
------------------------------------------------------
99
static void cocoa_resize(DisplayState *ds, int w, int h)
101
const int device_bpp = 32;
102
static void *screen_pixels;
103
static int screen_pitch;
106
//printf("resizing to %d %d\n", w, h);
108
contentRect = NSMakeRect (0, 0, w, h);
114
window = [ [ QemuWindow alloc ] initWithContentRect:contentRect
115
styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask
116
backing:NSBackingStoreBuffered defer:NO];
119
fprintf(stderr, "(cocoa) can't create window\n");
126
qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
130
fprintf(stderr, "(cocoa) can't create qd_view\n");
134
[ window setAcceptsMouseMovedEvents:YES ];
135
[ window setTitle:@"Qemu" ];
136
[ window setReleasedWhenClosed:NO ];
138
/* Set screen to black */
139
[ window setBackgroundColor: [NSColor blackColor] ];
141
/* set window position */
144
[ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
145
[ [ window contentView ] addSubview:qd_view ];
147
[ window makeKeyAndOrderFront:nil ];
149
/* Careful here, the window seems to have to be onscreen to do that */
150
LockPortBits ( [ qd_view qdPort ] );
151
screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) );
152
screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) );
153
UnlockPortBits ( [ qd_view qdPort ] );
155
int vOffset = [ window frame ].size.height -
156
[ qd_view frame ].size.height - [ qd_view frame ].origin.y;
158
int hOffset = [ qd_view frame ].origin.x;
160
screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8);
162
ds->data = screen_pixels;
163
ds->linesize = screen_pitch;
164
ds->depth = device_bpp;
172
------------------------------------------------------
174
------------------------------------------------------
68
179
// SdlI macI macH SdlH 104xtH 104xtC sdl
239
350
return keymap[keycode];
245
354
------------------------------------------------------
247
356
------------------------------------------------------
249
@interface QemuCocoaView : NSView
252
NSWindow *fullScreenWindow;
253
float cx,cy,cw,ch,cdx,cdy;
254
CGDataProviderRef dataProviderRef;
255
int modifiers_state[256];
258
BOOL isAbsoluteEnabled;
259
BOOL isTabletEnabled;
261
- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds;
263
- (void) ungrabMouse;
264
- (void) toggleFullScreen:(id)sender;
265
- (void) handleEvent:(NSEvent *)event;
266
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
267
- (BOOL) isMouseGrabed;
268
- (BOOL) isAbsoluteEnabled;
271
- (QEMUScreen) gscreen;
274
@implementation QemuCocoaView
275
- (id)initWithFrame:(NSRect)frameRect
277
COCOA_DEBUG("QemuCocoaView: initWithFrame\n");
279
self = [super initWithFrame:frameRect];
282
screen.bitsPerComponent = 8;
283
screen.bitsPerPixel = 32;
284
screen.width = frameRect.size.width;
285
screen.height = frameRect.size.height;
293
COCOA_DEBUG("QemuCocoaView: dealloc\n");
299
CGDataProviderRelease(dataProviderRef);
304
- (void) drawRect:(NSRect) rect
306
COCOA_DEBUG("QemuCocoaView: drawRect\n");
308
if ((int)screenBuffer == -1)
311
// get CoreGraphic context
312
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] graphicsPort];
313
CGContextSetInterpolationQuality (viewContextRef, kCGInterpolationNone);
314
CGContextSetShouldAntialias (viewContextRef, NO);
316
// draw screen bitmap directly to Core Graphics context
317
if (dataProviderRef) {
318
CGImageRef imageRef = CGImageCreate(
319
screen.width, //width
320
screen.height, //height
321
screen.bitsPerComponent, //bitsPerComponent
322
screen.bitsPerPixel, //bitsPerPixel
323
(screen.width * 4), //bytesPerRow
324
#if __LITTLE_ENDIAN__
325
CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), //colorspace for OS X >= 10.4
326
kCGImageAlphaNoneSkipLast,
328
CGColorSpaceCreateDeviceRGB(), //colorspace for OS X < 10.4 (actually ppc)
329
kCGImageAlphaNoneSkipFirst, //bitmapInfo
331
dataProviderRef, //provider
334
kCGRenderingIntentDefault //intent
336
// test if host support "CGImageCreateWithImageInRect" at compiletime
337
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
338
if (CGImageCreateWithImageInRect == NULL) { // test if "CGImageCreateWithImageInRect" is supported on host at runtime
340
// compatibility drawing code (draws everything) (OS X < 10.4)
341
CGContextDrawImage (viewContextRef, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), imageRef);
342
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
344
// selective drawing code (draws only dirty rectangles) (OS X >= 10.4)
345
const NSRect *rectList;
348
CGImageRef clipImageRef;
351
[self getRectsBeingDrawn:&rectList count:&rectCount];
352
for (i = 0; i < rectCount; i++) {
353
clipRect.origin.x = rectList[i].origin.x / cdx;
354
clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height) / cdy;
355
clipRect.size.width = rectList[i].size.width / cdx;
356
clipRect.size.height = rectList[i].size.height / cdy;
357
clipImageRef = CGImageCreateWithImageInRect(
361
CGContextDrawImage (viewContextRef, cgrect(rectList[i]), clipImageRef);
362
CGImageRelease (clipImageRef);
366
CGImageRelease (imageRef);
370
- (void) setContentDimensions
372
COCOA_DEBUG("QemuCocoaView: setContentDimensions\n");
375
cdx = [[NSScreen mainScreen] frame].size.width / (float)screen.width;
376
cdy = [[NSScreen mainScreen] frame].size.height / (float)screen.height;
377
cw = screen.width * cdx;
378
ch = screen.height * cdy;
379
cx = ([[NSScreen mainScreen] frame].size.width - cw) / 2.0;
380
cy = ([[NSScreen mainScreen] frame].size.height - ch) / 2.0;
391
- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds
393
COCOA_DEBUG("QemuCocoaView: resizeContent\n");
395
// update screenBuffer
397
CGDataProviderRelease(dataProviderRef);
400
screenBuffer = malloc( w * 4 * h );
402
ds->data = screenBuffer;
403
ds->linesize = (w * 4);
407
#ifdef __LITTLE_ENDIAN__
413
dataProviderRef = CGDataProviderCreateWithData(NULL, screenBuffer, w * 4 * h, NULL);
417
[[fullScreenWindow contentView] setFrame:[[NSScreen mainScreen] frame]];
418
[normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:NO animate:NO];
421
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
422
[normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:YES animate:YES];
426
[self setContentDimensions];
427
[self setFrame:NSMakeRect(cx, cy, cw, ch)];
430
- (void) toggleFullScreen:(id)sender
432
COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n");
434
if (isFullscreen) { // switch from fullscreen to desktop
435
isFullscreen = FALSE;
437
[self setContentDimensions];
438
// test if host support "enterFullScreenMode:withOptions" at compiletime
439
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
440
if ([NSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)]) { // test if "exitFullScreenModeWithOptions" is supported on host at runtime
441
[self exitFullScreenModeWithOptions:nil];
444
[fullScreenWindow close];
445
[normalWindow setContentView: self];
446
[normalWindow makeKeyAndOrderFront: self];
447
[NSMenu setMenuBarVisible:YES];
448
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
451
} else { // switch from desktop to fullscreen
454
[self setContentDimensions];
455
// test if host support "enterFullScreenMode:withOptions" at compiletime
456
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
457
if ([NSView respondsToSelector:@selector(enterFullScreenMode:withOptions:)]) { // test if "enterFullScreenMode:withOptions" is supported on host at runtime
458
[self enterFullScreenMode:[NSScreen mainScreen] withOptions:[NSDictionary dictionaryWithObjectsAndKeys:
459
[NSNumber numberWithBool:NO], NSFullScreenModeAllScreens,
460
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kCGDisplayModeIsStretched, nil], NSFullScreenModeSetting,
464
[NSMenu setMenuBarVisible:NO];
465
fullScreenWindow = [[NSWindow alloc] initWithContentRect:[[NSScreen mainScreen] frame]
466
styleMask:NSBorderlessWindowMask
467
backing:NSBackingStoreBuffered
469
[fullScreenWindow setHasShadow:NO];
470
[fullScreenWindow setContentView:self];
471
[fullScreenWindow makeKeyAndOrderFront:self];
472
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
478
- (void) handleEvent:(NSEvent *)event
480
COCOA_DEBUG("QemuCocoaView: handleEvent\n");
484
NSPoint p = [event locationInWindow];
486
switch ([event type]) {
488
keycode = cocoa_keycode_to_qemu([event keyCode]);
490
if (keycode == 58 || keycode == 69) { // emulate caps lock and num lock keydown and keyup
491
kbd_put_keycode(keycode);
492
kbd_put_keycode(keycode | 0x80);
493
} else if (is_graphic_console()) {
495
kbd_put_keycode(0xe0);
496
if (modifiers_state[keycode] == 0) { // keydown
497
kbd_put_keycode(keycode & 0x7f);
498
modifiers_state[keycode] = 1;
500
kbd_put_keycode(keycode | 0x80);
501
modifiers_state[keycode] = 0;
506
// release Mouse grab when pressing ctrl+alt
507
if (!isFullscreen && ([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
513
// forward command Key Combos
514
if ([event modifierFlags] & NSCommandKeyMask) {
515
[NSApp sendEvent:event];
520
keycode = cocoa_keycode_to_qemu([event keyCode]);
522
// handle control + alt Key Combos (ctrl+alt is reserved for QEMU)
523
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
526
// enable graphic console
527
case 0x02 ... 0x0a: // '1' to '9' keys
528
console_select(keycode - 0x02);
532
// handle keys for graphic console
533
} else if (is_graphic_console()) {
534
if (keycode & 0x80) //check bit for e0 in front
535
kbd_put_keycode(0xe0);
536
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
538
// handlekeys for Monitor
541
switch([event keyCode]) {
543
keysym = QEMU_KEY_HOME;
546
keysym = QEMU_KEY_DELETE;
549
keysym = QEMU_KEY_END;
552
keysym = QEMU_KEY_LEFT;
555
keysym = QEMU_KEY_RIGHT;
558
keysym = QEMU_KEY_DOWN;
561
keysym = QEMU_KEY_UP;
565
NSString *ks = [event characters];
567
keysym = [ks characterAtIndex:0];
571
kbd_put_keysym(keysym);
575
keycode = cocoa_keycode_to_qemu([event keyCode]);
576
if (is_graphic_console()) {
578
kbd_put_keycode(0xe0);
579
kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
583
if (isAbsoluteEnabled) {
584
if (p.x < 0 || p.x > screen.width || p.y < 0 || p.y > screen.height || ![[self window] isKeyWindow]) {
585
if (isTabletEnabled) { // if we leave the window, deactivate the tablet
587
isTabletEnabled = FALSE;
590
if (!isTabletEnabled) { // if we enter the window, activate the tablet
358
static void cocoa_refresh(DisplayState *ds)
360
//printf("cocoa_refresh \n");
363
NSAutoreleasePool *pool;
365
pool = [ [ NSAutoreleasePool alloc ] init ];
366
distantPast = [ NSDate distantPast ];
371
event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
372
inMode: NSDefaultRunLoopMode dequeue:YES ];
374
switch ([event type]) {
377
int keycode = cocoa_keycode_to_qemu([event keyCode]);
381
if (keycode == 58 || keycode == 69) {
382
/* emulate caps lock and num lock keydown and keyup */
383
kbd_put_keycode(keycode);
384
kbd_put_keycode(keycode | 0x80);
385
} else if (is_graphic_console()) {
387
kbd_put_keycode(0xe0);
388
if (modifiers_state[keycode] == 0) {
390
kbd_put_keycode(keycode & 0x7f);
391
modifiers_state[keycode] = 1;
394
kbd_put_keycode(keycode | 0x80);
395
modifiers_state[keycode] = 0;
400
/* release Mouse grab when pressing ctrl+alt */
401
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask))
403
[window setTitle: @"QEMU"];
405
CGAssociateMouseAndMouseCursorPosition ( TRUE );
413
int keycode = cocoa_keycode_to_qemu([event keyCode]);
415
/* handle command Key Combos */
416
if ([event modifierFlags] & NSCommandKeyMask) {
417
switch ([event keyCode]) {
420
/* switch to windowed View */
426
/* handle control + alt Key Combos */
427
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
430
case 0x02 ... 0x0a: /* '1' to '9' keys */
431
console_select(keycode - 0x02);
435
/* handle standard key events */
436
if (is_graphic_console()) {
437
if (keycode & 0x80) //check bit for e0 in front
438
kbd_put_keycode(0xe0);
439
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
440
/* handle monitor key events */
444
switch([event keyCode]) {
446
keysym = QEMU_KEY_HOME;
449
keysym = QEMU_KEY_DELETE;
452
keysym = QEMU_KEY_END;
455
keysym = QEMU_KEY_LEFT;
458
keysym = QEMU_KEY_RIGHT;
461
keysym = QEMU_KEY_DOWN;
464
keysym = QEMU_KEY_UP;
468
NSString *ks = [event characters];
471
keysym = [ks characterAtIndex:0];
475
kbd_put_keysym(keysym);
483
int keycode = cocoa_keycode_to_qemu([event keyCode]);
484
if (is_graphic_console()) {
486
kbd_put_keycode(0xe0);
487
kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
494
int dx = [event deltaX];
495
int dy = [event deltaY];
496
int dz = [event deltaZ];
498
kbd_mouse_event(dx, dy, dz, buttons);
502
case NSLeftMouseDown:
506
/* leftclick+command simulates rightclick */
507
if ([event modifierFlags] & NSCommandKeyMask) {
508
buttons |= MOUSE_EVENT_RBUTTON;
510
buttons |= MOUSE_EVENT_LBUTTON;
512
kbd_mouse_event(0, 0, 0, buttons);
514
[NSApp sendEvent: event];
518
case NSLeftMouseDragged:
520
int dx = [event deltaX];
521
int dy = [event deltaY];
522
int dz = [event deltaZ];
524
if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) { //leftclick+command simulates rightclick
525
buttons |= MOUSE_EVENT_RBUTTON;
527
buttons |= MOUSE_EVENT_LBUTTON;
529
kbd_mouse_event(dx, dy, dz, buttons);
535
kbd_mouse_event(0, 0, 0, 0);
537
[window setTitle: @"QEMU (Press ctrl + alt to release Mouse)"];
592
isTabletEnabled = TRUE;
598
case NSLeftMouseDown:
599
if ([event modifierFlags] & NSCommandKeyMask) {
600
buttons |= MOUSE_EVENT_RBUTTON;
602
buttons |= MOUSE_EVENT_LBUTTON;
606
case NSRightMouseDown:
607
buttons |= MOUSE_EVENT_RBUTTON;
610
case NSOtherMouseDown:
611
buttons |= MOUSE_EVENT_MBUTTON;
614
case NSLeftMouseDragged:
615
if ([event modifierFlags] & NSCommandKeyMask) {
616
buttons |= MOUSE_EVENT_RBUTTON;
618
buttons |= MOUSE_EVENT_LBUTTON;
622
case NSRightMouseDragged:
623
buttons |= MOUSE_EVENT_RBUTTON;
626
case NSOtherMouseDragged:
627
buttons |= MOUSE_EVENT_MBUTTON;
631
if (isTabletEnabled) {
633
} else if (!isMouseGrabed) {
634
if (p.x > -1 && p.x < screen.width && p.y > -1 && p.y < screen.height) {
637
[NSApp sendEvent:event];
650
if (isTabletEnabled || isMouseGrabed) {
651
kbd_mouse_event(0, 0, -[event deltaY], 0);
653
[NSApp sendEvent:event];
657
[NSApp sendEvent:event];
663
COCOA_DEBUG("QemuCocoaView: grabMouse\n");
667
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s - (Press ctrl + alt to release Mouse)", qemu_name]];
669
[normalWindow setTitle:@"QEMU - (Press ctrl + alt to release Mouse)"];
672
CGAssociateMouseAndMouseCursorPosition(FALSE);
673
isMouseGrabed = TRUE; // while isMouseGrabed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
678
COCOA_DEBUG("QemuCocoaView: ungrabMouse\n");
682
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
684
[normalWindow setTitle:@"QEMU"];
687
CGAssociateMouseAndMouseCursorPosition(TRUE);
688
isMouseGrabed = FALSE;
691
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {isAbsoluteEnabled = tIsAbsoluteEnabled;}
692
- (BOOL) isMouseGrabed {return isMouseGrabed;}
693
- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
694
- (float) cdx {return cdx;}
695
- (float) cdy {return cdy;}
696
- (QEMUScreen) gscreen {return screen;}
539
CGAssociateMouseAndMouseCursorPosition ( FALSE );
541
//[NSApp sendEvent: event];
545
case NSRightMouseDown:
549
buttons |= MOUSE_EVENT_RBUTTON;
550
kbd_mouse_event(0, 0, 0, buttons);
552
[NSApp sendEvent: event];
556
case NSRightMouseDragged:
558
int dx = [event deltaX];
559
int dy = [event deltaY];
560
int dz = [event deltaZ];
562
buttons |= MOUSE_EVENT_RBUTTON;
563
kbd_mouse_event(dx, dy, dz, buttons);
569
kbd_mouse_event(0, 0, 0, 0);
571
[NSApp sendEvent: event];
575
case NSOtherMouseDragged:
577
int dx = [event deltaX];
578
int dy = [event deltaY];
579
int dz = [event deltaZ];
581
buttons |= MOUSE_EVENT_MBUTTON;
582
kbd_mouse_event(dx, dy, dz, buttons);
586
case NSOtherMouseDown:
589
buttons |= MOUSE_EVENT_MBUTTON;
590
kbd_mouse_event(0, 0, 0, buttons);
592
[NSApp sendEvent:event];
598
kbd_mouse_event(0, 0, 0, 0);
600
[NSApp sendEvent: event];
606
int dz = [event deltaY];
607
kbd_mouse_event(0, 0, -dz, 0);
611
default: [NSApp sendEvent:event];
614
} while(event != nil);
618
------------------------------------------------------
620
------------------------------------------------------
623
static void cocoa_cleanup(void)
629
------------------------------------------------------
631
------------------------------------------------------
634
void cocoa_display_init(DisplayState *ds, int full_screen)
636
ds->dpy_update = cocoa_update;
637
ds->dpy_resize = cocoa_resize;
638
ds->dpy_refresh = cocoa_refresh;
640
cocoa_resize(ds, 640, 400);
642
atexit(cocoa_cleanup);
646
------------------------------------------------------
648
------------------------------------------------------
653
------------------------------------------------------
655
Some trick from SDL to use miniwindow
656
------------------------------------------------------
658
static void QZ_SetPortAlphaOpaque ()
660
/* Assume 32 bit if( bpp == 32 )*/
663
uint32_t *pixels = (uint32_t*) current_ds.data;
664
uint32_t rowPixels = current_ds.linesize / 4;
667
for (i = 0; i < current_ds.height; i++)
668
for (j = 0; j < current_ds.width; j++) {
670
pixels[ (i * rowPixels) + j ] |= 0xFF000000;
675
@implementation QemuWindow
676
- (void)miniaturize:(id)sender
679
/* make the alpha channel opaque so anim won't have holes in it */
680
QZ_SetPortAlphaOpaque ();
682
[ super miniaturize:sender ];
688
This method fires just before the window deminaturizes from the Dock.
690
We'll save the current visible surface, let the window manager redraw any
691
UI elements, and restore the SDL surface. This way, no expose event
692
is required, and the deminiaturize works perfectly.
695
/* make sure pixels are fully opaque */
696
QZ_SetPortAlphaOpaque ();
698
/* save current visible SDL surface */
699
[ self cacheImageInRect:[ qd_view frame ] ];
701
/* let the window manager redraw controls, border, etc */
704
/* restore visible SDL surface */
705
[ self restoreCachedImage ];
702
712
------------------------------------------------------
703
QemuCocoaAppController
713
QemuCocoaGUIController
714
NSApp's delegate - indeed main object
704
715
------------------------------------------------------
706
@interface QemuCocoaAppController : NSObject
718
@interface QemuCocoaGUIController : NSObject
721
- (void)applicationDidFinishLaunching: (NSNotification *) note;
722
- (void)applicationWillTerminate:(NSNotification *)aNotification;
724
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
709
726
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
710
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
711
- (void)toggleFullScreen:(id)sender;
712
- (void)showQEMUDoc:(id)sender;
713
- (void)showQEMUTec:(id)sender;
716
@implementation QemuCocoaAppController
719
COCOA_DEBUG("QemuCocoaAppController: init\n");
724
// create a view and add it to the window
725
cocoaView = [[QemuCocoaView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 640.0, 480.0)];
727
fprintf(stderr, "(cocoa) can't create a view\n");
732
normalWindow = [[NSWindow alloc] initWithContentRect:[cocoaView frame]
733
styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask
734
backing:NSBackingStoreBuffered defer:NO];
736
fprintf(stderr, "(cocoa) can't create window\n");
739
[normalWindow setAcceptsMouseMovedEvents:YES];
740
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU"]];
741
[normalWindow setContentView:cocoaView];
742
[normalWindow makeKeyAndOrderFront:self];
750
COCOA_DEBUG("QemuCocoaAppController: dealloc\n");
729
@implementation QemuCocoaGUIController
730
/* Called when the internal event loop has just started running */
757
731
- (void)applicationDidFinishLaunching: (NSNotification *) note
759
COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n");
761
// Display an open dialog box if no argument were passed or
762
// if qemu was launched from the finder ( the Finder passes "-psn" )
763
if( gArgc <= 1 || strncmp ((char *)gArgv[1], "-psn", 4) == 0) {
734
/* Display an open dialog box if no argument were passed or
735
if qemu was launched from the finder ( the Finder passes "-psn" ) */
737
if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0)
764
739
NSOpenPanel *op = [[NSOpenPanel alloc] init];
741
cocoa_resize(¤t_ds, 640, 400);
765
743
[op setPrompt:@"Boot image"];
766
745
[op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
767
747
[op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
768
modalForWindow:normalWindow modalDelegate:self
748
modalForWindow:window modalDelegate:self
769
749
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
771
// or Launch Qemu, with the global args
772
[self startEmulationWithArgc:gArgc argv:(char **)gArgv];
753
/* or Launch Qemu, with the global args */
754
[self startEmulationWithArgc:gArgc argv:gArgv];
776
758
- (void)applicationWillTerminate:(NSNotification *)aNotification
778
COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n");
760
printf("Application will terminate\n");
780
761
qemu_system_shutdown_request();
762
/* In order to avoid a crash */
784
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv
786
COCOA_DEBUG("QemuCocoaAppController: startEmulationWithArgc\n");
789
status = qemu_main(argc, argv);
793
766
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
795
COCOA_DEBUG("QemuCocoaAppController: openPanelDidEnd\n");
797
if(returnCode == NSCancelButton) {
768
if(returnCode == NSCancelButton)
799
} else if(returnCode == NSOKButton) {
773
if(returnCode == NSOKButton)
800
775
char *bin = "qemu";
801
char *img = (char*)[ [ sheet filename ] cStringUsingEncoding:NSASCIIStringEncoding];
776
char *img = (char*)[ [ sheet filename ] cString];
803
778
char **argv = (char**)malloc( sizeof(char*)*3 );
805
780
asprintf(&argv[0], "%s", bin);
806
781
asprintf(&argv[1], "-hda");
807
782
asprintf(&argv[2], "%s", img);
809
784
printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
811
786
[self startEmulationWithArgc:3 argv:(char**)argv];
814
- (void)toggleFullScreen:(id)sender
816
COCOA_DEBUG("QemuCocoaAppController: toggleFullScreen\n");
818
[cocoaView toggleFullScreen:sender];
821
- (void)showQEMUDoc:(id)sender
823
COCOA_DEBUG("QemuCocoaAppController: showQEMUDoc\n");
825
[[NSWorkspace sharedWorkspace] openFile:[NSString stringWithFormat:@"%@/../doc/qemu/qemu-doc.html",
826
[[NSBundle mainBundle] resourcePath]] withApplication:@"Help Viewer"];
829
- (void)showQEMUTec:(id)sender
831
COCOA_DEBUG("QemuCocoaAppController: showQEMUTec\n");
833
[[NSWorkspace sharedWorkspace] openFile:[NSString stringWithFormat:@"%@/../doc/qemu/qemu-tech.html",
834
[[NSBundle mainBundle] resourcePath]] withApplication:@"Help Viewer"];
790
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv
794
printf("starting qemu...\n");
795
status = qemu_main (argc, argv);
801
------------------------------------------------------
803
------------------------------------------------------
806
/* Dock Connection */
841
807
typedef struct CPSProcessSerNum
848
814
extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
849
815
extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
851
int main (int argc, const char * argv[]) {
854
gArgv = (char **)argv;
818
static void setApplicationMenu(void)
820
/* warning: this code is very odd */
822
NSMenuItem *menuItem;
827
appleMenu = [[NSMenu alloc] initWithTitle:@""];
830
title = [@"About " stringByAppendingString:appName];
831
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
833
[appleMenu addItem:[NSMenuItem separatorItem]];
835
title = [@"Hide " stringByAppendingString:appName];
836
[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
838
menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
839
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
841
[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
843
[appleMenu addItem:[NSMenuItem separatorItem]];
845
title = [@"Quit " stringByAppendingString:appName];
846
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
849
/* Put menu into the menubar */
850
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
851
[menuItem setSubmenu:appleMenu];
852
[[NSApp mainMenu] addItem:menuItem];
854
/* Tell the application object that this is now the application menu */
855
[NSApp setAppleMenu:appleMenu];
857
/* Finally give up our references to the objects */
862
/* Create a window menu */
863
static void setupWindowMenu(void)
866
NSMenuItem *windowMenuItem;
867
NSMenuItem *menuItem;
869
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
871
/* "Minimize" item */
872
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
873
[windowMenu addItem:menuItem];
876
/* Put menu into the menubar */
877
windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
878
[windowMenuItem setSubmenu:windowMenu];
879
[[NSApp mainMenu] addItem:windowMenuItem];
881
/* Tell the application object that this is now the window menu */
882
[NSApp setWindowsMenu:windowMenu];
884
/* Finally give up our references to the objects */
885
[windowMenu release];
886
[windowMenuItem release];
889
static void CustomApplicationMain(void)
891
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
892
QemuCocoaGUIController *gui_controller;
855
893
CPSProcessSerNum PSN;
857
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
858
895
[NSApplication sharedApplication];
860
897
if (!CPSGetCurrentProcess(&PSN))
861
898
if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
862
899
if (!CPSSetFrontProcess(&PSN))
863
900
[NSApplication sharedApplication];
867
NSMenuItem *menuItem;
902
/* Set up the menubar */
869
903
[NSApp setMainMenu:[[NSMenu alloc] init]];
872
menu = [[NSMenu alloc] initWithTitle:@""];
873
[menu addItemWithTitle:@"About QEMU" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; // About QEMU
874
[menu addItem:[NSMenuItem separatorItem]]; //Separator
875
[menu addItemWithTitle:@"Hide QEMU" action:@selector(hide:) keyEquivalent:@"h"]; //Hide QEMU
876
menuItem = (NSMenuItem *)[menu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; // Hide Others
877
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
878
[menu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; // Show All
879
[menu addItem:[NSMenuItem separatorItem]]; //Separator
880
[menu addItemWithTitle:@"Quit QEMU" action:@selector(terminate:) keyEquivalent:@"q"];
881
menuItem = [[NSMenuItem alloc] initWithTitle:@"Apple" action:nil keyEquivalent:@""];
882
[menuItem setSubmenu:menu];
883
[[NSApp mainMenu] addItem:menuItem];
884
[NSApp performSelector:@selector(setAppleMenu:) withObject:menu]; // Workaround (this method is private since 10.4+)
887
menu = [[NSMenu alloc] initWithTitle:@"View"];
888
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter Fullscreen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"] autorelease]]; // Fullscreen
889
menuItem = [[[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""] autorelease];
890
[menuItem setSubmenu:menu];
891
[[NSApp mainMenu] addItem:menuItem];
894
menu = [[NSMenu alloc] initWithTitle:@"Window"];
895
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"] autorelease]]; // Miniaturize
896
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease];
897
[menuItem setSubmenu:menu];
898
[[NSApp mainMenu] addItem:menuItem];
899
[NSApp setWindowsMenu:menu];
902
menu = [[NSMenu alloc] initWithTitle:@"Help"];
903
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU Documentation" action:@selector(showQEMUDoc:) keyEquivalent:@"?"] autorelease]]; // QEMU Help
904
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU Technology" action:@selector(showQEMUTec:) keyEquivalent:@""] autorelease]]; // QEMU Help
905
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease];
906
[menuItem setSubmenu:menu];
907
[[NSApp mainMenu] addItem:menuItem];
909
// Create an Application controller
910
QemuCocoaAppController *appController = [[QemuCocoaAppController alloc] init];
911
[NSApp setDelegate:appController];
913
// Start the main event loop
904
setApplicationMenu();
907
/* Create SDLMain and make it the app delegate */
908
gui_controller = [[QemuCocoaGUIController alloc] init];
909
[NSApp setDelegate:gui_controller];
911
/* Start the main event loop */
916
[appController release];
914
[gui_controller release];
918
/* Real main of qemu-cocoa */
919
int main(int argc, char **argv)
924
CustomApplicationMain();
925
static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
927
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
930
if ([cocoaView cdx] == 1.0) {
931
rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h);
935
([cocoaView gscreen].height - y - h) * [cocoaView cdy],
937
h * [cocoaView cdy]);
939
[cocoaView displayRect:rect];
942
static void cocoa_resize(DisplayState *ds, int w, int h)
944
COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
946
[cocoaView resizeContentToWidth:w height:h displayState:ds];
949
static void cocoa_refresh(DisplayState *ds)
951
COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
953
if (kbd_mouse_is_absolute()) {
954
if (![cocoaView isAbsoluteEnabled]) {
955
if ([cocoaView isMouseGrabed]) {
956
[cocoaView ungrabMouse];
959
[cocoaView setAbsoluteEnabled:YES];
964
distantPast = [NSDate distantPast];
966
event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
967
inMode: NSDefaultRunLoopMode dequeue:YES];
969
[cocoaView handleEvent:event];
971
} while(event != nil);
975
static void cocoa_cleanup(void)
977
COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n");
981
void cocoa_display_init(DisplayState *ds, int full_screen)
983
COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
985
// register vga outpu callbacks
986
ds->dpy_update = cocoa_update;
987
ds->dpy_resize = cocoa_resize;
988
ds->dpy_refresh = cocoa_refresh;
990
// give window a initial Size
991
cocoa_resize(ds, 640, 400);
993
// register cleanup function
994
atexit(cocoa_cleanup);