ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/EmulatorView.mm
Revision: 1.1
Committed: 2002-03-16T04:00:18Z (22 years, 8 months ago) by nigel
Branch: MAIN
Log Message:
Initial revision of Mac OS X port code. Uses Objective-C++. Needs Mac OS 10.1

File Contents

# User Rev Content
1 nigel 1.1 /*
2     * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3     *
4     * $Id$
5     *
6     * Basilisk II (C) 1997-2002 Christian Bauer
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23     #import "sysdeps.h" // Types used in Basilisk C++ code,
24    
25     #define DEBUG 0
26     #import <debug.h>
27    
28     #import <Cocoa/Cocoa.h>
29    
30     #import "main_macosx.h" // For WarningAlert() et al prototypes
31     #import "misc_macosx.h" // For InfoSheet() prototype
32     #import "video_macosx.h" // For init_* globals, and bitmap drawing strategy
33    
34     #import "EmulatorView.h"
35    
36     @implementation EmulatorView
37    
38    
39     //
40     // Standard NSView methods that we override
41     //
42    
43     - (id) initWithFrame: (NSRect) frameRect
44     {
45     self = [super initWithFrame: frameRect];
46    
47     output = self; // Set global for access by Basilisk C++ code
48     // bitmap = nil; // Set by readyToDraw:
49     drawView = NO; // Disable drawing until later
50    
51     #ifdef SAVE_GSTATE
52     [self allocateGState];
53     #endif
54    
55     return self;
56     }
57    
58     - (void) dealloc
59     {
60     #ifdef SAVE_GSTATE
61     [self releaseGState];
62     #endif
63     [super dealloc];
64     }
65    
66     // Mouse click in this window. If window is not active, should click be passed to this view?
67     - (BOOL) acceptsFirstMouse: (NSEvent *) event
68     {
69     return [self mouseInView];
70     }
71    
72     /*****
73     - (BOOL) acceptsFirstResponder
74     {
75     // return YES;
76     return [self mouseInView];
77     }
78     *****/
79    
80     #include <adb.h>
81    
82     static int prevFlags;
83    
84     - (void) flagsChanged: (NSEvent *) event
85     {
86     int flags = [event modifierFlags];
87    
88     if ( (flags & NSAlphaShiftKeyMask) != (prevFlags & NSAlphaShiftKeyMask) )
89     if ( flags & NSAlphaShiftKeyMask )
90     ADBKeyDown(0x39); // CAPS_LOCK
91     else
92     ADBKeyUp(0x39);
93    
94     if ( (flags & NSShiftKeyMask) != (prevFlags & NSShiftKeyMask) )
95     if ( flags & NSShiftKeyMask )
96     ADBKeyDown(0x38); // SHIFT_LEFT
97     else
98     ADBKeyUp(0x38);
99    
100     if ( (flags & NSControlKeyMask) != (prevFlags & NSControlKeyMask) )
101     if ( flags & NSControlKeyMask )
102     ADBKeyDown(0x36); // CTL_LEFT
103     else
104     ADBKeyUp(0x36);
105    
106     if ( (flags & NSAlternateKeyMask) != (prevFlags & NSAlternateKeyMask) )
107     if ( flags & NSAlternateKeyMask )
108     ADBKeyDown(0x3a); // OPTION_LEFT
109     else
110     ADBKeyUp(0x3a);
111    
112     if ( (flags & NSCommandKeyMask) != (prevFlags & NSCommandKeyMask) )
113     if ( flags & NSCommandKeyMask )
114     ADBKeyDown(0x37); // APPLE_LEFT
115     else
116     ADBKeyUp(0x37);
117    
118     prevFlags = flags;
119     }
120    
121     - (BOOL) mouseInView: (NSEvent *) event
122     {
123     NSPoint loc = [event locationInWindow];
124     NSRect box = [self frame];
125     D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f",
126     __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y));
127     return [self mouse: loc inRect: box];
128     }
129    
130     - (BOOL) mouseInView
131     {
132     NSPoint loc = [[self window] mouseLocationOutsideOfEventStream];
133     NSRect box = [self frame];
134     D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f",
135     __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y));
136     return [self mouse: loc inRect: box];
137     }
138    
139    
140     //
141     // Custom methods
142     //
143    
144     - (void) benchmark
145     {
146     int i;
147     float seconds;
148     NSDate *startDate;
149    
150     if ( ! drawView )
151     return;
152    
153     drawView = NO;
154     [self lockFocus];
155     startDate = [NSDate date];
156     for (i = 1; i < 300; ++i )
157     #ifdef NSBITMAP
158     [bitmap draw];
159     #endif
160     #ifdef CGIMAGEREF
161     cgDrawInto([self bounds], bitmap);
162     #endif
163     #ifdef CGDRAWBITMAP
164     [self CGDrawBitmap];
165     #endif
166     seconds = -[startDate timeIntervalSinceNow];
167     [self unlockFocus];
168     drawView = YES;
169    
170     InfoSheet(@"Benchmark run. 300 frames.",
171     [NSString stringWithFormat:
172     @"%.2f seconds, %.3f frames per second", seconds, i/seconds],
173     @"Thanks", [self window]);
174     }
175    
176     // Return a TIFF for a snapshot of the screen image
177     - (NSData *) TIFFrep
178     {
179     #ifdef NSBITMAP
180     return [bitmap TIFFRepresentation];
181     #else
182     WarningAlert("How do I get a TIFF from a CGImageRef?");
183     #endif
184     return nil;
185     }
186    
187     // Enable display of, and drawing into, the view
188     #ifdef NSBITMAP
189     - (void) readyToDraw: (NSBitmapImageRep *) theBitmap
190     imageWidth: (short) width
191     imageHeight: (short) height
192     {
193     bitmap = theBitmap;
194     #endif
195     #ifdef CGIMAGEREF
196     - (void) readyToDraw: (CGImageRef) image
197     imageWidth: (short) width
198     imageHeight: (short) height
199     {
200     bitmap = image;
201     #endif
202     #ifdef CGDRAWBITMAP
203     - (void) readyToDraw: (void *) theBitmap
204     width: (short) width
205     height: (short) height
206     bps: (short) bitsPerSample
207     spp: (short) samplesPerPixel
208     bpp: (short) bitsPerPixel
209     bpr: (int) bpr
210     isPlanar: (BOOL) planar
211     hasAlpha: (BOOL) alpha
212     {
213     bitmap = theBitmap;
214     bps = bitsPerSample;
215     spp = samplesPerPixel;
216     bpp = bitsPerPixel;
217     bytesPerRow = bpr;
218     isPlanar = planar;
219     hasAlpha = alpha;
220     #endif
221     x = width, y = height;
222     drawView = YES;
223    
224     [[self window] setAcceptsMouseMovedEvents: YES];
225     // [[self window] setInitialFirstResponder: self];
226     [[self window] makeFirstResponder: self];
227     }
228    
229     - (void) disableDrawing
230     {
231     drawView = NO;
232     }
233    
234     - (short) width
235     {
236     return (short)[self bounds].size.width;
237     }
238    
239     - (short) height
240     {
241     return (short)[self bounds].size.height;
242     }
243    
244     - (BOOL) isOpaque
245     {
246     return drawView;
247     }
248    
249     - (BOOL) processKeyEvent: (NSEvent *) event
250     {
251     if ( [self acceptsFirstMouse: event] || FULLSCREEN )
252     if ( [event isARepeat] )
253     return NO;
254     else
255     return YES;
256    
257     [self interpretKeyEvents:[NSArray arrayWithObject:event]];
258     return NO;
259     }
260    
261     - (void) keyDown: (NSEvent *) event
262     {
263     if ( [self processKeyEvent: event] )
264     ADBKeyDown([event keyCode]);
265     }
266    
267     - (void) keyUp: (NSEvent *) event
268     {
269     if ( [self processKeyEvent: event] )
270     ADBKeyUp([event keyCode]);
271     }
272    
273     static NSPoint mouse; // Previous/current mouse location
274    
275     - (BOOL) processMouseMove: (NSEvent *) event
276     {
277     NSPoint locInView;
278    
279     if ( FULLSCREEN )
280     locInView = [NSEvent mouseLocation];
281     else
282     locInView = [self convertPoint: [event locationInWindow] fromView:nil];
283    
284     if ( NSEqualPoints(locInView, mouse) )
285     return NO;
286    
287     mouse = locInView;
288    
289     if ( FULLSCREEN )
290     {
291     ADBMouseMoved((int)mouse.x, screen_height - (int)mouse.y);
292     return YES;
293     }
294    
295     #ifdef CAN_RESIZE_VIEW
296     int mouseY = y - y * mouse.y / [self height];
297     int mouseX = x * mouse.x / [self width];
298     #else
299     int mouseY = y - (int) mouse.y;
300     int mouseX = (int) mouse.x;
301     #endif
302    
303     ADBMouseMoved(mouseX, mouseY);
304     return YES;
305     }
306    
307     - (void) mouseDown: (NSEvent *) event
308     {
309     [self processMouseMove: event];
310     ADBMouseDown(0);
311     }
312    
313     - (void) mouseDragged: (NSEvent *) event
314     {
315     [self processMouseMove: event];
316     }
317    
318     - (void) mouseMoved: (NSEvent *) event
319     {
320     #if DEBUG
321     if ( ! [self mouseInView] )
322     {
323     NSLog (@"%s - Received event while outside of view", __PRETTY_FUNCTION__);
324     return;
325     }
326     #endif
327     [self processMouseMove: event];
328     }
329    
330     - (void) mouseUp: (NSEvent *) event
331     {
332     [self processMouseMove: event];
333     ADBMouseUp(0);
334     }
335    
336     #if DEBUG
337     - (void) randomise // Draw some coloured snow in the bitmap
338     {
339     unsigned char *pixel;
340    
341     for ( int i = 0; i < 1000; ++i )
342     {
343     pixel = [bitmap bitmapData]
344     + (int) (1.0 * [bitmap bytesPerRow] * 342 //[bitmap height]
345     * rand() / RAND_MAX);
346     *pixel = (unsigned char) (256.0 * rand() / RAND_MAX);
347     }
348     }
349     #endif
350    
351     - (void) drawRect: (NSRect) rect
352     {
353     if ( ! drawView ) // If the emulator is still being setup,
354     return; // we do not want to draw
355    
356     #if DEBUG
357     NSLog(@"In drawRect");
358     [self randomise];
359     #endif
360    
361     #ifdef NSBITMAP
362     NSRectClip(rect);
363     [bitmap draw];
364     #endif
365     #ifdef CGIMAGEREF
366     cgDrawInto(rect, bitmap);
367     #endif
368     #ifdef CGDRAWBITMAP
369     [self CGDrawBitmap];
370     #endif
371     }
372    
373     //
374     // Extra drawing stuff
375     //
376    
377     #ifdef CGDRAWBITMAP
378     extern "C" void CGDrawBitmap();
379    
380     - (void) CGDrawBitmap
381     {
382     CGContextRef cgContext = [[NSGraphicsContext currentContext]
383     graphicsPort];
384     NSRect rect = [self bounds];
385     CGRect cgRect = {
386     {rect.origin.x, rect.origin.y},
387     {rect.size.width, rect.size.height}
388     };
389    
390     CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
391    
392    
393     CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
394    
395     CGDrawBitmap(cgContext, cgRect, x, y, bps, spp, bpp,
396     bytesPerRow, isPlanar, hasAlpha, colourSpace, &bitmap);
397     }
398     #endif
399    
400     #ifdef CGIMAGEREF
401     void
402     cgDrawInto(NSRect rect, CGImageRef bitmap)
403     {
404     CGContextRef cgContext = [[NSGraphicsContext currentContext]
405     graphicsPort];
406     CGRect cgRect = {
407     {rect.origin.x, rect.origin.y},
408     {rect.size.width, rect.size.height}
409     };
410    
411     CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
412    
413     CGContextDrawImage(cgContext, cgRect, bitmap);
414     }
415     #endif
416    
417     @end