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, 3 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

# Content
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