ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/EmulatorView.mm
Revision: 1.5
Committed: 2002-06-05T10:18:51Z (22 years ago) by nigel
Branch: MAIN
Changes since 1.4: +24 -18 lines
Log Message:
Better mouse event control for full screen mode

File Contents

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