ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/EmulatorView.mm
Revision: 1.4
Committed: 2002-05-30T12:46:15Z (22 years ago) by nigel
Branch: MAIN
Changes since 1.3: +25 -5 lines
Log Message:
New way of storing if emulator is in full screen mode

File Contents

# Content
1 /*
2 * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3 *
4 * $Id: EmulatorView.mm,v 1.3 2002/05/12 10:34:16 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 fullScreen = NO;
51
52 #ifdef SAVE_GSTATE
53 [self allocateGState];
54 #endif
55
56 return self;
57 }
58
59 - (void) dealloc
60 {
61 #ifdef SAVE_GSTATE
62 [self releaseGState];
63 #endif
64 [super dealloc];
65 }
66
67 // Mouse click in this window. If window is not active, should click be passed to this view?
68 - (BOOL) acceptsFirstMouse: (NSEvent *) event
69 {
70 return [self mouseInView];
71 }
72
73
74 #include <adb.h>
75
76 static int prevFlags;
77
78 - (void) flagsChanged: (NSEvent *) event
79 {
80 int flags = [event modifierFlags];
81
82 if ( (flags & NSAlphaShiftKeyMask) != (prevFlags & NSAlphaShiftKeyMask) )
83 if ( flags & NSAlphaShiftKeyMask )
84 ADBKeyDown(0x39); // CAPS_LOCK
85 else
86 ADBKeyUp(0x39);
87
88 if ( (flags & NSShiftKeyMask) != (prevFlags & NSShiftKeyMask) )
89 if ( flags & NSShiftKeyMask )
90 ADBKeyDown(0x38); // SHIFT_LEFT
91 else
92 ADBKeyUp(0x38);
93
94 if ( (flags & NSControlKeyMask) != (prevFlags & NSControlKeyMask) )
95 if ( flags & NSControlKeyMask )
96 ADBKeyDown(0x36); // CTL_LEFT
97 else
98 ADBKeyUp(0x36);
99
100 if ( (flags & NSAlternateKeyMask) != (prevFlags & NSAlternateKeyMask) )
101 if ( flags & NSAlternateKeyMask )
102 ADBKeyDown(0x3a); // OPTION_LEFT
103 else
104 ADBKeyUp(0x3a);
105
106 if ( (flags & NSCommandKeyMask) != (prevFlags & NSCommandKeyMask) )
107 if ( flags & NSCommandKeyMask )
108 ADBKeyDown(0x37); // APPLE_LEFT
109 else
110 ADBKeyUp(0x37);
111
112 prevFlags = flags;
113 }
114
115 - (BOOL) mouseInView: (NSEvent *) event
116 {
117 NSPoint loc = [event locationInWindow];
118 NSRect box;
119 if ( fullScreen )
120 return YES;
121 else
122 box = [self frame];
123 D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f",
124 __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y));
125 return [self mouse: loc inRect: box];
126 }
127
128 - (BOOL) mouseInView
129 {
130 NSPoint loc = [[self window] mouseLocationOutsideOfEventStream];
131 NSRect box = [self frame];
132 D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f",
133 __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y));
134 return [self mouse: loc inRect: box];
135 }
136
137
138 //
139 // Custom methods
140 //
141
142 - (void) benchmark
143 {
144 int i;
145 float seconds;
146 NSDate *startDate;
147
148 if ( ! drawView )
149 return;
150
151 drawView = NO;
152 [self lockFocus];
153 startDate = [NSDate date];
154 for (i = 1; i < 300; ++i )
155 #ifdef NSBITMAP
156 [bitmap draw];
157 #endif
158 #ifdef CGIMAGEREF
159 cgDrawInto([self bounds], bitmap);
160 #endif
161 #ifdef CGDRAWBITMAP
162 [self CGDrawBitmap];
163 #endif
164 seconds = -[startDate timeIntervalSinceNow];
165 [self unlockFocus];
166 drawView = YES;
167
168 InfoSheet(@"Benchmark run. 300 frames.",
169 [NSString stringWithFormat:
170 @"%.2f seconds, %.3f frames per second", seconds, i/seconds],
171 @"Thanks", [self window]);
172 }
173
174 // Return a TIFF for a snapshot of the screen image
175 - (NSData *) TIFFrep
176 {
177 #ifdef NSBITMAP
178 return [bitmap TIFFRepresentation];
179 #else
180 WarningAlert("How do I get a TIFF from a CGImageRef?");
181 #endif
182 return nil;
183 }
184
185 // Enable display of, and drawing into, the view
186 #ifdef NSBITMAP
187 - (void) readyToDraw: (NSBitmapImageRep *) theBitmap
188 imageWidth: (short) width
189 imageHeight: (short) height
190 {
191 bitmap = theBitmap;
192 #endif
193 #ifdef CGIMAGEREF
194 - (void) readyToDraw: (CGImageRef) image
195 imageWidth: (short) width
196 imageHeight: (short) height
197 {
198 bitmap = image;
199 #endif
200 #ifdef CGDRAWBITMAP
201 - (void) readyToDraw: (void *) theBitmap
202 width: (short) width
203 height: (short) height
204 bps: (short) bitsPerSample
205 spp: (short) samplesPerPixel
206 bpp: (short) bitsPerPixel
207 bpr: (int) bpr
208 isPlanar: (BOOL) planar
209 hasAlpha: (BOOL) alpha
210 {
211 bitmap = theBitmap;
212 bps = bitsPerSample;
213 spp = samplesPerPixel;
214 bpp = bitsPerPixel;
215 bytesPerRow = bpr;
216 isPlanar = planar;
217 hasAlpha = alpha;
218 #endif
219 x = width, y = height;
220 drawView = YES;
221
222 [[self window] setAcceptsMouseMovedEvents: YES];
223 // [[self window] setInitialFirstResponder: self];
224 [[self window] makeFirstResponder: self];
225 }
226
227 - (void) disableDrawing
228 {
229 drawView = NO;
230 }
231
232 - (void) startedFullScreen
233 {
234 fullScreen = YES;
235 }
236
237 - (short) width
238 {
239 return (short)[self bounds].size.width;
240 }
241
242 - (short) height
243 {
244 return (short)[self bounds].size.height;
245 }
246
247 - (BOOL) isFullScreen
248 {
249 return fullScreen;
250 }
251
252 - (BOOL) isOpaque
253 {
254 return drawView;
255 }
256
257 - (BOOL) processKeyEvent: (NSEvent *) event
258 {
259 if ( fullScreen || [self acceptsFirstMouse: event] )
260 if ( [event isARepeat] )
261 return NO;
262 else
263 return YES;
264
265 [self interpretKeyEvents:[NSArray arrayWithObject:event]];
266 return NO;
267 }
268
269 - (void) keyDown: (NSEvent *) event
270 {
271 if ( [self processKeyEvent: event] )
272 {
273 int code = [event keyCode];
274
275 if ( code == 126 ) code = 0x3e; // CURS_UP
276 if ( code == 125 ) code = 0x3d; // CURS_DOWN
277 if ( code == 124 ) code = 0x3c; // CURS_RIGHT
278 if ( code == 123 ) code = 0x3b; // CURS_LEFT
279
280 ADBKeyDown(code);
281 }
282 }
283
284 - (void) keyUp: (NSEvent *) event
285 {
286 if ( [self processKeyEvent: event] )
287 {
288 int code = [event keyCode];
289
290 if ( code == 126 ) code = 0x3e; // CURS_UP
291 if ( code == 125 ) code = 0x3d; // CURS_DOWN
292 if ( code == 124 ) code = 0x3c; // CURS_RIGHT
293 if ( code == 123 ) code = 0x3b; // CURS_LEFT
294
295 ADBKeyUp(code);
296 }
297 }
298
299 static NSPoint mouse; // Previous/current mouse location
300
301 - (BOOL) processMouseMove: (NSEvent *) event
302 {
303 NSPoint locInView;
304
305 if ( fullScreen )
306 locInView = [NSEvent mouseLocation];
307 // CGAssociateMouseAndMouseCursorPosition(bool)
308 // which will let you unlink the mouse input and the mouse cursor. So I
309 // unlink the two, and the cursor doesn't move, but I still receive
310 // MouseMoved events and can get the movement value using
311 // CGGetLastMouseDelta.
312 else
313 locInView = [self convertPoint: [event locationInWindow] fromView:nil];
314
315 if ( NSEqualPoints(locInView, mouse) )
316 return NO;
317
318 mouse = locInView;
319
320 if ( fullScreen )
321 {
322 ADBMouseMoved((int)mouse.x, screen_height - (int)mouse.y);
323 return YES;
324 }
325
326 #ifdef CAN_RESIZE_VIEW
327 int mouseY = y - y * mouse.y / [self height];
328 int mouseX = x * mouse.x / [self width];
329 #else
330 int mouseY = y - (int) mouse.y;
331 int mouseX = (int) mouse.x;
332 #endif
333
334 ADBMouseMoved(mouseX, mouseY);
335 return YES;
336 }
337
338 - (void) mouseDown: (NSEvent *) event
339 {
340 [self processMouseMove: event];
341 ADBMouseDown(0);
342 }
343
344 - (void) mouseDragged: (NSEvent *) event
345 {
346 [self processMouseMove: event];
347 }
348
349 - (void) mouseMoved: (NSEvent *) event
350 {
351 #if DEBUG
352 if ( ! [self mouseInView] )
353 {
354 NSLog (@"%s - Received event while outside of view", __PRETTY_FUNCTION__);
355 return;
356 }
357 #endif
358 [self processMouseMove: event];
359 }
360
361 - (void) mouseUp: (NSEvent *) event
362 {
363 [self processMouseMove: event];
364 ADBMouseUp(0);
365 }
366
367 #if DEBUG
368 - (void) randomise // Draw some coloured snow in the bitmap
369 {
370 unsigned char *pixel;
371
372 for ( int i = 0; i < 1000; ++i )
373 {
374 pixel = [bitmap bitmapData]
375 + (int) (1.0 * [bitmap bytesPerRow] * 342 //[bitmap height]
376 * rand() / RAND_MAX);
377 *pixel = (unsigned char) (256.0 * rand() / RAND_MAX);
378 }
379 }
380 #endif
381
382 - (void) drawRect: (NSRect) rect
383 {
384 if ( ! drawView ) // If the emulator is still being setup,
385 return; // we do not want to draw
386
387 #if DEBUG
388 NSLog(@"In drawRect");
389 [self randomise];
390 #endif
391
392 #ifdef NSBITMAP
393 NSRectClip(rect);
394 [bitmap draw];
395 #endif
396 #ifdef CGIMAGEREF
397 cgDrawInto(rect, bitmap);
398 #endif
399 #ifdef CGDRAWBITMAP
400 [self CGDrawBitmap];
401 #endif
402 }
403
404 //
405 // Extra drawing stuff
406 //
407
408 #ifdef CGDRAWBITMAP
409 extern "C" void CGDrawBitmap();
410
411 - (void) CGDrawBitmap
412 {
413 CGContextRef cgContext = [[NSGraphicsContext currentContext]
414 graphicsPort];
415 NSRect rect = [self bounds];
416 CGRect cgRect = {
417 {rect.origin.x, rect.origin.y},
418 {rect.size.width, rect.size.height}
419 };
420
421 CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
422
423
424 CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
425
426 CGDrawBitmap(cgContext, cgRect, x, y, bps, spp, bpp,
427 bytesPerRow, isPlanar, hasAlpha, colourSpace, &bitmap);
428 }
429 #endif
430
431 #ifdef CGIMAGEREF
432 void
433 cgDrawInto(NSRect rect, CGImageRef bitmap)
434 {
435 CGContextRef cgContext = [[NSGraphicsContext currentContext]
436 graphicsPort];
437 CGRect cgRect = {
438 {rect.origin.x, rect.origin.y},
439 {rect.size.width, rect.size.height}
440 };
441
442 CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
443
444 CGContextDrawImage(cgContext, cgRect, bitmap);
445 }
446 #endif
447
448 @end