Annotation of qemu/cocoa.m, revision 1.1.1.2
1.1 root 1: /*
2: * QEMU Cocoa display driver
3: *
4: * Copyright (c) 2005 Pierre d'Herbemont
5: * many code/inspiration from SDL 1.2 code (LGPL)
6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a copy
8: * of this software and associated documentation files (the "Software"), to deal
9: * in the Software without restriction, including without limitation the rights
10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11: * copies of the Software, and to permit persons to whom the Software is
12: * furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included in
15: * all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23: * THE SOFTWARE.
24: */
25: /*
26: Todo : x miniaturize window
27: x center the window
28: - save window position
29: - handle keyboard event
30: - handle mouse event
31: - non 32 bpp support
32: - full screen
33: - mouse focus
34: x simple graphical prompt to demo
35: - better graphical prompt
36: */
37:
38: #import <Cocoa/Cocoa.h>
39:
40: #include "vl.h"
41:
42: NSWindow *window = NULL;
43: NSQuickDrawView *qd_view = NULL;
44:
45:
46: int gArgc;
47: char **gArgv;
48: DisplayState current_ds;
49:
1.1.1.2 ! root 50: int grab = 0;
! 51: int modifiers_state[256];
! 52:
1.1 root 53: /* main defined in qemu/vl.c */
54: int qemu_main(int argc, char **argv);
55:
56: /* To deal with miniaturization */
57: @interface QemuWindow : NSWindow
58: { }
59: @end
60:
61:
62: /*
63: ------------------------------------------------------
64: Qemu Video Driver
65: ------------------------------------------------------
66: */
67:
68: /*
69: ------------------------------------------------------
70: cocoa_update
71: ------------------------------------------------------
72: */
73: static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
74: {
75: //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
76:
77: /* Use QDFlushPortBuffer() to flush content to display */
78: RgnHandle dirty = NewRgn ();
79: RgnHandle temp = NewRgn ();
80:
81: SetEmptyRgn (dirty);
82:
83: /* Build the region of dirty rectangles */
84: MacSetRectRgn (temp, x, y,
85: x + w, y + h);
86: MacUnionRgn (dirty, temp, dirty);
87:
88: /* Flush the dirty region */
89: QDFlushPortBuffer ( [ qd_view qdPort ], dirty );
90: DisposeRgn (dirty);
91: DisposeRgn (temp);
92: }
93:
94: /*
95: ------------------------------------------------------
96: cocoa_resize
97: ------------------------------------------------------
98: */
99: static void cocoa_resize(DisplayState *ds, int w, int h)
100: {
101: const int device_bpp = 32;
102: static void *screen_pixels;
103: static int screen_pitch;
104: NSRect contentRect;
105:
106: //printf("resizing to %d %d\n", w, h);
107:
108: contentRect = NSMakeRect (0, 0, w, h);
109: if(window)
110: {
111: [window close];
112: [window release];
113: }
114: window = [ [ QemuWindow alloc ] initWithContentRect:contentRect
115: styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask
116: backing:NSBackingStoreBuffered defer:NO];
117: if(!window)
118: {
119: fprintf(stderr, "(cocoa) can't create window\n");
120: exit(1);
121: }
122:
123: if(qd_view)
124: [qd_view release];
125:
126: qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
127:
128: if(!qd_view)
129: {
130: fprintf(stderr, "(cocoa) can't create qd_view\n");
131: exit(1);
132: }
133:
134: [ window setAcceptsMouseMovedEvents:YES ];
135: [ window setTitle:@"Qemu" ];
136: [ window setReleasedWhenClosed:NO ];
137:
138: /* Set screen to black */
139: [ window setBackgroundColor: [NSColor blackColor] ];
140:
141: /* set window position */
142: [ window center ];
143:
144: [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
145: [ [ window contentView ] addSubview:qd_view ];
146: [ qd_view release ];
147: [ window makeKeyAndOrderFront:nil ];
148:
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 ] );
154: {
155: int vOffset = [ window frame ].size.height -
156: [ qd_view frame ].size.height - [ qd_view frame ].origin.y;
157:
158: int hOffset = [ qd_view frame ].origin.x;
159:
160: screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8);
161: }
162: ds->data = screen_pixels;
163: ds->linesize = screen_pitch;
164: ds->depth = device_bpp;
165: ds->width = w;
166: ds->height = h;
167:
168: current_ds = *ds;
169: }
170:
171: /*
172: ------------------------------------------------------
173: keymap conversion
174: ------------------------------------------------------
175: */
176:
1.1.1.2 ! root 177: int keymap[] =
1.1 root 178: {
1.1.1.2 ! root 179: // SdlI macI macH SdlH 104xtH 104xtC sdl
! 180: 30, // 0 0x00 0x1e A QZ_a
! 181: 31, // 1 0x01 0x1f S QZ_s
! 182: 32, // 2 0x02 0x20 D QZ_d
! 183: 33, // 3 0x03 0x21 F QZ_f
! 184: 35, // 4 0x04 0x23 H QZ_h
! 185: 34, // 5 0x05 0x22 G QZ_g
! 186: 44, // 6 0x06 0x2c Z QZ_z
! 187: 45, // 7 0x07 0x2d X QZ_x
! 188: 46, // 8 0x08 0x2e C QZ_c
! 189: 47, // 9 0x09 0x2f V QZ_v
! 190: 0, // 10 0x0A Undefined
! 191: 48, // 11 0x0B 0x30 B QZ_b
! 192: 16, // 12 0x0C 0x10 Q QZ_q
! 193: 17, // 13 0x0D 0x11 W QZ_w
! 194: 18, // 14 0x0E 0x12 E QZ_e
! 195: 19, // 15 0x0F 0x13 R QZ_r
! 196: 21, // 16 0x10 0x15 Y QZ_y
! 197: 20, // 17 0x11 0x14 T QZ_t
! 198: 2, // 18 0x12 0x02 1 QZ_1
! 199: 3, // 19 0x13 0x03 2 QZ_2
! 200: 4, // 20 0x14 0x04 3 QZ_3
! 201: 5, // 21 0x15 0x05 4 QZ_4
! 202: 7, // 22 0x16 0x07 6 QZ_6
! 203: 6, // 23 0x17 0x06 5 QZ_5
! 204: 13, // 24 0x18 0x0d = QZ_EQUALS
! 205: 10, // 25 0x19 0x0a 9 QZ_9
! 206: 8, // 26 0x1A 0x08 7 QZ_7
! 207: 12, // 27 0x1B 0x0c - QZ_MINUS
! 208: 9, // 28 0x1C 0x09 8 QZ_8
! 209: 11, // 29 0x1D 0x0b 0 QZ_0
! 210: 27, // 30 0x1E 0x1b ] QZ_RIGHTBRACKET
! 211: 24, // 31 0x1F 0x18 O QZ_o
! 212: 22, // 32 0x20 0x16 U QZ_u
! 213: 26, // 33 0x21 0x1a [ QZ_LEFTBRACKET
! 214: 23, // 34 0x22 0x17 I QZ_i
! 215: 25, // 35 0x23 0x19 P QZ_p
! 216: 28, // 36 0x24 0x1c ENTER QZ_RETURN
! 217: 38, // 37 0x25 0x26 L QZ_l
! 218: 36, // 38 0x26 0x24 J QZ_j
! 219: 40, // 39 0x27 0x28 ' QZ_QUOTE
! 220: 37, // 40 0x28 0x25 K QZ_k
! 221: 39, // 41 0x29 0x27 ; QZ_SEMICOLON
! 222: 43, // 42 0x2A 0x2b \ QZ_BACKSLASH
! 223: 51, // 43 0x2B 0x33 , QZ_COMMA
! 224: 53, // 44 0x2C 0x35 / QZ_SLASH
! 225: 49, // 45 0x2D 0x31 N QZ_n
! 226: 50, // 46 0x2E 0x32 M QZ_m
! 227: 52, // 47 0x2F 0x34 . QZ_PERIOD
! 228: 15, // 48 0x30 0x0f TAB QZ_TAB
! 229: 57, // 49 0x31 0x39 SPACE QZ_SPACE
! 230: 41, // 50 0x32 0x29 ` QZ_BACKQUOTE
! 231: 14, // 51 0x33 0x0e BKSP QZ_BACKSPACE
! 232: 0, // 52 0x34 Undefined
! 233: 1, // 53 0x35 0x01 ESC QZ_ESCAPE
! 234: 0, // 54 0x36 QZ_RMETA
! 235: 0, // 55 0x37 QZ_LMETA
! 236: 42, // 56 0x38 0x2a L SHFT QZ_LSHIFT
! 237: 58, // 57 0x39 0x3a CAPS QZ_CAPSLOCK
! 238: 56, // 58 0x3A 0x38 L ALT QZ_LALT
! 239: 29, // 59 0x3B 0x1d L CTRL QZ_LCTRL
! 240: 54, // 60 0x3C 0x36 R SHFT QZ_RSHIFT
! 241: 184,// 61 0x3D 0xb8 E0,38 R ALT QZ_RALT
! 242: 157,// 62 0x3E 0x9d E0,1D R CTRL QZ_RCTRL
! 243: 0, // 63 0x3F Undefined
! 244: 0, // 64 0x40 Undefined
! 245: 0, // 65 0x41 Undefined
! 246: 0, // 66 0x42 Undefined
! 247: 55, // 67 0x43 0x37 KP * QZ_KP_MULTIPLY
! 248: 0, // 68 0x44 Undefined
! 249: 78, // 69 0x45 0x4e KP + QZ_KP_PLUS
! 250: 0, // 70 0x46 Undefined
! 251: 69, // 71 0x47 0x45 NUM QZ_NUMLOCK
! 252: 0, // 72 0x48 Undefined
! 253: 0, // 73 0x49 Undefined
! 254: 0, // 74 0x4A Undefined
! 255: 181,// 75 0x4B 0xb5 E0,35 KP / QZ_KP_DIVIDE
! 256: 152,// 76 0x4C 0x9c E0,1C KP EN QZ_KP_ENTER
! 257: 0, // 77 0x4D undefined
! 258: 74, // 78 0x4E 0x4a KP - QZ_KP_MINUS
! 259: 0, // 79 0x4F Undefined
! 260: 0, // 80 0x50 Undefined
! 261: 0, // 81 0x51 QZ_KP_EQUALS
! 262: 82, // 82 0x52 0x52 KP 0 QZ_KP0
! 263: 79, // 83 0x53 0x4f KP 1 QZ_KP1
! 264: 80, // 84 0x54 0x50 KP 2 QZ_KP2
! 265: 81, // 85 0x55 0x51 KP 3 QZ_KP3
! 266: 75, // 86 0x56 0x4b KP 4 QZ_KP4
! 267: 76, // 87 0x57 0x4c KP 5 QZ_KP5
! 268: 77, // 88 0x58 0x4d KP 6 QZ_KP6
! 269: 71, // 89 0x59 0x47 KP 7 QZ_KP7
! 270: 0, // 90 0x5A Undefined
! 271: 72, // 91 0x5B 0x48 KP 8 QZ_KP8
! 272: 73, // 92 0x5C 0x49 KP 9 QZ_KP9
! 273: 0, // 93 0x5D Undefined
! 274: 0, // 94 0x5E Undefined
! 275: 0, // 95 0x5F Undefined
! 276: 63, // 96 0x60 0x3f F5 QZ_F5
! 277: 64, // 97 0x61 0x40 F6 QZ_F6
! 278: 65, // 98 0x62 0x41 F7 QZ_F7
! 279: 61, // 99 0x63 0x3d F3 QZ_F3
! 280: 66, // 100 0x64 0x42 F8 QZ_F8
! 281: 67, // 101 0x65 0x43 F9 QZ_F9
! 282: 0, // 102 0x66 Undefined
! 283: 87, // 103 0x67 0x57 F11 QZ_F11
! 284: 0, // 104 0x68 Undefined
! 285: 183,// 105 0x69 0xb7 QZ_PRINT
! 286: 0, // 106 0x6A Undefined
! 287: 70, // 107 0x6B 0x46 SCROLL QZ_SCROLLOCK
! 288: 0, // 108 0x6C Undefined
! 289: 68, // 109 0x6D 0x44 F10 QZ_F10
! 290: 0, // 110 0x6E Undefined
! 291: 88, // 111 0x6F 0x58 F12 QZ_F12
! 292: 0, // 112 0x70 Undefined
! 293: 110,// 113 0x71 0x0 QZ_PAUSE
! 294: 210,// 114 0x72 0xd2 E0,52 INSERT QZ_INSERT
! 295: 199,// 115 0x73 0xc7 E0,47 HOME QZ_HOME
! 296: 201,// 116 0x74 0xc9 E0,49 PG UP QZ_PAGEUP
! 297: 211,// 117 0x75 0xd3 E0,53 DELETE QZ_DELETE
! 298: 62, // 118 0x76 0x3e F4 QZ_F4
! 299: 207,// 119 0x77 0xcf E0,4f END QZ_END
! 300: 60, // 120 0x78 0x3c F2 QZ_F2
! 301: 209,// 121 0x79 0xd1 E0,51 PG DN QZ_PAGEDOWN
! 302: 59, // 122 0x7A 0x3b F1 QZ_F1
! 303: 203,// 123 0x7B 0xcb e0,4B L ARROW QZ_LEFT
! 304: 205,// 124 0x7C 0xcd e0,4D R ARROW QZ_RIGHT
! 305: 208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN
! 306: 200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP
! 307: /* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */
! 308:
! 309: /* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
! 310: /*
! 311: 219 // 0xdb e0,5b L GUI
! 312: 220 // 0xdc e0,5c R GUI
! 313: 221 // 0xdd e0,5d APPS
! 314: // E0,2A,E0,37 PRNT SCRN
! 315: // E1,1D,45,E1,9D,C5 PAUSE
! 316: 83 // 0x53 0x53 KP .
! 317: // ACPI Scan Codes
! 318: 222 // 0xde E0, 5E Power
! 319: 223 // 0xdf E0, 5F Sleep
! 320: 227 // 0xe3 E0, 63 Wake
! 321: // Windows Multimedia Scan Codes
! 322: 153 // 0x99 E0, 19 Next Track
! 323: 144 // 0x90 E0, 10 Previous Track
! 324: 164 // 0xa4 E0, 24 Stop
! 325: 162 // 0xa2 E0, 22 Play/Pause
! 326: 160 // 0xa0 E0, 20 Mute
! 327: 176 // 0xb0 E0, 30 Volume Up
! 328: 174 // 0xae E0, 2E Volume Down
! 329: 237 // 0xed E0, 6D Media Select
! 330: 236 // 0xec E0, 6C E-Mail
! 331: 161 // 0xa1 E0, 21 Calculator
! 332: 235 // 0xeb E0, 6B My Computer
! 333: 229 // 0xe5 E0, 65 WWW Search
! 334: 178 // 0xb2 E0, 32 WWW Home
! 335: 234 // 0xea E0, 6A WWW Back
! 336: 233 // 0xe9 E0, 69 WWW Forward
! 337: 232 // 0xe8 E0, 68 WWW Stop
! 338: 231 // 0xe7 E0, 67 WWW Refresh
! 339: 230 // 0xe6 E0, 66 WWW Favorites
! 340: */
1.1 root 341: };
342:
1.1.1.2 ! root 343: int cocoa_keycode_to_qemu(int keycode)
1.1 root 344: {
1.1.1.2 ! root 345: if((sizeof(keymap)/sizeof(int)) <= keycode)
1.1 root 346: {
347: printf("(cocoa) warning unknow keycode 0x%x\n", keycode);
348: return 0;
349: }
350: return keymap[keycode];
351: }
352:
353: /*
354: ------------------------------------------------------
355: cocoa_refresh
356: ------------------------------------------------------
357: */
358: static void cocoa_refresh(DisplayState *ds)
359: {
360: //printf("cocoa_refresh \n");
361: NSDate *distantPast;
362: NSEvent *event;
363: NSAutoreleasePool *pool;
364:
365: pool = [ [ NSAutoreleasePool alloc ] init ];
366: distantPast = [ NSDate distantPast ];
367:
368: if (is_active_console(vga_console))
369: vga_update_display();
370: do {
371: event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
372: inMode: NSDefaultRunLoopMode dequeue:YES ];
373: if (event != nil) {
374: switch ([event type]) {
1.1.1.2 ! root 375: case NSFlagsChanged:
1.1 root 376: {
377: int keycode = cocoa_keycode_to_qemu([event keyCode]);
1.1.1.2 ! root 378:
! 379: if (keycode)
! 380: {
! 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_active_console(vga_console)) {
! 386: if (keycode & 0x80)
! 387: kbd_put_keycode(0xe0);
! 388: if (modifiers_state[keycode] == 0) {
! 389: /* keydown */
! 390: kbd_put_keycode(keycode & 0x7f);
! 391: modifiers_state[keycode] = 1;
! 392: } else {
! 393: /* keyup */
! 394: kbd_put_keycode(keycode | 0x80);
! 395: modifiers_state[keycode] = 0;
! 396: }
! 397: }
! 398: }
! 399:
! 400: /* release Mouse grab when pressing ctrl+alt */
! 401: if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask))
! 402: {
! 403: [window setTitle: @"QEMU"];
! 404: [NSCursor unhide];
! 405: CGAssociateMouseAndMouseCursorPosition ( TRUE );
! 406: grab = 0;
! 407: }
! 408: }
! 409: break;
! 410:
! 411: case NSKeyDown:
! 412: {
! 413: int keycode = cocoa_keycode_to_qemu([event keyCode]);
! 414:
! 415: /* handle command Key Combos */
! 416: if ([event modifierFlags] & NSCommandKeyMask) {
! 417: switch ([event keyCode]) {
! 418: /* quit */
! 419: case 12: /* q key */
! 420: /* switch to windowed View */
! 421: exit(0);
! 422: return;
! 423: }
! 424: }
1.1 root 425:
1.1.1.2 ! root 426: /* handle control + alt Key Combos */
! 427: if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
! 428: switch (keycode) {
! 429: /* toggle Monitor */
! 430: case 0x02 ... 0x0a: /* '1' to '9' keys */
! 431: console_select(keycode - 0x02);
! 432: if (is_active_console(vga_console)) {
! 433: /* tell the vga console to redisplay itself */
! 434: vga_invalidate_display();
! 435: break;
! 436: }
! 437: }
! 438: } else {
! 439: /* handle standard key events */
! 440: if (is_active_console(vga_console)) {
! 441: if (keycode & 0x80) //check bit for e0 in front
! 442: kbd_put_keycode(0xe0);
! 443: kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
! 444: /* handle monitor key events */
! 445: } else {
! 446: switch([event keyCode]) {
! 447: case 123:
! 448: kbd_put_keysym(QEMU_KEY_LEFT);
! 449: break;
! 450: case 124:
! 451: kbd_put_keysym(QEMU_KEY_RIGHT);
! 452: break;
! 453: case 125:
! 454: kbd_put_keysym(QEMU_KEY_DOWN);
! 455: break;
! 456: case 126:
! 457: kbd_put_keysym(QEMU_KEY_UP);
! 458: break;
! 459: default:
! 460: kbd_put_keysym([[event characters] characterAtIndex:0]);
! 461: break;
! 462: }
! 463: }
! 464: }
1.1 root 465: }
466: break;
1.1.1.2 ! root 467:
1.1 root 468: case NSKeyUp:
469: {
1.1.1.2 ! root 470: int keycode = cocoa_keycode_to_qemu([event keyCode]);
! 471: if (is_active_console(vga_console)) {
! 472: if (keycode & 0x80)
! 473: kbd_put_keycode(0xe0);
! 474: kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
! 475: }
1.1 root 476: }
477: break;
1.1.1.2 ! root 478:
! 479: case NSMouseMoved:
! 480: if (grab) {
! 481: int dx = [event deltaX];
! 482: int dy = [event deltaY];
! 483: int dz = [event deltaZ];
! 484: int buttons = 0;
! 485: kbd_mouse_event(dx, dy, dz, buttons);
! 486: }
! 487: break;
! 488:
1.1 root 489: case NSLeftMouseDown:
1.1.1.2 ! root 490: if (grab) {
! 491: int buttons = 0;
! 492:
! 493: /* leftclick+command simulates rightclick */
! 494: if ([event modifierFlags] & NSCommandKeyMask) {
! 495: buttons |= MOUSE_EVENT_RBUTTON;
! 496: } else {
! 497: buttons |= MOUSE_EVENT_LBUTTON;
! 498: }
! 499: kbd_mouse_event(0, 0, 0, buttons);
! 500: } else {
! 501: [NSApp sendEvent: event];
! 502: }
! 503: break;
! 504:
! 505: case NSLeftMouseDragged:
! 506: if (grab) {
! 507: int dx = [event deltaX];
! 508: int dy = [event deltaY];
! 509: int dz = [event deltaZ];
! 510: int buttons = 0;
! 511: if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) { //leftclick+command simulates rightclick
! 512: buttons |= MOUSE_EVENT_RBUTTON;
! 513: } else {
! 514: buttons |= MOUSE_EVENT_LBUTTON;
! 515: }
! 516: kbd_mouse_event(dx, dy, dz, buttons);
! 517: }
! 518: break;
! 519:
1.1 root 520: case NSLeftMouseUp:
1.1.1.2 ! root 521: if (grab) {
! 522: kbd_mouse_event(0, 0, 0, 0);
! 523: } else {
! 524: [window setTitle: @"QEMU (Press ctrl + alt to release Mouse)"];
! 525: [NSCursor hide];
! 526: CGAssociateMouseAndMouseCursorPosition ( FALSE );
! 527: grab = 1;
! 528: //[NSApp sendEvent: event];
! 529: }
! 530: break;
! 531:
1.1 root 532: case NSRightMouseDown:
1.1.1.2 ! root 533: if (grab) {
! 534: int buttons = 0;
! 535:
! 536: buttons |= MOUSE_EVENT_RBUTTON;
! 537: kbd_mouse_event(0, 0, 0, buttons);
! 538: } else {
! 539: [NSApp sendEvent: event];
! 540: }
! 541: break;
! 542:
! 543: case NSRightMouseDragged:
! 544: if (grab) {
! 545: int dx = [event deltaX];
! 546: int dy = [event deltaY];
! 547: int dz = [event deltaZ];
! 548: int buttons = 0;
! 549: buttons |= MOUSE_EVENT_RBUTTON;
! 550: kbd_mouse_event(dx, dy, dz, buttons);
! 551: }
! 552: break;
! 553:
1.1 root 554: case NSRightMouseUp:
1.1.1.2 ! root 555: if (grab) {
! 556: kbd_mouse_event(0, 0, 0, 0);
! 557: } else {
! 558: [NSApp sendEvent: event];
! 559: }
! 560: break;
! 561:
1.1 root 562: case NSOtherMouseDragged:
1.1.1.2 ! root 563: if (grab) {
! 564: int dx = [event deltaX];
! 565: int dy = [event deltaY];
! 566: int dz = [event deltaZ];
! 567: int buttons = 0;
! 568: buttons |= MOUSE_EVENT_MBUTTON;
! 569: kbd_mouse_event(dx, dy, dz, buttons);
! 570: }
! 571: break;
! 572:
! 573: case NSOtherMouseDown:
! 574: if (grab) {
! 575: int buttons = 0;
! 576: buttons |= MOUSE_EVENT_MBUTTON;
! 577: kbd_mouse_event(0, 0, 0, buttons);
! 578: } else {
! 579: [NSApp sendEvent:event];
! 580: }
! 581: break;
! 582:
! 583: case NSOtherMouseUp:
! 584: if (grab) {
! 585: kbd_mouse_event(0, 0, 0, 0);
! 586: } else {
! 587: [NSApp sendEvent: event];
! 588: }
! 589: break;
! 590:
! 591: case NSScrollWheel:
! 592: if (grab) {
! 593: int dz = [event deltaY];
! 594: kbd_mouse_event(0, 0, -dz, 0);
! 595: }
! 596: break;
1.1 root 597:
598: default: [NSApp sendEvent:event];
599: }
600: }
601: } while(event != nil);
602: }
603:
604: /*
605: ------------------------------------------------------
606: cocoa_cleanup
607: ------------------------------------------------------
608: */
609:
610: static void cocoa_cleanup(void)
611: {
612:
613: }
614:
615: /*
616: ------------------------------------------------------
617: cocoa_display_init
618: ------------------------------------------------------
619: */
620:
621: void cocoa_display_init(DisplayState *ds, int full_screen)
622: {
623: ds->dpy_update = cocoa_update;
624: ds->dpy_resize = cocoa_resize;
625: ds->dpy_refresh = cocoa_refresh;
626:
627: cocoa_resize(ds, 640, 400);
628:
629: atexit(cocoa_cleanup);
630: }
631:
632: /*
633: ------------------------------------------------------
634: Interface with Cocoa
635: ------------------------------------------------------
636: */
637:
638:
639: /*
640: ------------------------------------------------------
641: QemuWindow
642: Some trick from SDL to use miniwindow
643: ------------------------------------------------------
644: */
645: static void QZ_SetPortAlphaOpaque ()
646: {
647: /* Assume 32 bit if( bpp == 32 )*/
648: if ( 1 ) {
649:
650: uint32_t *pixels = (uint32_t*) current_ds.data;
651: uint32_t rowPixels = current_ds.linesize / 4;
652: uint32_t i, j;
653:
654: for (i = 0; i < current_ds.height; i++)
655: for (j = 0; j < current_ds.width; j++) {
656:
657: pixels[ (i * rowPixels) + j ] |= 0xFF000000;
658: }
659: }
660: }
661:
662: @implementation QemuWindow
663: - (void)miniaturize:(id)sender
664: {
665:
666: /* make the alpha channel opaque so anim won't have holes in it */
667: QZ_SetPortAlphaOpaque ();
668:
669: [ super miniaturize:sender ];
670:
671: }
672: - (void)display
673: {
674: /*
675: This method fires just before the window deminaturizes from the Dock.
676:
677: We'll save the current visible surface, let the window manager redraw any
678: UI elements, and restore the SDL surface. This way, no expose event
679: is required, and the deminiaturize works perfectly.
680: */
681:
682: /* make sure pixels are fully opaque */
683: QZ_SetPortAlphaOpaque ();
684:
685: /* save current visible SDL surface */
686: [ self cacheImageInRect:[ qd_view frame ] ];
687:
688: /* let the window manager redraw controls, border, etc */
689: [ super display ];
690:
691: /* restore visible SDL surface */
692: [ self restoreCachedImage ];
693: }
694:
695: @end
696:
697:
698: /*
699: ------------------------------------------------------
700: QemuCocoaGUIController
701: NSApp's delegate - indeed main object
702: ------------------------------------------------------
703: */
704:
705: @interface QemuCocoaGUIController : NSObject
706: {
707: }
708: - (void)applicationDidFinishLaunching: (NSNotification *) note;
709: - (void)applicationWillTerminate:(NSNotification *)aNotification;
710:
711: - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
712:
713: - (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
714: @end
715:
716: @implementation QemuCocoaGUIController
717: /* Called when the internal event loop has just started running */
718: - (void)applicationDidFinishLaunching: (NSNotification *) note
719: {
720:
721: /* Display an open dialog box if no argument were passed or
722: if qemu was launched from the finder ( the Finder passes "-psn" ) */
723:
724: if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0)
725: {
726: NSOpenPanel *op = [[NSOpenPanel alloc] init];
727:
728: cocoa_resize(¤t_ds, 640, 400);
729:
730: [op setPrompt:@"Boot image"];
731:
732: [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
733:
734: [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
735: modalForWindow:window modalDelegate:self
736: didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
737: }
738: else
739: {
740: /* or Launch Qemu, with the global args */
741: [self startEmulationWithArgc:gArgc argv:gArgv];
742: }
743: }
744:
745: - (void)applicationWillTerminate:(NSNotification *)aNotification
746: {
747: printf("Application will terminate\n");
748: qemu_system_shutdown_request();
749: /* In order to avoid a crash */
750: exit(0);
751: }
752:
753: - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
754: {
755: if(returnCode == NSCancelButton)
756: {
757: exit(0);
758: }
759:
760: if(returnCode == NSOKButton)
761: {
762: char *bin = "qemu";
763: char *img = (char*)[ [ sheet filename ] cString];
764:
765: char **argv = (char**)malloc( sizeof(char*)*3 );
766:
767: asprintf(&argv[0], "%s", bin);
768: asprintf(&argv[1], "-hda");
769: asprintf(&argv[2], "%s", img);
770:
771: printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
772:
773: [self startEmulationWithArgc:3 argv:(char**)argv];
774: }
775: }
776:
777: - (void)startEmulationWithArgc:(int)argc argv:(char**)argv
778: {
779: int status;
780: /* Launch Qemu */
781: printf("starting qemu...\n");
782: status = qemu_main (argc, argv);
783: exit(status);
784: }
785: @end
786:
787: /*
788: ------------------------------------------------------
789: Application Creation
790: ------------------------------------------------------
791: */
792:
793: /* Dock Connection */
794: typedef struct CPSProcessSerNum
795: {
796: UInt32 lo;
797: UInt32 hi;
798: } CPSProcessSerNum;
799:
800: extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
801: extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
802: extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
803:
804: /* Menu Creation */
805: static void setApplicationMenu(void)
806: {
807: /* warning: this code is very odd */
808: NSMenu *appleMenu;
809: NSMenuItem *menuItem;
810: NSString *title;
811: NSString *appName;
812:
813: appName = @"Qemu";
814: appleMenu = [[NSMenu alloc] initWithTitle:@""];
815:
816: /* Add menu items */
817: title = [@"About " stringByAppendingString:appName];
818: [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
819:
820: [appleMenu addItem:[NSMenuItem separatorItem]];
821:
822: title = [@"Hide " stringByAppendingString:appName];
823: [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
824:
825: menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
826: [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
827:
828: [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
829:
830: [appleMenu addItem:[NSMenuItem separatorItem]];
831:
832: title = [@"Quit " stringByAppendingString:appName];
833: [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
834:
835:
836: /* Put menu into the menubar */
837: menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
838: [menuItem setSubmenu:appleMenu];
839: [[NSApp mainMenu] addItem:menuItem];
840:
841: /* Tell the application object that this is now the application menu */
842: [NSApp setAppleMenu:appleMenu];
843:
844: /* Finally give up our references to the objects */
845: [appleMenu release];
846: [menuItem release];
847: }
848:
849: /* Create a window menu */
850: static void setupWindowMenu(void)
851: {
852: NSMenu *windowMenu;
853: NSMenuItem *windowMenuItem;
854: NSMenuItem *menuItem;
855:
856: windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
857:
858: /* "Minimize" item */
859: menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
860: [windowMenu addItem:menuItem];
861: [menuItem release];
862:
863: /* Put menu into the menubar */
864: windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
865: [windowMenuItem setSubmenu:windowMenu];
866: [[NSApp mainMenu] addItem:windowMenuItem];
867:
868: /* Tell the application object that this is now the window menu */
869: [NSApp setWindowsMenu:windowMenu];
870:
871: /* Finally give up our references to the objects */
872: [windowMenu release];
873: [windowMenuItem release];
874:
875: }
876:
877: static void CustomApplicationMain (argc, argv)
878: {
879: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
880: QemuCocoaGUIController *gui_controller;
881: CPSProcessSerNum PSN;
882:
883: [NSApplication sharedApplication];
884:
885: if (!CPSGetCurrentProcess(&PSN))
886: if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
887: if (!CPSSetFrontProcess(&PSN))
888: [NSApplication sharedApplication];
889:
890: /* Set up the menubar */
891: [NSApp setMainMenu:[[NSMenu alloc] init]];
892: setApplicationMenu();
893: setupWindowMenu();
894:
895: /* Create SDLMain and make it the app delegate */
896: gui_controller = [[QemuCocoaGUIController alloc] init];
897: [NSApp setDelegate:gui_controller];
898:
899: /* Start the main event loop */
900: [NSApp run];
901:
902: [gui_controller release];
903: [pool release];
904: }
905:
906: /* Real main of qemu-cocoa */
907: int main(int argc, char **argv)
908: {
909: gArgc = argc;
910: gArgv = argv;
911:
912: CustomApplicationMain (argc, argv);
913:
914: return 0;
915: }
unix.superglobalmegacorp.com