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

# User Rev Content
1 nigel 1.1 /*
2     * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3     *
4 nigel 1.2 * $Id: EmulatorView.mm,v 1.2 2002/03/16 10:00:19 nigel Exp $
5 nigel 1.1 *
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 nigel 1.2 {
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 nigel 1.1 }
275    
276     - (void) keyUp: (NSEvent *) event
277     {
278     if ( [self processKeyEvent: event] )
279 nigel 1.2 {
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 nigel 1.1 }
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