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(&current_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