13e230dd2SCorentin Chary/* 23e230dd2SCorentin Chary * QEMU Cocoa CG display driver 33e230dd2SCorentin Chary * 43e230dd2SCorentin Chary * Copyright (c) 2008 Mike Kronenberg 53e230dd2SCorentin Chary * 63e230dd2SCorentin Chary * Permission is hereby granted, free of charge, to any person obtaining a copy 73e230dd2SCorentin Chary * of this software and associated documentation files (the "Software"), to deal 83e230dd2SCorentin Chary * in the Software without restriction, including without limitation the rights 93e230dd2SCorentin Chary * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 103e230dd2SCorentin Chary * copies of the Software, and to permit persons to whom the Software is 113e230dd2SCorentin Chary * furnished to do so, subject to the following conditions: 123e230dd2SCorentin Chary * 133e230dd2SCorentin Chary * The above copyright notice and this permission notice shall be included in 143e230dd2SCorentin Chary * all copies or substantial portions of the Software. 153e230dd2SCorentin Chary * 163e230dd2SCorentin Chary * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 173e230dd2SCorentin Chary * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183e230dd2SCorentin Chary * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 193e230dd2SCorentin Chary * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 203e230dd2SCorentin Chary * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 213e230dd2SCorentin Chary * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 223e230dd2SCorentin Chary * THE SOFTWARE. 233e230dd2SCorentin Chary */ 243e230dd2SCorentin Chary 253e230dd2SCorentin Chary#import <Cocoa/Cocoa.h> 263bbbee18SAndreas Färber#include <crt_externs.h> 273e230dd2SCorentin Chary 283e230dd2SCorentin Chary#include "qemu-common.h" 2928ecbaeeSPaolo Bonzini#include "ui/console.h" 309c17d615SPaolo Bonzini#include "sysemu/sysemu.h" 313e230dd2SCorentin Chary 323e230dd2SCorentin Chary#ifndef MAC_OS_X_VERSION_10_4 333e230dd2SCorentin Chary#define MAC_OS_X_VERSION_10_4 1040 343e230dd2SCorentin Chary#endif 353e230dd2SCorentin Chary#ifndef MAC_OS_X_VERSION_10_5 363e230dd2SCorentin Chary#define MAC_OS_X_VERSION_10_5 1050 373e230dd2SCorentin Chary#endif 382ba9de6eSPeter Maydell#ifndef MAC_OS_X_VERSION_10_6 392ba9de6eSPeter Maydell#define MAC_OS_X_VERSION_10_6 1060 402ba9de6eSPeter Maydell#endif 413e230dd2SCorentin Chary 423e230dd2SCorentin Chary 433e230dd2SCorentin Chary//#define DEBUG 443e230dd2SCorentin Chary 453e230dd2SCorentin Chary#ifdef DEBUG 463e230dd2SCorentin Chary#define COCOA_DEBUG(...) { (void) fprintf (stdout, __VA_ARGS__); } 473e230dd2SCorentin Chary#else 483e230dd2SCorentin Chary#define COCOA_DEBUG(...) ((void) 0) 493e230dd2SCorentin Chary#endif 503e230dd2SCorentin Chary 513e230dd2SCorentin Chary#define cgrect(nsrect) (*(CGRect *)&(nsrect)) 523e230dd2SCorentin Chary#define COCOA_MOUSE_EVENT \ 533e230dd2SCorentin Chary if (isTabletEnabled) { \ 543e230dd2SCorentin Chary kbd_mouse_event((int)(p.x * 0x7FFF / (screen.width - 1)), (int)((screen.height - p.y) * 0x7FFF / (screen.height - 1)), 0, buttons); \ 553e230dd2SCorentin Chary } else if (isMouseGrabed) { \ 563e230dd2SCorentin Chary kbd_mouse_event((int)[event deltaX], (int)[event deltaY], 0, buttons); \ 573e230dd2SCorentin Chary } else { \ 583e230dd2SCorentin Chary [NSApp sendEvent:event]; \ 593e230dd2SCorentin Chary } 603e230dd2SCorentin Chary 613e230dd2SCorentin Charytypedef struct { 623e230dd2SCorentin Chary int width; 633e230dd2SCorentin Chary int height; 643e230dd2SCorentin Chary int bitsPerComponent; 653e230dd2SCorentin Chary int bitsPerPixel; 663e230dd2SCorentin Chary} QEMUScreen; 673e230dd2SCorentin Chary 683e230dd2SCorentin CharyNSWindow *normalWindow; 693e230dd2SCorentin Charystatic DisplayChangeListener *dcl; 703e230dd2SCorentin Chary 713e230dd2SCorentin Charyint gArgc; 723e230dd2SCorentin Charychar **gArgv; 733e230dd2SCorentin Chary 743e230dd2SCorentin Chary// keymap conversion 753e230dd2SCorentin Charyint keymap[] = 763e230dd2SCorentin Chary{ 773e230dd2SCorentin Chary// SdlI macI macH SdlH 104xtH 104xtC sdl 783e230dd2SCorentin Chary 30, // 0 0x00 0x1e A QZ_a 793e230dd2SCorentin Chary 31, // 1 0x01 0x1f S QZ_s 803e230dd2SCorentin Chary 32, // 2 0x02 0x20 D QZ_d 813e230dd2SCorentin Chary 33, // 3 0x03 0x21 F QZ_f 823e230dd2SCorentin Chary 35, // 4 0x04 0x23 H QZ_h 833e230dd2SCorentin Chary 34, // 5 0x05 0x22 G QZ_g 843e230dd2SCorentin Chary 44, // 6 0x06 0x2c Z QZ_z 853e230dd2SCorentin Chary 45, // 7 0x07 0x2d X QZ_x 863e230dd2SCorentin Chary 46, // 8 0x08 0x2e C QZ_c 873e230dd2SCorentin Chary 47, // 9 0x09 0x2f V QZ_v 883e230dd2SCorentin Chary 0, // 10 0x0A Undefined 893e230dd2SCorentin Chary 48, // 11 0x0B 0x30 B QZ_b 903e230dd2SCorentin Chary 16, // 12 0x0C 0x10 Q QZ_q 913e230dd2SCorentin Chary 17, // 13 0x0D 0x11 W QZ_w 923e230dd2SCorentin Chary 18, // 14 0x0E 0x12 E QZ_e 933e230dd2SCorentin Chary 19, // 15 0x0F 0x13 R QZ_r 943e230dd2SCorentin Chary 21, // 16 0x10 0x15 Y QZ_y 953e230dd2SCorentin Chary 20, // 17 0x11 0x14 T QZ_t 963e230dd2SCorentin Chary 2, // 18 0x12 0x02 1 QZ_1 973e230dd2SCorentin Chary 3, // 19 0x13 0x03 2 QZ_2 983e230dd2SCorentin Chary 4, // 20 0x14 0x04 3 QZ_3 993e230dd2SCorentin Chary 5, // 21 0x15 0x05 4 QZ_4 1003e230dd2SCorentin Chary 7, // 22 0x16 0x07 6 QZ_6 1013e230dd2SCorentin Chary 6, // 23 0x17 0x06 5 QZ_5 1023e230dd2SCorentin Chary 13, // 24 0x18 0x0d = QZ_EQUALS 1033e230dd2SCorentin Chary 10, // 25 0x19 0x0a 9 QZ_9 1043e230dd2SCorentin Chary 8, // 26 0x1A 0x08 7 QZ_7 1053e230dd2SCorentin Chary 12, // 27 0x1B 0x0c - QZ_MINUS 1063e230dd2SCorentin Chary 9, // 28 0x1C 0x09 8 QZ_8 1073e230dd2SCorentin Chary 11, // 29 0x1D 0x0b 0 QZ_0 1083e230dd2SCorentin Chary 27, // 30 0x1E 0x1b ] QZ_RIGHTBRACKET 1093e230dd2SCorentin Chary 24, // 31 0x1F 0x18 O QZ_o 1103e230dd2SCorentin Chary 22, // 32 0x20 0x16 U QZ_u 1113e230dd2SCorentin Chary 26, // 33 0x21 0x1a [ QZ_LEFTBRACKET 1123e230dd2SCorentin Chary 23, // 34 0x22 0x17 I QZ_i 1133e230dd2SCorentin Chary 25, // 35 0x23 0x19 P QZ_p 1143e230dd2SCorentin Chary 28, // 36 0x24 0x1c ENTER QZ_RETURN 1153e230dd2SCorentin Chary 38, // 37 0x25 0x26 L QZ_l 1163e230dd2SCorentin Chary 36, // 38 0x26 0x24 J QZ_j 1173e230dd2SCorentin Chary 40, // 39 0x27 0x28 ' QZ_QUOTE 1183e230dd2SCorentin Chary 37, // 40 0x28 0x25 K QZ_k 1193e230dd2SCorentin Chary 39, // 41 0x29 0x27 ; QZ_SEMICOLON 1203e230dd2SCorentin Chary 43, // 42 0x2A 0x2b \ QZ_BACKSLASH 1213e230dd2SCorentin Chary 51, // 43 0x2B 0x33 , QZ_COMMA 1223e230dd2SCorentin Chary 53, // 44 0x2C 0x35 / QZ_SLASH 1233e230dd2SCorentin Chary 49, // 45 0x2D 0x31 N QZ_n 1243e230dd2SCorentin Chary 50, // 46 0x2E 0x32 M QZ_m 1253e230dd2SCorentin Chary 52, // 47 0x2F 0x34 . QZ_PERIOD 1263e230dd2SCorentin Chary 15, // 48 0x30 0x0f TAB QZ_TAB 1273e230dd2SCorentin Chary 57, // 49 0x31 0x39 SPACE QZ_SPACE 1283e230dd2SCorentin Chary 41, // 50 0x32 0x29 ` QZ_BACKQUOTE 1293e230dd2SCorentin Chary 14, // 51 0x33 0x0e BKSP QZ_BACKSPACE 1303e230dd2SCorentin Chary 0, // 52 0x34 Undefined 1313e230dd2SCorentin Chary 1, // 53 0x35 0x01 ESC QZ_ESCAPE 1323e230dd2SCorentin Chary 0, // 54 0x36 QZ_RMETA 1333e230dd2SCorentin Chary 0, // 55 0x37 QZ_LMETA 1343e230dd2SCorentin Chary 42, // 56 0x38 0x2a L SHFT QZ_LSHIFT 1353e230dd2SCorentin Chary 58, // 57 0x39 0x3a CAPS QZ_CAPSLOCK 1363e230dd2SCorentin Chary 56, // 58 0x3A 0x38 L ALT QZ_LALT 1373e230dd2SCorentin Chary 29, // 59 0x3B 0x1d L CTRL QZ_LCTRL 1383e230dd2SCorentin Chary 54, // 60 0x3C 0x36 R SHFT QZ_RSHIFT 1393e230dd2SCorentin Chary 184,// 61 0x3D 0xb8 E0,38 R ALT QZ_RALT 1403e230dd2SCorentin Chary 157,// 62 0x3E 0x9d E0,1D R CTRL QZ_RCTRL 1413e230dd2SCorentin Chary 0, // 63 0x3F Undefined 1423e230dd2SCorentin Chary 0, // 64 0x40 Undefined 1433e230dd2SCorentin Chary 0, // 65 0x41 Undefined 1443e230dd2SCorentin Chary 0, // 66 0x42 Undefined 1453e230dd2SCorentin Chary 55, // 67 0x43 0x37 KP * QZ_KP_MULTIPLY 1463e230dd2SCorentin Chary 0, // 68 0x44 Undefined 1473e230dd2SCorentin Chary 78, // 69 0x45 0x4e KP + QZ_KP_PLUS 1483e230dd2SCorentin Chary 0, // 70 0x46 Undefined 1493e230dd2SCorentin Chary 69, // 71 0x47 0x45 NUM QZ_NUMLOCK 1503e230dd2SCorentin Chary 0, // 72 0x48 Undefined 1513e230dd2SCorentin Chary 0, // 73 0x49 Undefined 1523e230dd2SCorentin Chary 0, // 74 0x4A Undefined 1533e230dd2SCorentin Chary 181,// 75 0x4B 0xb5 E0,35 KP / QZ_KP_DIVIDE 1543e230dd2SCorentin Chary 152,// 76 0x4C 0x9c E0,1C KP EN QZ_KP_ENTER 1553e230dd2SCorentin Chary 0, // 77 0x4D undefined 1563e230dd2SCorentin Chary 74, // 78 0x4E 0x4a KP - QZ_KP_MINUS 1573e230dd2SCorentin Chary 0, // 79 0x4F Undefined 1583e230dd2SCorentin Chary 0, // 80 0x50 Undefined 1593e230dd2SCorentin Chary 0, // 81 0x51 QZ_KP_EQUALS 1603e230dd2SCorentin Chary 82, // 82 0x52 0x52 KP 0 QZ_KP0 1613e230dd2SCorentin Chary 79, // 83 0x53 0x4f KP 1 QZ_KP1 1623e230dd2SCorentin Chary 80, // 84 0x54 0x50 KP 2 QZ_KP2 1633e230dd2SCorentin Chary 81, // 85 0x55 0x51 KP 3 QZ_KP3 1643e230dd2SCorentin Chary 75, // 86 0x56 0x4b KP 4 QZ_KP4 1653e230dd2SCorentin Chary 76, // 87 0x57 0x4c KP 5 QZ_KP5 1663e230dd2SCorentin Chary 77, // 88 0x58 0x4d KP 6 QZ_KP6 1673e230dd2SCorentin Chary 71, // 89 0x59 0x47 KP 7 QZ_KP7 1683e230dd2SCorentin Chary 0, // 90 0x5A Undefined 1693e230dd2SCorentin Chary 72, // 91 0x5B 0x48 KP 8 QZ_KP8 1703e230dd2SCorentin Chary 73, // 92 0x5C 0x49 KP 9 QZ_KP9 1713e230dd2SCorentin Chary 0, // 93 0x5D Undefined 1723e230dd2SCorentin Chary 0, // 94 0x5E Undefined 1733e230dd2SCorentin Chary 0, // 95 0x5F Undefined 1743e230dd2SCorentin Chary 63, // 96 0x60 0x3f F5 QZ_F5 1753e230dd2SCorentin Chary 64, // 97 0x61 0x40 F6 QZ_F6 1763e230dd2SCorentin Chary 65, // 98 0x62 0x41 F7 QZ_F7 1773e230dd2SCorentin Chary 61, // 99 0x63 0x3d F3 QZ_F3 1783e230dd2SCorentin Chary 66, // 100 0x64 0x42 F8 QZ_F8 1793e230dd2SCorentin Chary 67, // 101 0x65 0x43 F9 QZ_F9 1803e230dd2SCorentin Chary 0, // 102 0x66 Undefined 1813e230dd2SCorentin Chary 87, // 103 0x67 0x57 F11 QZ_F11 1823e230dd2SCorentin Chary 0, // 104 0x68 Undefined 1833e230dd2SCorentin Chary 183,// 105 0x69 0xb7 QZ_PRINT 1843e230dd2SCorentin Chary 0, // 106 0x6A Undefined 1853e230dd2SCorentin Chary 70, // 107 0x6B 0x46 SCROLL QZ_SCROLLOCK 1863e230dd2SCorentin Chary 0, // 108 0x6C Undefined 1873e230dd2SCorentin Chary 68, // 109 0x6D 0x44 F10 QZ_F10 1883e230dd2SCorentin Chary 0, // 110 0x6E Undefined 1893e230dd2SCorentin Chary 88, // 111 0x6F 0x58 F12 QZ_F12 1903e230dd2SCorentin Chary 0, // 112 0x70 Undefined 1913e230dd2SCorentin Chary 110,// 113 0x71 0x0 QZ_PAUSE 1923e230dd2SCorentin Chary 210,// 114 0x72 0xd2 E0,52 INSERT QZ_INSERT 1933e230dd2SCorentin Chary 199,// 115 0x73 0xc7 E0,47 HOME QZ_HOME 1943e230dd2SCorentin Chary 201,// 116 0x74 0xc9 E0,49 PG UP QZ_PAGEUP 1953e230dd2SCorentin Chary 211,// 117 0x75 0xd3 E0,53 DELETE QZ_DELETE 1963e230dd2SCorentin Chary 62, // 118 0x76 0x3e F4 QZ_F4 1973e230dd2SCorentin Chary 207,// 119 0x77 0xcf E0,4f END QZ_END 1983e230dd2SCorentin Chary 60, // 120 0x78 0x3c F2 QZ_F2 1993e230dd2SCorentin Chary 209,// 121 0x79 0xd1 E0,51 PG DN QZ_PAGEDOWN 2003e230dd2SCorentin Chary 59, // 122 0x7A 0x3b F1 QZ_F1 2013e230dd2SCorentin Chary 203,// 123 0x7B 0xcb e0,4B L ARROW QZ_LEFT 2023e230dd2SCorentin Chary 205,// 124 0x7C 0xcd e0,4D R ARROW QZ_RIGHT 2033e230dd2SCorentin Chary 208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN 2043e230dd2SCorentin Chary 200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP 2053e230dd2SCorentin Chary/* 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 */ 2063e230dd2SCorentin Chary 2073e230dd2SCorentin Chary/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */ 2083e230dd2SCorentin Chary/* 2093e230dd2SCorentin Chary 219 // 0xdb e0,5b L GUI 2103e230dd2SCorentin Chary 220 // 0xdc e0,5c R GUI 2113e230dd2SCorentin Chary 221 // 0xdd e0,5d APPS 2123e230dd2SCorentin Chary // E0,2A,E0,37 PRNT SCRN 2133e230dd2SCorentin Chary // E1,1D,45,E1,9D,C5 PAUSE 2143e230dd2SCorentin Chary 83 // 0x53 0x53 KP . 2153e230dd2SCorentin Chary// ACPI Scan Codes 2163e230dd2SCorentin Chary 222 // 0xde E0, 5E Power 2173e230dd2SCorentin Chary 223 // 0xdf E0, 5F Sleep 2183e230dd2SCorentin Chary 227 // 0xe3 E0, 63 Wake 2193e230dd2SCorentin Chary// Windows Multimedia Scan Codes 2203e230dd2SCorentin Chary 153 // 0x99 E0, 19 Next Track 2213e230dd2SCorentin Chary 144 // 0x90 E0, 10 Previous Track 2223e230dd2SCorentin Chary 164 // 0xa4 E0, 24 Stop 2233e230dd2SCorentin Chary 162 // 0xa2 E0, 22 Play/Pause 2243e230dd2SCorentin Chary 160 // 0xa0 E0, 20 Mute 2253e230dd2SCorentin Chary 176 // 0xb0 E0, 30 Volume Up 2263e230dd2SCorentin Chary 174 // 0xae E0, 2E Volume Down 2273e230dd2SCorentin Chary 237 // 0xed E0, 6D Media Select 2283e230dd2SCorentin Chary 236 // 0xec E0, 6C E-Mail 2293e230dd2SCorentin Chary 161 // 0xa1 E0, 21 Calculator 2303e230dd2SCorentin Chary 235 // 0xeb E0, 6B My Computer 2313e230dd2SCorentin Chary 229 // 0xe5 E0, 65 WWW Search 2323e230dd2SCorentin Chary 178 // 0xb2 E0, 32 WWW Home 2333e230dd2SCorentin Chary 234 // 0xea E0, 6A WWW Back 2343e230dd2SCorentin Chary 233 // 0xe9 E0, 69 WWW Forward 2353e230dd2SCorentin Chary 232 // 0xe8 E0, 68 WWW Stop 2363e230dd2SCorentin Chary 231 // 0xe7 E0, 67 WWW Refresh 2373e230dd2SCorentin Chary 230 // 0xe6 E0, 66 WWW Favorites 2383e230dd2SCorentin Chary*/ 2393e230dd2SCorentin Chary}; 2403e230dd2SCorentin Chary 2413e230dd2SCorentin Charystatic int cocoa_keycode_to_qemu(int keycode) 2423e230dd2SCorentin Chary{ 243*5d70192bSStefan Weil if (ARRAY_SIZE(keymap) <= keycode) { 244*5d70192bSStefan Weil printf("(cocoa) warning unknown keycode 0x%x\n", keycode); 2453e230dd2SCorentin Chary return 0; 2463e230dd2SCorentin Chary } 2473e230dd2SCorentin Chary return keymap[keycode]; 2483e230dd2SCorentin Chary} 2493e230dd2SCorentin Chary 2503e230dd2SCorentin Chary 2513e230dd2SCorentin Chary 2523e230dd2SCorentin Chary/* 2533e230dd2SCorentin Chary ------------------------------------------------------ 2543e230dd2SCorentin Chary QemuCocoaView 2553e230dd2SCorentin Chary ------------------------------------------------------ 2563e230dd2SCorentin Chary*/ 2573e230dd2SCorentin Chary@interface QemuCocoaView : NSView 2583e230dd2SCorentin Chary{ 2593e230dd2SCorentin Chary QEMUScreen screen; 2603e230dd2SCorentin Chary NSWindow *fullScreenWindow; 2613e230dd2SCorentin Chary float cx,cy,cw,ch,cdx,cdy; 2623e230dd2SCorentin Chary CGDataProviderRef dataProviderRef; 2633e230dd2SCorentin Chary int modifiers_state[256]; 2643e230dd2SCorentin Chary BOOL isMouseGrabed; 2653e230dd2SCorentin Chary BOOL isFullscreen; 2663e230dd2SCorentin Chary BOOL isAbsoluteEnabled; 2673e230dd2SCorentin Chary BOOL isTabletEnabled; 2683e230dd2SCorentin Chary} 2695e00d3acSGerd Hoffmann- (void) switchSurface:(DisplaySurface *)surface; 2703e230dd2SCorentin Chary- (void) grabMouse; 2713e230dd2SCorentin Chary- (void) ungrabMouse; 2723e230dd2SCorentin Chary- (void) toggleFullScreen:(id)sender; 2733e230dd2SCorentin Chary- (void) handleEvent:(NSEvent *)event; 2743e230dd2SCorentin Chary- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled; 2753e230dd2SCorentin Chary- (BOOL) isMouseGrabed; 2763e230dd2SCorentin Chary- (BOOL) isAbsoluteEnabled; 2773e230dd2SCorentin Chary- (float) cdx; 2783e230dd2SCorentin Chary- (float) cdy; 2793e230dd2SCorentin Chary- (QEMUScreen) gscreen; 2803e230dd2SCorentin Chary@end 2813e230dd2SCorentin Chary 2827fee199cSAndreas FärberQemuCocoaView *cocoaView; 2837fee199cSAndreas Färber 2843e230dd2SCorentin Chary@implementation QemuCocoaView 2853e230dd2SCorentin Chary- (id)initWithFrame:(NSRect)frameRect 2863e230dd2SCorentin Chary{ 2873e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: initWithFrame\n"); 2883e230dd2SCorentin Chary 2893e230dd2SCorentin Chary self = [super initWithFrame:frameRect]; 2903e230dd2SCorentin Chary if (self) { 2913e230dd2SCorentin Chary 2923e230dd2SCorentin Chary screen.bitsPerComponent = 8; 2933e230dd2SCorentin Chary screen.bitsPerPixel = 32; 2943e230dd2SCorentin Chary screen.width = frameRect.size.width; 2953e230dd2SCorentin Chary screen.height = frameRect.size.height; 2963e230dd2SCorentin Chary 2973e230dd2SCorentin Chary } 2983e230dd2SCorentin Chary return self; 2993e230dd2SCorentin Chary} 3003e230dd2SCorentin Chary 3013e230dd2SCorentin Chary- (void) dealloc 3023e230dd2SCorentin Chary{ 3033e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: dealloc\n"); 3043e230dd2SCorentin Chary 3053e230dd2SCorentin Chary if (dataProviderRef) 3063e230dd2SCorentin Chary CGDataProviderRelease(dataProviderRef); 3073e230dd2SCorentin Chary 3083e230dd2SCorentin Chary [super dealloc]; 3093e230dd2SCorentin Chary} 3103e230dd2SCorentin Chary 3113e230dd2SCorentin Chary- (BOOL) isOpaque 3123e230dd2SCorentin Chary{ 3133e230dd2SCorentin Chary return YES; 3143e230dd2SCorentin Chary} 3153e230dd2SCorentin Chary 3163e230dd2SCorentin Chary- (void) drawRect:(NSRect) rect 3173e230dd2SCorentin Chary{ 3183e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: drawRect\n"); 3193e230dd2SCorentin Chary 3203e230dd2SCorentin Chary // get CoreGraphic context 3213e230dd2SCorentin Chary CGContextRef viewContextRef = [[NSGraphicsContext currentContext] graphicsPort]; 3223e230dd2SCorentin Chary CGContextSetInterpolationQuality (viewContextRef, kCGInterpolationNone); 3233e230dd2SCorentin Chary CGContextSetShouldAntialias (viewContextRef, NO); 3243e230dd2SCorentin Chary 3253e230dd2SCorentin Chary // draw screen bitmap directly to Core Graphics context 3263e230dd2SCorentin Chary if (dataProviderRef) { 3273e230dd2SCorentin Chary CGImageRef imageRef = CGImageCreate( 3283e230dd2SCorentin Chary screen.width, //width 3293e230dd2SCorentin Chary screen.height, //height 3303e230dd2SCorentin Chary screen.bitsPerComponent, //bitsPerComponent 3313e230dd2SCorentin Chary screen.bitsPerPixel, //bitsPerPixel 3323e230dd2SCorentin Chary (screen.width * (screen.bitsPerComponent/2)), //bytesPerRow 3333e230dd2SCorentin Chary#ifdef __LITTLE_ENDIAN__ 3343e230dd2SCorentin Chary CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), //colorspace for OS X >= 10.4 3353e230dd2SCorentin Chary kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, 3363e230dd2SCorentin Chary#else 3373e230dd2SCorentin Chary CGColorSpaceCreateDeviceRGB(), //colorspace for OS X < 10.4 (actually ppc) 3383e230dd2SCorentin Chary kCGImageAlphaNoneSkipFirst, //bitmapInfo 3393e230dd2SCorentin Chary#endif 3403e230dd2SCorentin Chary dataProviderRef, //provider 3413e230dd2SCorentin Chary NULL, //decode 3423e230dd2SCorentin Chary 0, //interpolate 3433e230dd2SCorentin Chary kCGRenderingIntentDefault //intent 3443e230dd2SCorentin Chary ); 3453e230dd2SCorentin Chary// test if host supports "CGImageCreateWithImageInRect" at compile time 3463e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) 3473e230dd2SCorentin Chary if (CGImageCreateWithImageInRect == NULL) { // test if "CGImageCreateWithImageInRect" is supported on host at runtime 3483e230dd2SCorentin Chary#endif 3493e230dd2SCorentin Chary // compatibility drawing code (draws everything) (OS X < 10.4) 3503e230dd2SCorentin Chary CGContextDrawImage (viewContextRef, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), imageRef); 3513e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) 3523e230dd2SCorentin Chary } else { 3533e230dd2SCorentin Chary // selective drawing code (draws only dirty rectangles) (OS X >= 10.4) 3543e230dd2SCorentin Chary const NSRect *rectList; 3553e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 3563e230dd2SCorentin Chary NSInteger rectCount; 3573e230dd2SCorentin Chary#else 3583e230dd2SCorentin Chary int rectCount; 3593e230dd2SCorentin Chary#endif 3603e230dd2SCorentin Chary int i; 3613e230dd2SCorentin Chary CGImageRef clipImageRef; 3623e230dd2SCorentin Chary CGRect clipRect; 3633e230dd2SCorentin Chary 3643e230dd2SCorentin Chary [self getRectsBeingDrawn:&rectList count:&rectCount]; 3653e230dd2SCorentin Chary for (i = 0; i < rectCount; i++) { 3663e230dd2SCorentin Chary clipRect.origin.x = rectList[i].origin.x / cdx; 3673e230dd2SCorentin Chary clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height) / cdy; 3683e230dd2SCorentin Chary clipRect.size.width = rectList[i].size.width / cdx; 3693e230dd2SCorentin Chary clipRect.size.height = rectList[i].size.height / cdy; 3703e230dd2SCorentin Chary clipImageRef = CGImageCreateWithImageInRect( 3713e230dd2SCorentin Chary imageRef, 3723e230dd2SCorentin Chary clipRect 3733e230dd2SCorentin Chary ); 3743e230dd2SCorentin Chary CGContextDrawImage (viewContextRef, cgrect(rectList[i]), clipImageRef); 3753e230dd2SCorentin Chary CGImageRelease (clipImageRef); 3763e230dd2SCorentin Chary } 3773e230dd2SCorentin Chary } 3783e230dd2SCorentin Chary#endif 3793e230dd2SCorentin Chary CGImageRelease (imageRef); 3803e230dd2SCorentin Chary } 3813e230dd2SCorentin Chary} 3823e230dd2SCorentin Chary 3833e230dd2SCorentin Chary- (void) setContentDimensions 3843e230dd2SCorentin Chary{ 3853e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: setContentDimensions\n"); 3863e230dd2SCorentin Chary 3873e230dd2SCorentin Chary if (isFullscreen) { 3883e230dd2SCorentin Chary cdx = [[NSScreen mainScreen] frame].size.width / (float)screen.width; 3893e230dd2SCorentin Chary cdy = [[NSScreen mainScreen] frame].size.height / (float)screen.height; 3903e230dd2SCorentin Chary cw = screen.width * cdx; 3913e230dd2SCorentin Chary ch = screen.height * cdy; 3923e230dd2SCorentin Chary cx = ([[NSScreen mainScreen] frame].size.width - cw) / 2.0; 3933e230dd2SCorentin Chary cy = ([[NSScreen mainScreen] frame].size.height - ch) / 2.0; 3943e230dd2SCorentin Chary } else { 3953e230dd2SCorentin Chary cx = 0; 3963e230dd2SCorentin Chary cy = 0; 3973e230dd2SCorentin Chary cw = screen.width; 3983e230dd2SCorentin Chary ch = screen.height; 3993e230dd2SCorentin Chary cdx = 1.0; 4003e230dd2SCorentin Chary cdy = 1.0; 4013e230dd2SCorentin Chary } 4023e230dd2SCorentin Chary} 4033e230dd2SCorentin Chary 4045e00d3acSGerd Hoffmann- (void) switchSurface:(DisplaySurface *)surface 4053e230dd2SCorentin Chary{ 4065e00d3acSGerd Hoffmann COCOA_DEBUG("QemuCocoaView: switchSurface\n"); 4073e230dd2SCorentin Chary 4088510d91eSPeter Maydell int w = surface_width(surface); 4098510d91eSPeter Maydell int h = surface_height(surface); 4108510d91eSPeter Maydell 4113e230dd2SCorentin Chary // update screenBuffer 4123e230dd2SCorentin Chary if (dataProviderRef) 4133e230dd2SCorentin Chary CGDataProviderRelease(dataProviderRef); 4143e230dd2SCorentin Chary 4153e230dd2SCorentin Chary //sync host window color space with guests 4165e00d3acSGerd Hoffmann screen.bitsPerPixel = surface_bits_per_pixel(surface); 4175e00d3acSGerd Hoffmann screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2; 4183e230dd2SCorentin Chary 4195e00d3acSGerd Hoffmann dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL); 4203e230dd2SCorentin Chary 4213e230dd2SCorentin Chary // update windows 4223e230dd2SCorentin Chary if (isFullscreen) { 4233e230dd2SCorentin Chary [[fullScreenWindow contentView] setFrame:[[NSScreen mainScreen] frame]]; 4243e230dd2SCorentin Chary [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]; 4253e230dd2SCorentin Chary } else { 4263e230dd2SCorentin Chary if (qemu_name) 4273e230dd2SCorentin Chary [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]]; 4283e230dd2SCorentin Chary [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:NO]; 4293e230dd2SCorentin Chary } 4303e230dd2SCorentin Chary screen.width = w; 4313e230dd2SCorentin Chary screen.height = h; 4323e230dd2SCorentin Chary [normalWindow center]; 4333e230dd2SCorentin Chary [self setContentDimensions]; 4343e230dd2SCorentin Chary [self setFrame:NSMakeRect(cx, cy, cw, ch)]; 4353e230dd2SCorentin Chary} 4363e230dd2SCorentin Chary 4373e230dd2SCorentin Chary- (void) toggleFullScreen:(id)sender 4383e230dd2SCorentin Chary{ 4393e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n"); 4403e230dd2SCorentin Chary 4413e230dd2SCorentin Chary if (isFullscreen) { // switch from fullscreen to desktop 4423e230dd2SCorentin Chary isFullscreen = FALSE; 4433e230dd2SCorentin Chary [self ungrabMouse]; 4443e230dd2SCorentin Chary [self setContentDimensions]; 4453e230dd2SCorentin Chary// test if host supports "exitFullScreenModeWithOptions" at compile time 4463e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 4473e230dd2SCorentin Chary if ([NSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)]) { // test if "exitFullScreenModeWithOptions" is supported on host at runtime 4483e230dd2SCorentin Chary [self exitFullScreenModeWithOptions:nil]; 4493e230dd2SCorentin Chary } else { 4503e230dd2SCorentin Chary#endif 4513e230dd2SCorentin Chary [fullScreenWindow close]; 4523e230dd2SCorentin Chary [normalWindow setContentView: self]; 4533e230dd2SCorentin Chary [normalWindow makeKeyAndOrderFront: self]; 4543e230dd2SCorentin Chary [NSMenu setMenuBarVisible:YES]; 4553e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 4563e230dd2SCorentin Chary } 4573e230dd2SCorentin Chary#endif 4583e230dd2SCorentin Chary } else { // switch from desktop to fullscreen 4593e230dd2SCorentin Chary isFullscreen = TRUE; 4603e230dd2SCorentin Chary [self grabMouse]; 4613e230dd2SCorentin Chary [self setContentDimensions]; 4623e230dd2SCorentin Chary// test if host supports "enterFullScreenMode:withOptions" at compile time 4633e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 4643e230dd2SCorentin Chary if ([NSView respondsToSelector:@selector(enterFullScreenMode:withOptions:)]) { // test if "enterFullScreenMode:withOptions" is supported on host at runtime 4653e230dd2SCorentin Chary [self enterFullScreenMode:[NSScreen mainScreen] withOptions:[NSDictionary dictionaryWithObjectsAndKeys: 4663e230dd2SCorentin Chary [NSNumber numberWithBool:NO], NSFullScreenModeAllScreens, 4673e230dd2SCorentin Chary [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kCGDisplayModeIsStretched, nil], NSFullScreenModeSetting, 4683e230dd2SCorentin Chary nil]]; 4693e230dd2SCorentin Chary } else { 4703e230dd2SCorentin Chary#endif 4713e230dd2SCorentin Chary [NSMenu setMenuBarVisible:NO]; 4723e230dd2SCorentin Chary fullScreenWindow = [[NSWindow alloc] initWithContentRect:[[NSScreen mainScreen] frame] 4733e230dd2SCorentin Chary styleMask:NSBorderlessWindowMask 4743e230dd2SCorentin Chary backing:NSBackingStoreBuffered 4753e230dd2SCorentin Chary defer:NO]; 4763e230dd2SCorentin Chary [fullScreenWindow setHasShadow:NO]; 4773e230dd2SCorentin Chary [fullScreenWindow setContentView:self]; 4783e230dd2SCorentin Chary [fullScreenWindow makeKeyAndOrderFront:self]; 4793e230dd2SCorentin Chary#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 4803e230dd2SCorentin Chary } 4813e230dd2SCorentin Chary#endif 4823e230dd2SCorentin Chary } 4833e230dd2SCorentin Chary} 4843e230dd2SCorentin Chary 4853e230dd2SCorentin Chary- (void) handleEvent:(NSEvent *)event 4863e230dd2SCorentin Chary{ 4873e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: handleEvent\n"); 4883e230dd2SCorentin Chary 4893e230dd2SCorentin Chary int buttons = 0; 4903e230dd2SCorentin Chary int keycode; 4913e230dd2SCorentin Chary NSPoint p = [event locationInWindow]; 4923e230dd2SCorentin Chary 4933e230dd2SCorentin Chary switch ([event type]) { 4943e230dd2SCorentin Chary case NSFlagsChanged: 4953e230dd2SCorentin Chary keycode = cocoa_keycode_to_qemu([event keyCode]); 4963e230dd2SCorentin Chary if (keycode) { 4973e230dd2SCorentin Chary if (keycode == 58 || keycode == 69) { // emulate caps lock and num lock keydown and keyup 4983e230dd2SCorentin Chary kbd_put_keycode(keycode); 4993e230dd2SCorentin Chary kbd_put_keycode(keycode | 0x80); 50068c0aa6eSPeter Maydell } else if (qemu_console_is_graphic(NULL)) { 5013e230dd2SCorentin Chary if (keycode & 0x80) 5023e230dd2SCorentin Chary kbd_put_keycode(0xe0); 5033e230dd2SCorentin Chary if (modifiers_state[keycode] == 0) { // keydown 5043e230dd2SCorentin Chary kbd_put_keycode(keycode & 0x7f); 5053e230dd2SCorentin Chary modifiers_state[keycode] = 1; 5063e230dd2SCorentin Chary } else { // keyup 5073e230dd2SCorentin Chary kbd_put_keycode(keycode | 0x80); 5083e230dd2SCorentin Chary modifiers_state[keycode] = 0; 5093e230dd2SCorentin Chary } 5103e230dd2SCorentin Chary } 5113e230dd2SCorentin Chary } 5123e230dd2SCorentin Chary 5133e230dd2SCorentin Chary // release Mouse grab when pressing ctrl+alt 5143e230dd2SCorentin Chary if (!isFullscreen && ([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) { 5153e230dd2SCorentin Chary [self ungrabMouse]; 5163e230dd2SCorentin Chary } 5173e230dd2SCorentin Chary break; 5183e230dd2SCorentin Chary case NSKeyDown: 5193e230dd2SCorentin Chary 5203e230dd2SCorentin Chary // forward command Key Combos 5213e230dd2SCorentin Chary if ([event modifierFlags] & NSCommandKeyMask) { 5223e230dd2SCorentin Chary [NSApp sendEvent:event]; 5233e230dd2SCorentin Chary return; 5243e230dd2SCorentin Chary } 5253e230dd2SCorentin Chary 5263e230dd2SCorentin Chary // default 5273e230dd2SCorentin Chary keycode = cocoa_keycode_to_qemu([event keyCode]); 5283e230dd2SCorentin Chary 5293e230dd2SCorentin Chary // handle control + alt Key Combos (ctrl+alt is reserved for QEMU) 5303e230dd2SCorentin Chary if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) { 5313e230dd2SCorentin Chary switch (keycode) { 5323e230dd2SCorentin Chary 5333e230dd2SCorentin Chary // enable graphic console 5343e230dd2SCorentin Chary case 0x02 ... 0x0a: // '1' to '9' keys 5353e230dd2SCorentin Chary console_select(keycode - 0x02); 5363e230dd2SCorentin Chary break; 5373e230dd2SCorentin Chary } 5383e230dd2SCorentin Chary 5393e230dd2SCorentin Chary // handle keys for graphic console 54068c0aa6eSPeter Maydell } else if (qemu_console_is_graphic(NULL)) { 5413e230dd2SCorentin Chary if (keycode & 0x80) //check bit for e0 in front 5423e230dd2SCorentin Chary kbd_put_keycode(0xe0); 5433e230dd2SCorentin Chary kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front 5443e230dd2SCorentin Chary 5453e230dd2SCorentin Chary // handlekeys for Monitor 5463e230dd2SCorentin Chary } else { 5473e230dd2SCorentin Chary int keysym = 0; 5483e230dd2SCorentin Chary switch([event keyCode]) { 5493e230dd2SCorentin Chary case 115: 5503e230dd2SCorentin Chary keysym = QEMU_KEY_HOME; 5513e230dd2SCorentin Chary break; 5523e230dd2SCorentin Chary case 117: 5533e230dd2SCorentin Chary keysym = QEMU_KEY_DELETE; 5543e230dd2SCorentin Chary break; 5553e230dd2SCorentin Chary case 119: 5563e230dd2SCorentin Chary keysym = QEMU_KEY_END; 5573e230dd2SCorentin Chary break; 5583e230dd2SCorentin Chary case 123: 5593e230dd2SCorentin Chary keysym = QEMU_KEY_LEFT; 5603e230dd2SCorentin Chary break; 5613e230dd2SCorentin Chary case 124: 5623e230dd2SCorentin Chary keysym = QEMU_KEY_RIGHT; 5633e230dd2SCorentin Chary break; 5643e230dd2SCorentin Chary case 125: 5653e230dd2SCorentin Chary keysym = QEMU_KEY_DOWN; 5663e230dd2SCorentin Chary break; 5673e230dd2SCorentin Chary case 126: 5683e230dd2SCorentin Chary keysym = QEMU_KEY_UP; 5693e230dd2SCorentin Chary break; 5703e230dd2SCorentin Chary default: 5713e230dd2SCorentin Chary { 5723e230dd2SCorentin Chary NSString *ks = [event characters]; 5733e230dd2SCorentin Chary if ([ks length] > 0) 5743e230dd2SCorentin Chary keysym = [ks characterAtIndex:0]; 5753e230dd2SCorentin Chary } 5763e230dd2SCorentin Chary } 5773e230dd2SCorentin Chary if (keysym) 5783e230dd2SCorentin Chary kbd_put_keysym(keysym); 5793e230dd2SCorentin Chary } 5803e230dd2SCorentin Chary break; 5813e230dd2SCorentin Chary case NSKeyUp: 5823e230dd2SCorentin Chary keycode = cocoa_keycode_to_qemu([event keyCode]); 58368c0aa6eSPeter Maydell if (qemu_console_is_graphic(NULL)) { 5843e230dd2SCorentin Chary if (keycode & 0x80) 5853e230dd2SCorentin Chary kbd_put_keycode(0xe0); 5863e230dd2SCorentin Chary kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key 5873e230dd2SCorentin Chary } 5883e230dd2SCorentin Chary break; 5893e230dd2SCorentin Chary case NSMouseMoved: 5903e230dd2SCorentin Chary if (isAbsoluteEnabled) { 5913e230dd2SCorentin Chary if (p.x < 0 || p.x > screen.width || p.y < 0 || p.y > screen.height || ![[self window] isKeyWindow]) { 5923e230dd2SCorentin Chary if (isTabletEnabled) { // if we leave the window, deactivate the tablet 5933e230dd2SCorentin Chary [NSCursor unhide]; 5943e230dd2SCorentin Chary isTabletEnabled = FALSE; 5953e230dd2SCorentin Chary } 5963e230dd2SCorentin Chary } else { 5973e230dd2SCorentin Chary if (!isTabletEnabled) { // if we enter the window, activate the tablet 5983e230dd2SCorentin Chary [NSCursor hide]; 5993e230dd2SCorentin Chary isTabletEnabled = TRUE; 6003e230dd2SCorentin Chary } 6013e230dd2SCorentin Chary } 6023e230dd2SCorentin Chary } 6033e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6043e230dd2SCorentin Chary break; 6053e230dd2SCorentin Chary case NSLeftMouseDown: 6063e230dd2SCorentin Chary if ([event modifierFlags] & NSCommandKeyMask) { 6073e230dd2SCorentin Chary buttons |= MOUSE_EVENT_RBUTTON; 6083e230dd2SCorentin Chary } else { 6093e230dd2SCorentin Chary buttons |= MOUSE_EVENT_LBUTTON; 6103e230dd2SCorentin Chary } 6113e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6123e230dd2SCorentin Chary break; 6133e230dd2SCorentin Chary case NSRightMouseDown: 6143e230dd2SCorentin Chary buttons |= MOUSE_EVENT_RBUTTON; 6153e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6163e230dd2SCorentin Chary break; 6173e230dd2SCorentin Chary case NSOtherMouseDown: 6183e230dd2SCorentin Chary buttons |= MOUSE_EVENT_MBUTTON; 6193e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6203e230dd2SCorentin Chary break; 6213e230dd2SCorentin Chary case NSLeftMouseDragged: 6223e230dd2SCorentin Chary if ([event modifierFlags] & NSCommandKeyMask) { 6233e230dd2SCorentin Chary buttons |= MOUSE_EVENT_RBUTTON; 6243e230dd2SCorentin Chary } else { 6253e230dd2SCorentin Chary buttons |= MOUSE_EVENT_LBUTTON; 6263e230dd2SCorentin Chary } 6273e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6283e230dd2SCorentin Chary break; 6293e230dd2SCorentin Chary case NSRightMouseDragged: 6303e230dd2SCorentin Chary buttons |= MOUSE_EVENT_RBUTTON; 6313e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6323e230dd2SCorentin Chary break; 6333e230dd2SCorentin Chary case NSOtherMouseDragged: 6343e230dd2SCorentin Chary buttons |= MOUSE_EVENT_MBUTTON; 6353e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6363e230dd2SCorentin Chary break; 6373e230dd2SCorentin Chary case NSLeftMouseUp: 6383e230dd2SCorentin Chary if (isTabletEnabled) { 6393e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6403e230dd2SCorentin Chary } else if (!isMouseGrabed) { 6413e230dd2SCorentin Chary if (p.x > -1 && p.x < screen.width && p.y > -1 && p.y < screen.height) { 6423e230dd2SCorentin Chary [self grabMouse]; 6433e230dd2SCorentin Chary } else { 6443e230dd2SCorentin Chary [NSApp sendEvent:event]; 6453e230dd2SCorentin Chary } 6463e230dd2SCorentin Chary } else { 6473e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6483e230dd2SCorentin Chary } 6493e230dd2SCorentin Chary break; 6503e230dd2SCorentin Chary case NSRightMouseUp: 6513e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6523e230dd2SCorentin Chary break; 6533e230dd2SCorentin Chary case NSOtherMouseUp: 6543e230dd2SCorentin Chary COCOA_MOUSE_EVENT 6553e230dd2SCorentin Chary break; 6563e230dd2SCorentin Chary case NSScrollWheel: 6573e230dd2SCorentin Chary if (isTabletEnabled || isMouseGrabed) { 6583e230dd2SCorentin Chary kbd_mouse_event(0, 0, -[event deltaY], 0); 6593e230dd2SCorentin Chary } else { 6603e230dd2SCorentin Chary [NSApp sendEvent:event]; 6613e230dd2SCorentin Chary } 6623e230dd2SCorentin Chary break; 6633e230dd2SCorentin Chary default: 6643e230dd2SCorentin Chary [NSApp sendEvent:event]; 6653e230dd2SCorentin Chary } 6663e230dd2SCorentin Chary} 6673e230dd2SCorentin Chary 6683e230dd2SCorentin Chary- (void) grabMouse 6693e230dd2SCorentin Chary{ 6703e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: grabMouse\n"); 6713e230dd2SCorentin Chary 6723e230dd2SCorentin Chary if (!isFullscreen) { 6733e230dd2SCorentin Chary if (qemu_name) 6743e230dd2SCorentin Chary [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s - (Press ctrl + alt to release Mouse)", qemu_name]]; 6753e230dd2SCorentin Chary else 6763e230dd2SCorentin Chary [normalWindow setTitle:@"QEMU - (Press ctrl + alt to release Mouse)"]; 6773e230dd2SCorentin Chary } 6783e230dd2SCorentin Chary [NSCursor hide]; 6793e230dd2SCorentin Chary CGAssociateMouseAndMouseCursorPosition(FALSE); 6803e230dd2SCorentin Chary isMouseGrabed = TRUE; // while isMouseGrabed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:] 6813e230dd2SCorentin Chary} 6823e230dd2SCorentin Chary 6833e230dd2SCorentin Chary- (void) ungrabMouse 6843e230dd2SCorentin Chary{ 6853e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaView: ungrabMouse\n"); 6863e230dd2SCorentin Chary 6873e230dd2SCorentin Chary if (!isFullscreen) { 6883e230dd2SCorentin Chary if (qemu_name) 6893e230dd2SCorentin Chary [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]]; 6903e230dd2SCorentin Chary else 6913e230dd2SCorentin Chary [normalWindow setTitle:@"QEMU"]; 6923e230dd2SCorentin Chary } 6933e230dd2SCorentin Chary [NSCursor unhide]; 6943e230dd2SCorentin Chary CGAssociateMouseAndMouseCursorPosition(TRUE); 6953e230dd2SCorentin Chary isMouseGrabed = FALSE; 6963e230dd2SCorentin Chary} 6973e230dd2SCorentin Chary 6983e230dd2SCorentin Chary- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {isAbsoluteEnabled = tIsAbsoluteEnabled;} 6993e230dd2SCorentin Chary- (BOOL) isMouseGrabed {return isMouseGrabed;} 7003e230dd2SCorentin Chary- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;} 7013e230dd2SCorentin Chary- (float) cdx {return cdx;} 7023e230dd2SCorentin Chary- (float) cdy {return cdy;} 7033e230dd2SCorentin Chary- (QEMUScreen) gscreen {return screen;} 7043e230dd2SCorentin Chary@end 7053e230dd2SCorentin Chary 7063e230dd2SCorentin Chary 7073e230dd2SCorentin Chary 7083e230dd2SCorentin Chary/* 7093e230dd2SCorentin Chary ------------------------------------------------------ 7103e230dd2SCorentin Chary QemuCocoaAppController 7113e230dd2SCorentin Chary ------------------------------------------------------ 7123e230dd2SCorentin Chary*/ 7133e230dd2SCorentin Chary@interface QemuCocoaAppController : NSObject 7143e230dd2SCorentin Chary{ 7153e230dd2SCorentin Chary} 7163e230dd2SCorentin Chary- (void)startEmulationWithArgc:(int)argc argv:(char**)argv; 7173e230dd2SCorentin Chary- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; 7183e230dd2SCorentin Chary- (void)toggleFullScreen:(id)sender; 7193e230dd2SCorentin Chary- (void)showQEMUDoc:(id)sender; 7203e230dd2SCorentin Chary- (void)showQEMUTec:(id)sender; 7213e230dd2SCorentin Chary@end 7223e230dd2SCorentin Chary 7233e230dd2SCorentin Chary@implementation QemuCocoaAppController 7243e230dd2SCorentin Chary- (id) init 7253e230dd2SCorentin Chary{ 7263e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: init\n"); 7273e230dd2SCorentin Chary 7283e230dd2SCorentin Chary self = [super init]; 7293e230dd2SCorentin Chary if (self) { 7303e230dd2SCorentin Chary 7313e230dd2SCorentin Chary // create a view and add it to the window 7323e230dd2SCorentin Chary cocoaView = [[QemuCocoaView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 640.0, 480.0)]; 7333e230dd2SCorentin Chary if(!cocoaView) { 7343e230dd2SCorentin Chary fprintf(stderr, "(cocoa) can't create a view\n"); 7353e230dd2SCorentin Chary exit(1); 7363e230dd2SCorentin Chary } 7373e230dd2SCorentin Chary 7383e230dd2SCorentin Chary // create a window 7393e230dd2SCorentin Chary normalWindow = [[NSWindow alloc] initWithContentRect:[cocoaView frame] 7403e230dd2SCorentin Chary styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask 7413e230dd2SCorentin Chary backing:NSBackingStoreBuffered defer:NO]; 7423e230dd2SCorentin Chary if(!normalWindow) { 7433e230dd2SCorentin Chary fprintf(stderr, "(cocoa) can't create window\n"); 7443e230dd2SCorentin Chary exit(1); 7453e230dd2SCorentin Chary } 7463e230dd2SCorentin Chary [normalWindow setAcceptsMouseMovedEvents:YES]; 7473e230dd2SCorentin Chary [normalWindow setTitle:[NSString stringWithFormat:@"QEMU"]]; 7483e230dd2SCorentin Chary [normalWindow setContentView:cocoaView]; 7493e230dd2SCorentin Chary [normalWindow useOptimizedDrawing:YES]; 7503e230dd2SCorentin Chary [normalWindow makeKeyAndOrderFront:self]; 7513e230dd2SCorentin Chary [normalWindow center]; 7523e230dd2SCorentin Chary 7533e230dd2SCorentin Chary } 7543e230dd2SCorentin Chary return self; 7553e230dd2SCorentin Chary} 7563e230dd2SCorentin Chary 7573e230dd2SCorentin Chary- (void) dealloc 7583e230dd2SCorentin Chary{ 7593e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: dealloc\n"); 7603e230dd2SCorentin Chary 7613e230dd2SCorentin Chary if (cocoaView) 7623e230dd2SCorentin Chary [cocoaView release]; 7633e230dd2SCorentin Chary [super dealloc]; 7643e230dd2SCorentin Chary} 7653e230dd2SCorentin Chary 7663e230dd2SCorentin Chary- (void)applicationDidFinishLaunching: (NSNotification *) note 7673e230dd2SCorentin Chary{ 7683e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n"); 7693e230dd2SCorentin Chary 7703e230dd2SCorentin Chary // Display an open dialog box if no argument were passed or 7713e230dd2SCorentin Chary // if qemu was launched from the finder ( the Finder passes "-psn" ) 7723e230dd2SCorentin Chary if( gArgc <= 1 || strncmp ((char *)gArgv[1], "-psn", 4) == 0) { 7733e230dd2SCorentin Chary NSOpenPanel *op = [[NSOpenPanel alloc] init]; 7743e230dd2SCorentin Chary [op setPrompt:@"Boot image"]; 7753e230dd2SCorentin Chary [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; 7762ba9de6eSPeter Maydell NSArray *filetypes = [NSArray arrayWithObjects:@"img", @"iso", @"dmg", 7772ba9de6eSPeter Maydell @"qcow", @"cow", @"cloop", @"vmdk", nil]; 7782ba9de6eSPeter Maydell#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) 7792ba9de6eSPeter Maydell [op setAllowedFileTypes:filetypes]; 7802ba9de6eSPeter Maydell [op beginSheetModalForWindow:normalWindow 7812ba9de6eSPeter Maydell completionHandler:^(NSInteger returnCode) 7822ba9de6eSPeter Maydell { [self openPanelDidEnd:op 7832ba9de6eSPeter Maydell returnCode:returnCode contextInfo:NULL ]; } ]; 7842ba9de6eSPeter Maydell#else 7852ba9de6eSPeter Maydell // Compatibility code for pre-10.6, using deprecated method 7862ba9de6eSPeter Maydell [op beginSheetForDirectory:nil file:nil types:filetypes 7873e230dd2SCorentin Chary modalForWindow:normalWindow modalDelegate:self 7883e230dd2SCorentin Chary didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; 7892ba9de6eSPeter Maydell#endif 7903e230dd2SCorentin Chary } else { 7915cbdb3a3SStefan Weil // or launch QEMU, with the global args 7923e230dd2SCorentin Chary [self startEmulationWithArgc:gArgc argv:(char **)gArgv]; 7933e230dd2SCorentin Chary } 7943e230dd2SCorentin Chary} 7953e230dd2SCorentin Chary 7963e230dd2SCorentin Chary- (void)applicationWillTerminate:(NSNotification *)aNotification 7973e230dd2SCorentin Chary{ 7983e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n"); 7993e230dd2SCorentin Chary 8003e230dd2SCorentin Chary qemu_system_shutdown_request(); 8013e230dd2SCorentin Chary exit(0); 8023e230dd2SCorentin Chary} 8033e230dd2SCorentin Chary 8043e230dd2SCorentin Chary- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication 8053e230dd2SCorentin Chary{ 8063e230dd2SCorentin Chary return YES; 8073e230dd2SCorentin Chary} 8083e230dd2SCorentin Chary 8093e230dd2SCorentin Chary- (void)startEmulationWithArgc:(int)argc argv:(char**)argv 8103e230dd2SCorentin Chary{ 8113e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: startEmulationWithArgc\n"); 8123e230dd2SCorentin Chary 8133e230dd2SCorentin Chary int status; 8143bbbee18SAndreas Färber status = qemu_main(argc, argv, *_NSGetEnviron()); 8153e230dd2SCorentin Chary exit(status); 8163e230dd2SCorentin Chary} 8173e230dd2SCorentin Chary 8183e230dd2SCorentin Chary- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo 8193e230dd2SCorentin Chary{ 8203e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: openPanelDidEnd\n"); 8213e230dd2SCorentin Chary 8223e230dd2SCorentin Chary if(returnCode == NSCancelButton) { 8233e230dd2SCorentin Chary exit(0); 8243e230dd2SCorentin Chary } else if(returnCode == NSOKButton) { 8253e230dd2SCorentin Chary const char *bin = "qemu"; 8268bb3f1e3SPeter Maydell char *img = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding]; 8273e230dd2SCorentin Chary 8283e230dd2SCorentin Chary char **argv = (char**)malloc( sizeof(char*)*3 ); 8293e230dd2SCorentin Chary 83013766eb1SAndreas Färber [sheet close]; 83113766eb1SAndreas Färber 8327e02dc63SStefan Weil argv[0] = g_strdup_printf("%s", bin); 8337e02dc63SStefan Weil argv[1] = g_strdup_printf("-hda"); 8347e02dc63SStefan Weil argv[2] = g_strdup_printf("%s", img); 8353e230dd2SCorentin Chary 8363e230dd2SCorentin Chary printf("Using argc %d argv %s -hda %s\n", 3, bin, img); 8373e230dd2SCorentin Chary 8383e230dd2SCorentin Chary [self startEmulationWithArgc:3 argv:(char**)argv]; 8393e230dd2SCorentin Chary } 8403e230dd2SCorentin Chary} 8413e230dd2SCorentin Chary- (void)toggleFullScreen:(id)sender 8423e230dd2SCorentin Chary{ 8433e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: toggleFullScreen\n"); 8443e230dd2SCorentin Chary 8453e230dd2SCorentin Chary [cocoaView toggleFullScreen:sender]; 8463e230dd2SCorentin Chary} 8473e230dd2SCorentin Chary 8483e230dd2SCorentin Chary- (void)showQEMUDoc:(id)sender 8493e230dd2SCorentin Chary{ 8503e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: showQEMUDoc\n"); 8513e230dd2SCorentin Chary 8523e230dd2SCorentin Chary [[NSWorkspace sharedWorkspace] openFile:[NSString stringWithFormat:@"%@/../doc/qemu/qemu-doc.html", 8533e230dd2SCorentin Chary [[NSBundle mainBundle] resourcePath]] withApplication:@"Help Viewer"]; 8543e230dd2SCorentin Chary} 8553e230dd2SCorentin Chary 8563e230dd2SCorentin Chary- (void)showQEMUTec:(id)sender 8573e230dd2SCorentin Chary{ 8583e230dd2SCorentin Chary COCOA_DEBUG("QemuCocoaAppController: showQEMUTec\n"); 8593e230dd2SCorentin Chary 8603e230dd2SCorentin Chary [[NSWorkspace sharedWorkspace] openFile:[NSString stringWithFormat:@"%@/../doc/qemu/qemu-tech.html", 8613e230dd2SCorentin Chary [[NSBundle mainBundle] resourcePath]] withApplication:@"Help Viewer"]; 8623e230dd2SCorentin Chary} 8633e230dd2SCorentin Chary@end 8643e230dd2SCorentin Chary 8653e230dd2SCorentin Chary 8663e230dd2SCorentin Chary 8673e230dd2SCorentin Charyint main (int argc, const char * argv[]) { 8683e230dd2SCorentin Chary 8693e230dd2SCorentin Chary gArgc = argc; 8703e230dd2SCorentin Chary gArgv = (char **)argv; 8713e230dd2SCorentin Chary int i; 8723e230dd2SCorentin Chary 8733e230dd2SCorentin Chary /* In case we don't need to display a window, let's not do that */ 8743e230dd2SCorentin Chary for (i = 1; i < argc; i++) { 875e4ebcc1aSTristan Gingold const char *opt = argv[i]; 876e4ebcc1aSTristan Gingold 877e4ebcc1aSTristan Gingold if (opt[0] == '-') { 878e4ebcc1aSTristan Gingold /* Treat --foo the same as -foo. */ 879e4ebcc1aSTristan Gingold if (opt[1] == '-') { 880e4ebcc1aSTristan Gingold opt++; 881e4ebcc1aSTristan Gingold } 8829851484fSAlexandre Raymond if (!strcmp(opt, "-h") || !strcmp(opt, "-help") || 8839851484fSAlexandre Raymond !strcmp(opt, "-vnc") || 884e4ebcc1aSTristan Gingold !strcmp(opt, "-nographic") || 885e4ebcc1aSTristan Gingold !strcmp(opt, "-version") || 88660b46aa2SAndreas Färber !strcmp(opt, "-curses") || 88760b46aa2SAndreas Färber !strcmp(opt, "-qtest")) { 8883bbbee18SAndreas Färber return qemu_main(gArgc, gArgv, *_NSGetEnviron()); 8893e230dd2SCorentin Chary } 8903e230dd2SCorentin Chary } 891e4ebcc1aSTristan Gingold } 8923e230dd2SCorentin Chary 8933e230dd2SCorentin Chary NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 8943e230dd2SCorentin Chary 89542a5dfe7SPeter Maydell // Pull this console process up to being a fully-fledged graphical 89642a5dfe7SPeter Maydell // app with a menubar and Dock icon 89742a5dfe7SPeter Maydell ProcessSerialNumber psn = { 0, kCurrentProcess }; 89842a5dfe7SPeter Maydell TransformProcessType(&psn, kProcessTransformToForegroundApplication); 89942a5dfe7SPeter Maydell 9003e230dd2SCorentin Chary [NSApplication sharedApplication]; 9013e230dd2SCorentin Chary 9023e230dd2SCorentin Chary // Add menus 9033e230dd2SCorentin Chary NSMenu *menu; 9043e230dd2SCorentin Chary NSMenuItem *menuItem; 9053e230dd2SCorentin Chary 9063e230dd2SCorentin Chary [NSApp setMainMenu:[[NSMenu alloc] init]]; 9073e230dd2SCorentin Chary 9083e230dd2SCorentin Chary // Application menu 9093e230dd2SCorentin Chary menu = [[NSMenu alloc] initWithTitle:@""]; 9103e230dd2SCorentin Chary [menu addItemWithTitle:@"About QEMU" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; // About QEMU 9113e230dd2SCorentin Chary [menu addItem:[NSMenuItem separatorItem]]; //Separator 9123e230dd2SCorentin Chary [menu addItemWithTitle:@"Hide QEMU" action:@selector(hide:) keyEquivalent:@"h"]; //Hide QEMU 9133e230dd2SCorentin Chary menuItem = (NSMenuItem *)[menu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; // Hide Others 9143e230dd2SCorentin Chary [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; 9153e230dd2SCorentin Chary [menu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; // Show All 9163e230dd2SCorentin Chary [menu addItem:[NSMenuItem separatorItem]]; //Separator 9173e230dd2SCorentin Chary [menu addItemWithTitle:@"Quit QEMU" action:@selector(terminate:) keyEquivalent:@"q"]; 9183e230dd2SCorentin Chary menuItem = [[NSMenuItem alloc] initWithTitle:@"Apple" action:nil keyEquivalent:@""]; 9193e230dd2SCorentin Chary [menuItem setSubmenu:menu]; 9203e230dd2SCorentin Chary [[NSApp mainMenu] addItem:menuItem]; 9213e230dd2SCorentin Chary [NSApp performSelector:@selector(setAppleMenu:) withObject:menu]; // Workaround (this method is private since 10.4+) 9223e230dd2SCorentin Chary 9233e230dd2SCorentin Chary // View menu 9243e230dd2SCorentin Chary menu = [[NSMenu alloc] initWithTitle:@"View"]; 9253e230dd2SCorentin Chary [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter Fullscreen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"] autorelease]]; // Fullscreen 9263e230dd2SCorentin Chary menuItem = [[[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""] autorelease]; 9273e230dd2SCorentin Chary [menuItem setSubmenu:menu]; 9283e230dd2SCorentin Chary [[NSApp mainMenu] addItem:menuItem]; 9293e230dd2SCorentin Chary 9303e230dd2SCorentin Chary // Window menu 9313e230dd2SCorentin Chary menu = [[NSMenu alloc] initWithTitle:@"Window"]; 9323e230dd2SCorentin Chary [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"] autorelease]]; // Miniaturize 9333e230dd2SCorentin Chary menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease]; 9343e230dd2SCorentin Chary [menuItem setSubmenu:menu]; 9353e230dd2SCorentin Chary [[NSApp mainMenu] addItem:menuItem]; 9363e230dd2SCorentin Chary [NSApp setWindowsMenu:menu]; 9373e230dd2SCorentin Chary 9383e230dd2SCorentin Chary // Help menu 9393e230dd2SCorentin Chary menu = [[NSMenu alloc] initWithTitle:@"Help"]; 9403e230dd2SCorentin Chary [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU Documentation" action:@selector(showQEMUDoc:) keyEquivalent:@"?"] autorelease]]; // QEMU Help 9413e230dd2SCorentin Chary [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU Technology" action:@selector(showQEMUTec:) keyEquivalent:@""] autorelease]]; // QEMU Help 9423e230dd2SCorentin Chary menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease]; 9433e230dd2SCorentin Chary [menuItem setSubmenu:menu]; 9443e230dd2SCorentin Chary [[NSApp mainMenu] addItem:menuItem]; 9453e230dd2SCorentin Chary 9463e230dd2SCorentin Chary // Create an Application controller 9473e230dd2SCorentin Chary QemuCocoaAppController *appController = [[QemuCocoaAppController alloc] init]; 9483e230dd2SCorentin Chary [NSApp setDelegate:appController]; 9493e230dd2SCorentin Chary 9503e230dd2SCorentin Chary // Start the main event loop 9513e230dd2SCorentin Chary [NSApp run]; 9523e230dd2SCorentin Chary 9533e230dd2SCorentin Chary [appController release]; 9543e230dd2SCorentin Chary [pool release]; 9553e230dd2SCorentin Chary 9563e230dd2SCorentin Chary return 0; 9573e230dd2SCorentin Chary} 9583e230dd2SCorentin Chary 9593e230dd2SCorentin Chary 9603e230dd2SCorentin Chary 9613e230dd2SCorentin Chary#pragma mark qemu 9627c20b4a3SGerd Hoffmannstatic void cocoa_update(DisplayChangeListener *dcl, 9637c20b4a3SGerd Hoffmann int x, int y, int w, int h) 9643e230dd2SCorentin Chary{ 9656e657e64SPeter Maydell NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 9666e657e64SPeter Maydell 9673e230dd2SCorentin Chary COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); 9683e230dd2SCorentin Chary 9693e230dd2SCorentin Chary NSRect rect; 9703e230dd2SCorentin Chary if ([cocoaView cdx] == 1.0) { 9713e230dd2SCorentin Chary rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h); 9723e230dd2SCorentin Chary } else { 9733e230dd2SCorentin Chary rect = NSMakeRect( 9743e230dd2SCorentin Chary x * [cocoaView cdx], 9753e230dd2SCorentin Chary ([cocoaView gscreen].height - y - h) * [cocoaView cdy], 9763e230dd2SCorentin Chary w * [cocoaView cdx], 9773e230dd2SCorentin Chary h * [cocoaView cdy]); 9783e230dd2SCorentin Chary } 9793e230dd2SCorentin Chary [cocoaView setNeedsDisplayInRect:rect]; 9806e657e64SPeter Maydell 9816e657e64SPeter Maydell [pool release]; 9823e230dd2SCorentin Chary} 9833e230dd2SCorentin Chary 984c12aeb86SGerd Hoffmannstatic void cocoa_switch(DisplayChangeListener *dcl, 985c12aeb86SGerd Hoffmann DisplaySurface *surface) 9863e230dd2SCorentin Chary{ 9876e657e64SPeter Maydell NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 9883e230dd2SCorentin Chary 9896e657e64SPeter Maydell COCOA_DEBUG("qemu_cocoa: cocoa_switch\n"); 9905e00d3acSGerd Hoffmann [cocoaView switchSurface:surface]; 9916e657e64SPeter Maydell [pool release]; 9923e230dd2SCorentin Chary} 9933e230dd2SCorentin Chary 994bc2ed970SGerd Hoffmannstatic void cocoa_refresh(DisplayChangeListener *dcl) 9953e230dd2SCorentin Chary{ 9966e657e64SPeter Maydell NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 9976e657e64SPeter Maydell 9983e230dd2SCorentin Chary COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n"); 9993e230dd2SCorentin Chary 10003e230dd2SCorentin Chary if (kbd_mouse_is_absolute()) { 10013e230dd2SCorentin Chary if (![cocoaView isAbsoluteEnabled]) { 10023e230dd2SCorentin Chary if ([cocoaView isMouseGrabed]) { 10033e230dd2SCorentin Chary [cocoaView ungrabMouse]; 10043e230dd2SCorentin Chary } 10053e230dd2SCorentin Chary } 10063e230dd2SCorentin Chary [cocoaView setAbsoluteEnabled:YES]; 10073e230dd2SCorentin Chary } 10083e230dd2SCorentin Chary 10093e230dd2SCorentin Chary NSDate *distantPast; 10103e230dd2SCorentin Chary NSEvent *event; 10113e230dd2SCorentin Chary distantPast = [NSDate distantPast]; 10123e230dd2SCorentin Chary do { 10133e230dd2SCorentin Chary event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast 10143e230dd2SCorentin Chary inMode: NSDefaultRunLoopMode dequeue:YES]; 10153e230dd2SCorentin Chary if (event != nil) { 10163e230dd2SCorentin Chary [cocoaView handleEvent:event]; 10173e230dd2SCorentin Chary } 10183e230dd2SCorentin Chary } while(event != nil); 101968c0aa6eSPeter Maydell graphic_hw_update(NULL); 10206e657e64SPeter Maydell [pool release]; 10213e230dd2SCorentin Chary} 10223e230dd2SCorentin Chary 10233e230dd2SCorentin Charystatic void cocoa_cleanup(void) 10243e230dd2SCorentin Chary{ 10253e230dd2SCorentin Chary COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n"); 102658a06675SBlue Swirl g_free(dcl); 10273e230dd2SCorentin Chary} 10283e230dd2SCorentin Chary 10297c20b4a3SGerd Hoffmannstatic const DisplayChangeListenerOps dcl_ops = { 10307c20b4a3SGerd Hoffmann .dpy_name = "cocoa", 10318510d91eSPeter Maydell .dpy_gfx_update = cocoa_update, 10328510d91eSPeter Maydell .dpy_gfx_switch = cocoa_switch, 10338510d91eSPeter Maydell .dpy_refresh = cocoa_refresh, 10347c20b4a3SGerd Hoffmann}; 10357c20b4a3SGerd Hoffmann 10363e230dd2SCorentin Charyvoid cocoa_display_init(DisplayState *ds, int full_screen) 10373e230dd2SCorentin Chary{ 10383e230dd2SCorentin Chary COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n"); 10393e230dd2SCorentin Chary 104058a06675SBlue Swirl dcl = g_malloc0(sizeof(DisplayChangeListener)); 10413e230dd2SCorentin Chary 10423e230dd2SCorentin Chary // register vga output callbacks 10437c20b4a3SGerd Hoffmann dcl->ops = &dcl_ops; 10445209089fSGerd Hoffmann register_displaychangelistener(dcl); 10453e230dd2SCorentin Chary 10463e230dd2SCorentin Chary // register cleanup function 10473e230dd2SCorentin Chary atexit(cocoa_cleanup); 10483e230dd2SCorentin Chary} 1049