ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/EmulatorView.mm
Revision: 1.2
Committed: 2002-03-18T11:00:27Z (22 years, 2 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-10
Changes since 1.1: +21 -3 lines
Log Message:
Extra code to map cursor keys

File Contents

# Content
1 /*
2 * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3 *
4 * $Id: EmulatorView.mm,v 1.2 2002/03/16 10:00:19 nigel Exp $
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 {
265 int code = [event keyCode];
266
267 if ( code == 126 ) code = 0x3e; // CURS_UP
268 if ( code == 125 ) code = 0x3d; // CURS_DOWN
269 if ( code == 124 ) code = 0x3c; // CURS_RIGHT
270 if ( code == 123 ) code = 0x3b; // CURS_LEFT
271
272 ADBKeyDown(code);
273 }
274 }
275
276 - (void) keyUp: (NSEvent *) event
277 {
278 if ( [self processKeyEvent: event] )
279 {
280 int code = [event keyCode];
281
282 if ( code == 126 ) code = 0x3e; // CURS_UP
283 if ( code == 125 ) code = 0x3d; // CURS_DOWN
284 if ( code == 124 ) code = 0x3c; // CURS_RIGHT
285 if ( code == 123 ) code = 0x3b; // CURS_LEFT
286
287 ADBKeyUp(code);
288 }
289 }
290
291 static NSPoint mouse; // Previous/current mouse location
292
293 - (BOOL) processMouseMove: (NSEvent *) event
294 {
295 NSPoint locInView;
296
297 if ( FULLSCREEN )
298 locInView = [NSEvent mouseLocation];
299 else
300 locInView = [self convertPoint: [event locationInWindow] fromView:nil];
301
302 if ( NSEqualPoints(locInView, mouse) )
303 return NO;
304
305 mouse = locInView;
306
307 if ( FULLSCREEN )
308 {
309 ADBMouseMoved((int)mouse.x, screen_height - (int)mouse.y);
310 return YES;
311 }
312
313 #ifdef CAN_RESIZE_VIEW
314 int mouseY = y - y * mouse.y / [self height];
315 int mouseX = x * mouse.x / [self width];
316 #else
317 int mouseY = y - (int) mouse.y;
318 int mouseX = (int) mouse.x;
319 #endif
320
321 ADBMouseMoved(mouseX, mouseY);
322 return YES;
323 }
324
325 - (void) mouseDown: (NSEvent *) event
326 {
327 [self processMouseMove: event];
328 ADBMouseDown(0);
329 }
330
331 - (void) mouseDragged: (NSEvent *) event
332 {
333 [self processMouseMove: event];
334 }
335
336 - (void) mouseMoved: (NSEvent *) event
337 {
338 #if DEBUG
339 if ( ! [self mouseInView] )
340 {
341 NSLog (@"%s - Received event while outside of view", __PRETTY_FUNCTION__);
342 return;
343 }
344 #endif
345 [self processMouseMove: event];
346 }
347
348 - (void) mouseUp: (NSEvent *) event
349 {
350 [self processMouseMove: event];
351 ADBMouseUp(0);
352 }
353
354 #if DEBUG
355 - (void) randomise // Draw some coloured snow in the bitmap
356 {
357 unsigned char *pixel;
358
359 for ( int i = 0; i < 1000; ++i )
360 {
361 pixel = [bitmap bitmapData]
362 + (int) (1.0 * [bitmap bytesPerRow] * 342 //[bitmap height]
363 * rand() / RAND_MAX);
364 *pixel = (unsigned char) (256.0 * rand() / RAND_MAX);
365 }
366 }
367 #endif
368
369 - (void) drawRect: (NSRect) rect
370 {
371 if ( ! drawView ) // If the emulator is still being setup,
372 return; // we do not want to draw
373
374 #if DEBUG
375 NSLog(@"In drawRect");
376 [self randomise];
377 #endif
378
379 #ifdef NSBITMAP
380 NSRectClip(rect);
381 [bitmap draw];
382 #endif
383 #ifdef CGIMAGEREF
384 cgDrawInto(rect, bitmap);
385 #endif
386 #ifdef CGDRAWBITMAP
387 [self CGDrawBitmap];
388 #endif
389 }
390
391 //
392 // Extra drawing stuff
393 //
394
395 #ifdef CGDRAWBITMAP
396 extern "C" void CGDrawBitmap();
397
398 - (void) CGDrawBitmap
399 {
400 CGContextRef cgContext = [[NSGraphicsContext currentContext]
401 graphicsPort];
402 NSRect rect = [self bounds];
403 CGRect cgRect = {
404 {rect.origin.x, rect.origin.y},
405 {rect.size.width, rect.size.height}
406 };
407
408 CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
409
410
411 CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
412
413 CGDrawBitmap(cgContext, cgRect, x, y, bps, spp, bpp,
414 bytesPerRow, isPlanar, hasAlpha, colourSpace, &bitmap);
415 }
416 #endif
417
418 #ifdef CGIMAGEREF
419 void
420 cgDrawInto(NSRect rect, CGImageRef bitmap)
421 {
422 CGContextRef cgContext = [[NSGraphicsContext currentContext]
423 graphicsPort];
424 CGRect cgRect = {
425 {rect.origin.x, rect.origin.y},
426 {rect.size.width, rect.size.height}
427 };
428
429 CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
430
431 CGContextDrawImage(cgContext, cgRect, bitmap);
432 }
433 #endif
434
435 @end