Statistics
| Branch: | Revision:

root / cocoa.m @ 43fb823b

History | View | Annotate | Download (17 kB)

1 5b0753e0 bellard
/*
2 5b0753e0 bellard
 * QEMU Cocoa display driver
3 5b0753e0 bellard
 * 
4 5b0753e0 bellard
 * Copyright (c) 2005 Pierre d'Herbemont
5 5b0753e0 bellard
 *                    many code/inspiration from SDL 1.2 code (LGPL)
6 5b0753e0 bellard
 * 
7 5b0753e0 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 5b0753e0 bellard
 * of this software and associated documentation files (the "Software"), to deal
9 5b0753e0 bellard
 * in the Software without restriction, including without limitation the rights
10 5b0753e0 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 5b0753e0 bellard
 * copies of the Software, and to permit persons to whom the Software is
12 5b0753e0 bellard
 * furnished to do so, subject to the following conditions:
13 5b0753e0 bellard
 *
14 5b0753e0 bellard
 * The above copyright notice and this permission notice shall be included in
15 5b0753e0 bellard
 * all copies or substantial portions of the Software.
16 5b0753e0 bellard
 *
17 5b0753e0 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 5b0753e0 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 5b0753e0 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 5b0753e0 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 5b0753e0 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 5b0753e0 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 5b0753e0 bellard
 * THE SOFTWARE.
24 5b0753e0 bellard
 */
25 5b0753e0 bellard
/*
26 5b0753e0 bellard
    Todo :    x  miniaturize window 
27 5b0753e0 bellard
              x  center the window
28 5b0753e0 bellard
              -  save window position
29 5b0753e0 bellard
              -  handle keyboard event
30 5b0753e0 bellard
              -  handle mouse event
31 5b0753e0 bellard
              -  non 32 bpp support
32 5b0753e0 bellard
              -  full screen
33 5b0753e0 bellard
              -  mouse focus
34 5b0753e0 bellard
              x  simple graphical prompt to demo
35 5b0753e0 bellard
              -  better graphical prompt
36 5b0753e0 bellard
*/
37 da4dbf74 bellard
38 5b0753e0 bellard
#import <Cocoa/Cocoa.h>
39 5b0753e0 bellard
40 da4dbf74 bellard
#include "vl.h"
41 da4dbf74 bellard
42 5b0753e0 bellard
NSWindow *window = NULL;
43 5b0753e0 bellard
NSQuickDrawView *qd_view = NULL;
44 5b0753e0 bellard
45 5b0753e0 bellard
46 5b0753e0 bellard
int gArgc;
47 5b0753e0 bellard
char **gArgv;
48 5b0753e0 bellard
DisplayState current_ds;
49 5b0753e0 bellard
50 5b0753e0 bellard
/* main defined in qemu/vl.c */
51 5b0753e0 bellard
int qemu_main(int argc, char **argv);
52 5b0753e0 bellard
53 5b0753e0 bellard
/* To deal with miniaturization */
54 5b0753e0 bellard
@interface QemuWindow : NSWindow
55 5b0753e0 bellard
{ }
56 5b0753e0 bellard
@end
57 5b0753e0 bellard
58 5b0753e0 bellard
59 5b0753e0 bellard
/*
60 5b0753e0 bellard
 ------------------------------------------------------
61 5b0753e0 bellard
    Qemu Video Driver
62 5b0753e0 bellard
 ------------------------------------------------------
63 5b0753e0 bellard
*/
64 5b0753e0 bellard
65 5b0753e0 bellard
/*
66 5b0753e0 bellard
 ------------------------------------------------------
67 5b0753e0 bellard
    cocoa_update
68 5b0753e0 bellard
 ------------------------------------------------------
69 5b0753e0 bellard
*/
70 5b0753e0 bellard
static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
71 5b0753e0 bellard
{
72 5b0753e0 bellard
    //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
73 5b0753e0 bellard
74 5b0753e0 bellard
    /* Use QDFlushPortBuffer() to flush content to display */
75 5b0753e0 bellard
    RgnHandle dirty = NewRgn ();
76 5b0753e0 bellard
    RgnHandle temp  = NewRgn ();
77 5b0753e0 bellard
78 5b0753e0 bellard
    SetEmptyRgn (dirty);
79 5b0753e0 bellard
80 5b0753e0 bellard
    /* Build the region of dirty rectangles */
81 5b0753e0 bellard
    MacSetRectRgn (temp, x, y,
82 5b0753e0 bellard
                        x + w, y + h);
83 5b0753e0 bellard
    MacUnionRgn (dirty, temp, dirty);
84 5b0753e0 bellard
                
85 5b0753e0 bellard
    /* Flush the dirty region */
86 5b0753e0 bellard
    QDFlushPortBuffer ( [ qd_view  qdPort ], dirty );
87 5b0753e0 bellard
    DisposeRgn (dirty);
88 5b0753e0 bellard
    DisposeRgn (temp);
89 5b0753e0 bellard
}
90 5b0753e0 bellard
91 5b0753e0 bellard
/*
92 5b0753e0 bellard
 ------------------------------------------------------
93 5b0753e0 bellard
    cocoa_resize
94 5b0753e0 bellard
 ------------------------------------------------------
95 5b0753e0 bellard
*/
96 5b0753e0 bellard
static void cocoa_resize(DisplayState *ds, int w, int h)
97 5b0753e0 bellard
{
98 5b0753e0 bellard
    const int device_bpp = 32;
99 5b0753e0 bellard
    static void *screen_pixels;
100 5b0753e0 bellard
    static int  screen_pitch;
101 5b0753e0 bellard
    NSRect contentRect;
102 5b0753e0 bellard
    
103 5b0753e0 bellard
    //printf("resizing to %d %d\n", w, h);
104 5b0753e0 bellard
    
105 5b0753e0 bellard
    contentRect = NSMakeRect (0, 0, w, h);
106 5b0753e0 bellard
    if(window)
107 5b0753e0 bellard
    {
108 5b0753e0 bellard
        [window close];
109 5b0753e0 bellard
        [window release];
110 5b0753e0 bellard
    }
111 5b0753e0 bellard
    window = [ [ QemuWindow alloc ] initWithContentRect:contentRect
112 5b0753e0 bellard
                                  styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask
113 5b0753e0 bellard
                                  backing:NSBackingStoreBuffered defer:NO];
114 5b0753e0 bellard
    if(!window)
115 5b0753e0 bellard
    {
116 5b0753e0 bellard
        fprintf(stderr, "(cocoa) can't create window\n");
117 5b0753e0 bellard
        exit(1);
118 5b0753e0 bellard
    }
119 5b0753e0 bellard
    
120 5b0753e0 bellard
    if(qd_view)
121 5b0753e0 bellard
        [qd_view release];
122 5b0753e0 bellard
    
123 5b0753e0 bellard
    qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
124 5b0753e0 bellard
    
125 5b0753e0 bellard
    if(!qd_view)
126 5b0753e0 bellard
    {
127 5b0753e0 bellard
         fprintf(stderr, "(cocoa) can't create qd_view\n");
128 5b0753e0 bellard
        exit(1);
129 5b0753e0 bellard
    }
130 5b0753e0 bellard
    
131 5b0753e0 bellard
    [ window setAcceptsMouseMovedEvents:YES ];
132 5b0753e0 bellard
    [ window setTitle:@"Qemu" ];
133 5b0753e0 bellard
    [ window setReleasedWhenClosed:NO ];
134 5b0753e0 bellard
    
135 5b0753e0 bellard
    /* Set screen to black */
136 5b0753e0 bellard
    [ window setBackgroundColor: [NSColor blackColor] ];
137 5b0753e0 bellard
    
138 5b0753e0 bellard
    /* set window position */
139 5b0753e0 bellard
    [ window center ];
140 5b0753e0 bellard
    
141 5b0753e0 bellard
    [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
142 5b0753e0 bellard
    [ [ window contentView ] addSubview:qd_view ];
143 5b0753e0 bellard
    [ qd_view release ];
144 5b0753e0 bellard
    [ window makeKeyAndOrderFront:nil ];
145 5b0753e0 bellard
    
146 5b0753e0 bellard
    /* Careful here, the window seems to have to be onscreen to do that */
147 5b0753e0 bellard
    LockPortBits ( [ qd_view qdPort ] );
148 5b0753e0 bellard
    screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) );
149 5b0753e0 bellard
    screen_pitch  = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) );
150 5b0753e0 bellard
    UnlockPortBits ( [ qd_view qdPort ] );
151 5b0753e0 bellard
    { 
152 5b0753e0 bellard
            int vOffset = [ window frame ].size.height - 
153 5b0753e0 bellard
                [ qd_view frame ].size.height - [ qd_view frame ].origin.y;
154 5b0753e0 bellard
            
155 5b0753e0 bellard
            int hOffset = [ qd_view frame ].origin.x;
156 5b0753e0 bellard
                    
157 5b0753e0 bellard
            screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8);
158 5b0753e0 bellard
    }
159 5b0753e0 bellard
    ds->data = screen_pixels;
160 5b0753e0 bellard
    ds->linesize = screen_pitch;
161 5b0753e0 bellard
    ds->depth = device_bpp;
162 5b0753e0 bellard
    ds->width = w;
163 5b0753e0 bellard
    ds->height = h;
164 5b0753e0 bellard
    
165 5b0753e0 bellard
    current_ds = *ds;
166 5b0753e0 bellard
}
167 5b0753e0 bellard
168 5b0753e0 bellard
/*
169 5b0753e0 bellard
 ------------------------------------------------------
170 5b0753e0 bellard
    keymap conversion
171 5b0753e0 bellard
 ------------------------------------------------------
172 5b0753e0 bellard
*/
173 5b0753e0 bellard
174 5b0753e0 bellard
static int keymap[] =
175 5b0753e0 bellard
{
176 5b0753e0 bellard
    30, //'a' 0x0
177 5b0753e0 bellard
    31,  //'s'
178 5b0753e0 bellard
    32,  //'d'
179 5b0753e0 bellard
    33,  //'f'
180 5b0753e0 bellard
    35,  //'h'
181 5b0753e0 bellard
    34,  //'g'
182 5b0753e0 bellard
    44,  //'z'
183 5b0753e0 bellard
    45,  //'x'
184 5b0753e0 bellard
    46,  //'c'
185 5b0753e0 bellard
    47,  //'v'
186 5b0753e0 bellard
    0,   // 0  0x0a
187 5b0753e0 bellard
    48,  //'b'
188 5b0753e0 bellard
    16,  //'q'
189 5b0753e0 bellard
    17,  //'w'
190 5b0753e0 bellard
    18,  //'e'
191 5b0753e0 bellard
    19,  //'r' 
192 5b0753e0 bellard
    21,  //'y' 0x10
193 5b0753e0 bellard
    20,  //'t'
194 5b0753e0 bellard
    2,  //'1'
195 5b0753e0 bellard
    3,  //'2'
196 5b0753e0 bellard
    4,  //'3'
197 5b0753e0 bellard
    5,  //'4'
198 5b0753e0 bellard
    7,  //'6'
199 5b0753e0 bellard
    6,  //'5'
200 5b0753e0 bellard
    0,  //'='
201 5b0753e0 bellard
    10,  //'9'
202 5b0753e0 bellard
    8,  //'7' 0x1A
203 5b0753e0 bellard
    0,  //'-' 
204 5b0753e0 bellard
    9,  //'8' 
205 5b0753e0 bellard
    11,  //'0' 
206 5b0753e0 bellard
    27,  //']' 
207 5b0753e0 bellard
    24,  //'o' 
208 5b0753e0 bellard
    22,  //'u' 0x20
209 5b0753e0 bellard
    26,  //'['
210 5b0753e0 bellard
    23,  //'i'
211 5b0753e0 bellard
    25,  //'p'
212 5b0753e0 bellard
    28,  //'\n'
213 5b0753e0 bellard
    38,  //'l'
214 5b0753e0 bellard
    36,  //'j'
215 5b0753e0 bellard
    40,  //'"'
216 5b0753e0 bellard
    37,  //'k'
217 5b0753e0 bellard
    39,  //';'
218 5b0753e0 bellard
    15,  //'\t' 0x30
219 5b0753e0 bellard
    0,  //' '
220 5b0753e0 bellard
    0,  //'`'
221 5b0753e0 bellard
    14,  //'<backspace>'
222 5b0753e0 bellard
    0,  //'' 0x34
223 5b0753e0 bellard
    0,  //'<esc>'
224 5b0753e0 bellard
    0,  //'<esc>'
225 5b0753e0 bellard
    /* Not completed to finish see http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */
226 5b0753e0 bellard
};
227 5b0753e0 bellard
228 5b0753e0 bellard
static int cocoa_keycode_to_qemu(int keycode)
229 5b0753e0 bellard
{
230 5b0753e0 bellard
    if(sizeof(keymap) <= keycode)
231 5b0753e0 bellard
    {
232 5b0753e0 bellard
        printf("(cocoa) warning unknow keycode 0x%x\n", keycode);
233 5b0753e0 bellard
        return 0;
234 5b0753e0 bellard
    }
235 5b0753e0 bellard
    return keymap[keycode];
236 5b0753e0 bellard
}
237 5b0753e0 bellard
238 5b0753e0 bellard
/*
239 5b0753e0 bellard
 ------------------------------------------------------
240 5b0753e0 bellard
    cocoa_refresh
241 5b0753e0 bellard
 ------------------------------------------------------
242 5b0753e0 bellard
*/
243 5b0753e0 bellard
static void cocoa_refresh(DisplayState *ds)
244 5b0753e0 bellard
{
245 5b0753e0 bellard
    //printf("cocoa_refresh \n");
246 5b0753e0 bellard
    NSDate *distantPast;
247 5b0753e0 bellard
    NSEvent *event;
248 5b0753e0 bellard
    NSAutoreleasePool *pool;
249 5b0753e0 bellard
    int grab = 1;
250 5b0753e0 bellard
    
251 5b0753e0 bellard
    pool = [ [ NSAutoreleasePool alloc ] init ];
252 5b0753e0 bellard
    distantPast = [ NSDate distantPast ];
253 5b0753e0 bellard
    
254 5b0753e0 bellard
    if (is_active_console(vga_console)) 
255 5b0753e0 bellard
        vga_update_display();
256 5b0753e0 bellard
    do {
257 5b0753e0 bellard
        event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
258 5b0753e0 bellard
                        inMode: NSDefaultRunLoopMode dequeue:YES ];
259 5b0753e0 bellard
        if (event != nil) {
260 5b0753e0 bellard
            switch ([event type]) {
261 5b0753e0 bellard
                case NSKeyDown:
262 5b0753e0 bellard
                    if(grab)
263 5b0753e0 bellard
                    {
264 5b0753e0 bellard
                        int keycode = cocoa_keycode_to_qemu([event keyCode]);
265 5b0753e0 bellard
                        
266 5b0753e0 bellard
                        if (keycode & 0x80)
267 5b0753e0 bellard
                            kbd_put_keycode(0xe0);
268 5b0753e0 bellard
                        kbd_put_keycode(keycode & 0x7f);
269 5b0753e0 bellard
                    }
270 5b0753e0 bellard
                    break;
271 5b0753e0 bellard
                case NSKeyUp:
272 5b0753e0 bellard
                    if(grab)
273 5b0753e0 bellard
                    {
274 5b0753e0 bellard
                        int keycode = cocoa_keycode_to_qemu([event keyCode]);
275 5b0753e0 bellard
276 5b0753e0 bellard
                        if (keycode & 0x80)
277 5b0753e0 bellard
                            kbd_put_keycode(0xe0);
278 5b0753e0 bellard
                        kbd_put_keycode(keycode | 0x80);
279 5b0753e0 bellard
                    }
280 5b0753e0 bellard
                    break;
281 5b0753e0 bellard
                case NSScrollWheel:
282 5b0753e0 bellard
                
283 5b0753e0 bellard
                case NSLeftMouseDown:
284 5b0753e0 bellard
                case NSLeftMouseUp:
285 5b0753e0 bellard
                
286 5b0753e0 bellard
                case NSOtherMouseDown:
287 5b0753e0 bellard
                case NSRightMouseDown:
288 5b0753e0 bellard
                
289 5b0753e0 bellard
                case NSOtherMouseUp:
290 5b0753e0 bellard
                case NSRightMouseUp:
291 5b0753e0 bellard
                
292 5b0753e0 bellard
                case NSMouseMoved:
293 5b0753e0 bellard
                case NSOtherMouseDragged:
294 5b0753e0 bellard
                case NSRightMouseDragged:
295 5b0753e0 bellard
                case NSLeftMouseDragged:
296 5b0753e0 bellard
                
297 5b0753e0 bellard
                default: [NSApp sendEvent:event];
298 5b0753e0 bellard
            }
299 5b0753e0 bellard
        }
300 5b0753e0 bellard
    } while(event != nil);
301 5b0753e0 bellard
}
302 5b0753e0 bellard
303 5b0753e0 bellard
/*
304 5b0753e0 bellard
 ------------------------------------------------------
305 5b0753e0 bellard
    cocoa_cleanup
306 5b0753e0 bellard
 ------------------------------------------------------
307 5b0753e0 bellard
*/
308 5b0753e0 bellard
309 5b0753e0 bellard
static void cocoa_cleanup(void) 
310 5b0753e0 bellard
{
311 5b0753e0 bellard
312 5b0753e0 bellard
}
313 5b0753e0 bellard
314 5b0753e0 bellard
/*
315 5b0753e0 bellard
 ------------------------------------------------------
316 5b0753e0 bellard
    cocoa_display_init
317 5b0753e0 bellard
 ------------------------------------------------------
318 5b0753e0 bellard
*/
319 5b0753e0 bellard
320 5b0753e0 bellard
void cocoa_display_init(DisplayState *ds, int full_screen)
321 5b0753e0 bellard
{
322 5b0753e0 bellard
    ds->dpy_update = cocoa_update;
323 5b0753e0 bellard
    ds->dpy_resize = cocoa_resize;
324 5b0753e0 bellard
    ds->dpy_refresh = cocoa_refresh;
325 5b0753e0 bellard
    
326 5b0753e0 bellard
    cocoa_resize(ds, 640, 400);
327 5b0753e0 bellard
    
328 5b0753e0 bellard
    atexit(cocoa_cleanup);
329 5b0753e0 bellard
}
330 5b0753e0 bellard
331 5b0753e0 bellard
/*
332 5b0753e0 bellard
 ------------------------------------------------------
333 5b0753e0 bellard
    Interface with Cocoa
334 5b0753e0 bellard
 ------------------------------------------------------
335 5b0753e0 bellard
*/
336 5b0753e0 bellard
337 5b0753e0 bellard
338 5b0753e0 bellard
/*
339 5b0753e0 bellard
 ------------------------------------------------------
340 5b0753e0 bellard
    QemuWindow
341 5b0753e0 bellard
    Some trick from SDL to use miniwindow
342 5b0753e0 bellard
 ------------------------------------------------------
343 5b0753e0 bellard
*/
344 5b0753e0 bellard
static void QZ_SetPortAlphaOpaque ()
345 5b0753e0 bellard
{    
346 5b0753e0 bellard
    /* Assume 32 bit if( bpp == 32 )*/
347 5b0753e0 bellard
    if ( 1 ) {
348 5b0753e0 bellard
    
349 5b0753e0 bellard
        uint32_t    *pixels = (uint32_t*) current_ds.data;
350 5b0753e0 bellard
        uint32_t    rowPixels = current_ds.linesize / 4;
351 5b0753e0 bellard
        uint32_t    i, j;
352 5b0753e0 bellard
        
353 5b0753e0 bellard
        for (i = 0; i < current_ds.height; i++)
354 5b0753e0 bellard
            for (j = 0; j < current_ds.width; j++) {
355 5b0753e0 bellard
        
356 5b0753e0 bellard
                pixels[ (i * rowPixels) + j ] |= 0xFF000000;
357 5b0753e0 bellard
            }
358 5b0753e0 bellard
    }
359 5b0753e0 bellard
}
360 5b0753e0 bellard
361 5b0753e0 bellard
@implementation QemuWindow
362 5b0753e0 bellard
- (void)miniaturize:(id)sender
363 5b0753e0 bellard
{
364 5b0753e0 bellard
        
365 5b0753e0 bellard
    /* make the alpha channel opaque so anim won't have holes in it */
366 5b0753e0 bellard
    QZ_SetPortAlphaOpaque ();
367 5b0753e0 bellard
    
368 5b0753e0 bellard
    [ super miniaturize:sender ];
369 5b0753e0 bellard
    
370 5b0753e0 bellard
}
371 5b0753e0 bellard
- (void)display
372 5b0753e0 bellard
{    
373 5b0753e0 bellard
    /* 
374 5b0753e0 bellard
        This method fires just before the window deminaturizes from the Dock.
375 5b0753e0 bellard
        
376 5b0753e0 bellard
        We'll save the current visible surface, let the window manager redraw any
377 5b0753e0 bellard
        UI elements, and restore the SDL surface. This way, no expose event 
378 5b0753e0 bellard
        is required, and the deminiaturize works perfectly.
379 5b0753e0 bellard
    */
380 5b0753e0 bellard
    
381 5b0753e0 bellard
    /* make sure pixels are fully opaque */
382 5b0753e0 bellard
    QZ_SetPortAlphaOpaque ();
383 5b0753e0 bellard
    
384 5b0753e0 bellard
    /* save current visible SDL surface */
385 5b0753e0 bellard
    [ self cacheImageInRect:[ qd_view frame ] ];
386 5b0753e0 bellard
    
387 5b0753e0 bellard
    /* let the window manager redraw controls, border, etc */
388 5b0753e0 bellard
    [ super display ];
389 5b0753e0 bellard
    
390 5b0753e0 bellard
    /* restore visible SDL surface */
391 5b0753e0 bellard
    [ self restoreCachedImage ];
392 5b0753e0 bellard
}
393 5b0753e0 bellard
394 5b0753e0 bellard
@end
395 5b0753e0 bellard
396 5b0753e0 bellard
397 5b0753e0 bellard
/*
398 5b0753e0 bellard
 ------------------------------------------------------
399 5b0753e0 bellard
    QemuCocoaGUIController
400 5b0753e0 bellard
    NSApp's delegate - indeed main object
401 5b0753e0 bellard
 ------------------------------------------------------
402 5b0753e0 bellard
*/
403 5b0753e0 bellard
404 5b0753e0 bellard
@interface QemuCocoaGUIController : NSObject
405 5b0753e0 bellard
{
406 5b0753e0 bellard
}
407 5b0753e0 bellard
- (void)applicationDidFinishLaunching: (NSNotification *) note;
408 5b0753e0 bellard
- (void)applicationWillTerminate:(NSNotification *)aNotification;
409 5b0753e0 bellard
410 5b0753e0 bellard
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
411 5b0753e0 bellard
412 5b0753e0 bellard
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
413 5b0753e0 bellard
@end
414 5b0753e0 bellard
415 5b0753e0 bellard
@implementation QemuCocoaGUIController
416 5b0753e0 bellard
/* Called when the internal event loop has just started running */
417 5b0753e0 bellard
- (void)applicationDidFinishLaunching: (NSNotification *) note
418 5b0753e0 bellard
{
419 5a246934 bellard
420 5a246934 bellard
    /* Display an open dialog box if no argument were passed or
421 5a246934 bellard
       if qemu was launched from the finder ( the Finder passes "-psn" ) */
422 5a246934 bellard
423 5a246934 bellard
    if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0)
424 5b0753e0 bellard
    {
425 5b0753e0 bellard
        NSOpenPanel *op = [[NSOpenPanel alloc] init];
426 5b0753e0 bellard
        
427 5b0753e0 bellard
        cocoa_resize(&current_ds, 640, 400);
428 5b0753e0 bellard
        
429 5b0753e0 bellard
        [op setPrompt:@"Boot image"];
430 5b0753e0 bellard
        
431 5b0753e0 bellard
        [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
432 5b0753e0 bellard
        
433 7a674b13 bellard
        [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
434 5b0753e0 bellard
              modalForWindow:window modalDelegate:self
435 5b0753e0 bellard
              didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
436 5b0753e0 bellard
    }
437 5a246934 bellard
    else
438 5a246934 bellard
    {
439 5a246934 bellard
        /* or Launch Qemu, with the global args */
440 5a246934 bellard
        [self startEmulationWithArgc:gArgc argv:gArgv];
441 5a246934 bellard
    }
442 5b0753e0 bellard
}
443 5b0753e0 bellard
444 5b0753e0 bellard
- (void)applicationWillTerminate:(NSNotification *)aNotification
445 5b0753e0 bellard
{
446 5b0753e0 bellard
    printf("Application will terminate\n");
447 5b0753e0 bellard
    qemu_system_shutdown_request();
448 5b0753e0 bellard
    /* In order to avoid a crash */
449 5b0753e0 bellard
    exit(0);
450 5b0753e0 bellard
}
451 5b0753e0 bellard
452 5b0753e0 bellard
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
453 5b0753e0 bellard
{
454 5b0753e0 bellard
    if(returnCode == NSCancelButton)
455 5b0753e0 bellard
    {
456 5b0753e0 bellard
        exit(0);
457 5b0753e0 bellard
    }
458 5b0753e0 bellard
    
459 5b0753e0 bellard
    if(returnCode == NSOKButton)
460 5b0753e0 bellard
    {
461 5b0753e0 bellard
        char *bin = "qemu";
462 5b0753e0 bellard
        char *img = (char*)[ [ sheet filename ] cString];
463 5b0753e0 bellard
        
464 5b0753e0 bellard
        char **argv = (char**)malloc( sizeof(char*)*3 );
465 5b0753e0 bellard
        
466 5b0753e0 bellard
        asprintf(&argv[0], "%s", bin);
467 5b0753e0 bellard
        asprintf(&argv[1], "-hda");
468 5b0753e0 bellard
        asprintf(&argv[2], "%s", img);
469 5b0753e0 bellard
        
470 5b0753e0 bellard
        printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
471 5b0753e0 bellard
        
472 5b0753e0 bellard
        [self startEmulationWithArgc:3 argv:(char**)argv];
473 5b0753e0 bellard
    }
474 5b0753e0 bellard
}
475 5b0753e0 bellard
476 5b0753e0 bellard
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv
477 5b0753e0 bellard
{
478 5b0753e0 bellard
    int status;
479 5b0753e0 bellard
    /* Launch Qemu */
480 5b0753e0 bellard
    printf("starting qemu...\n");
481 5b0753e0 bellard
    status = qemu_main (argc, argv);
482 5b0753e0 bellard
    exit(status);
483 5b0753e0 bellard
}
484 5b0753e0 bellard
@end
485 5b0753e0 bellard
486 5b0753e0 bellard
/*
487 5b0753e0 bellard
 ------------------------------------------------------
488 5b0753e0 bellard
    Application Creation
489 5b0753e0 bellard
 ------------------------------------------------------
490 5b0753e0 bellard
*/
491 5b0753e0 bellard
492 5b0753e0 bellard
/* Dock Connection */
493 5b0753e0 bellard
typedef struct CPSProcessSerNum
494 5b0753e0 bellard
{
495 5b0753e0 bellard
        UInt32                lo;
496 5b0753e0 bellard
        UInt32                hi;
497 5b0753e0 bellard
} CPSProcessSerNum;
498 5b0753e0 bellard
499 5b0753e0 bellard
extern OSErr    CPSGetCurrentProcess( CPSProcessSerNum *psn);
500 5b0753e0 bellard
extern OSErr    CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
501 5b0753e0 bellard
extern OSErr    CPSSetFrontProcess( CPSProcessSerNum *psn);
502 5b0753e0 bellard
503 5b0753e0 bellard
/* Menu Creation */
504 5b0753e0 bellard
static void setApplicationMenu(void)
505 5b0753e0 bellard
{
506 5b0753e0 bellard
    /* warning: this code is very odd */
507 5b0753e0 bellard
    NSMenu *appleMenu;
508 5b0753e0 bellard
    NSMenuItem *menuItem;
509 5b0753e0 bellard
    NSString *title;
510 5b0753e0 bellard
    NSString *appName;
511 5b0753e0 bellard
    
512 5b0753e0 bellard
    appName = @"Qemu";
513 5b0753e0 bellard
    appleMenu = [[NSMenu alloc] initWithTitle:@""];
514 5b0753e0 bellard
    
515 5b0753e0 bellard
    /* Add menu items */
516 5b0753e0 bellard
    title = [@"About " stringByAppendingString:appName];
517 5b0753e0 bellard
    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
518 5b0753e0 bellard
519 5b0753e0 bellard
    [appleMenu addItem:[NSMenuItem separatorItem]];
520 5b0753e0 bellard
521 5b0753e0 bellard
    title = [@"Hide " stringByAppendingString:appName];
522 5b0753e0 bellard
    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
523 5b0753e0 bellard
524 5b0753e0 bellard
    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
525 5b0753e0 bellard
    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
526 5b0753e0 bellard
527 5b0753e0 bellard
    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
528 5b0753e0 bellard
529 5b0753e0 bellard
    [appleMenu addItem:[NSMenuItem separatorItem]];
530 5b0753e0 bellard
531 5b0753e0 bellard
    title = [@"Quit " stringByAppendingString:appName];
532 5b0753e0 bellard
    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
533 5b0753e0 bellard
534 5b0753e0 bellard
    
535 5b0753e0 bellard
    /* Put menu into the menubar */
536 5b0753e0 bellard
    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
537 5b0753e0 bellard
    [menuItem setSubmenu:appleMenu];
538 5b0753e0 bellard
    [[NSApp mainMenu] addItem:menuItem];
539 5b0753e0 bellard
540 5b0753e0 bellard
    /* Tell the application object that this is now the application menu */
541 5b0753e0 bellard
    [NSApp setAppleMenu:appleMenu];
542 5b0753e0 bellard
543 5b0753e0 bellard
    /* Finally give up our references to the objects */
544 5b0753e0 bellard
    [appleMenu release];
545 5b0753e0 bellard
    [menuItem release];
546 5b0753e0 bellard
}
547 5b0753e0 bellard
548 5b0753e0 bellard
/* Create a window menu */
549 5b0753e0 bellard
static void setupWindowMenu(void)
550 5b0753e0 bellard
{
551 5b0753e0 bellard
    NSMenu      *windowMenu;
552 5b0753e0 bellard
    NSMenuItem  *windowMenuItem;
553 5b0753e0 bellard
    NSMenuItem  *menuItem;
554 5b0753e0 bellard
555 5b0753e0 bellard
    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
556 5b0753e0 bellard
    
557 5b0753e0 bellard
    /* "Minimize" item */
558 5b0753e0 bellard
    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
559 5b0753e0 bellard
    [windowMenu addItem:menuItem];
560 5b0753e0 bellard
    [menuItem release];
561 5b0753e0 bellard
    
562 5b0753e0 bellard
    /* Put menu into the menubar */
563 5b0753e0 bellard
    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
564 5b0753e0 bellard
    [windowMenuItem setSubmenu:windowMenu];
565 5b0753e0 bellard
    [[NSApp mainMenu] addItem:windowMenuItem];
566 5b0753e0 bellard
    
567 5b0753e0 bellard
    /* Tell the application object that this is now the window menu */
568 5b0753e0 bellard
    [NSApp setWindowsMenu:windowMenu];
569 5b0753e0 bellard
570 5b0753e0 bellard
    /* Finally give up our references to the objects */
571 5b0753e0 bellard
    [windowMenu release];
572 5b0753e0 bellard
    [windowMenuItem release];
573 5b0753e0 bellard
 
574 5b0753e0 bellard
}
575 5b0753e0 bellard
576 5b0753e0 bellard
static void CustomApplicationMain (argc, argv)
577 5b0753e0 bellard
{
578 5b0753e0 bellard
    NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
579 5b0753e0 bellard
    QemuCocoaGUIController *gui_controller;
580 5b0753e0 bellard
    CPSProcessSerNum PSN;
581 5b0753e0 bellard
    
582 5b0753e0 bellard
    [NSApplication sharedApplication];
583 5b0753e0 bellard
    
584 5b0753e0 bellard
    if (!CPSGetCurrentProcess(&PSN))
585 5b0753e0 bellard
        if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
586 5b0753e0 bellard
            if (!CPSSetFrontProcess(&PSN))
587 5b0753e0 bellard
                [NSApplication sharedApplication];
588 5b0753e0 bellard
                
589 5b0753e0 bellard
    /* Set up the menubar */
590 5b0753e0 bellard
    [NSApp setMainMenu:[[NSMenu alloc] init]];
591 5b0753e0 bellard
    setApplicationMenu();
592 5b0753e0 bellard
    setupWindowMenu();
593 5b0753e0 bellard
594 5b0753e0 bellard
    /* Create SDLMain and make it the app delegate */
595 5b0753e0 bellard
    gui_controller = [[QemuCocoaGUIController alloc] init];
596 5b0753e0 bellard
    [NSApp setDelegate:gui_controller];
597 5b0753e0 bellard
    
598 5b0753e0 bellard
    /* Start the main event loop */
599 5b0753e0 bellard
    [NSApp run];
600 5b0753e0 bellard
    
601 5b0753e0 bellard
    [gui_controller release];
602 5b0753e0 bellard
    [pool release];
603 5b0753e0 bellard
}
604 5b0753e0 bellard
605 5b0753e0 bellard
/* Real main of qemu-cocoa */
606 5b0753e0 bellard
int main(int argc, char **argv)
607 5b0753e0 bellard
{
608 5b0753e0 bellard
    gArgc = argc;
609 5b0753e0 bellard
    gArgv = argv;
610 5b0753e0 bellard
    
611 5b0753e0 bellard
    CustomApplicationMain (argc, argv);
612 5b0753e0 bellard
    
613 5b0753e0 bellard
    return 0;
614 5b0753e0 bellard
}