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

# User Rev Content
1 nigel 1.1 /*
2     * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3     *
4 nigel 1.5 * $Id: EmulatorView.mm,v 1.4 2002/05/30 12:46:15 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 nigel 1.4 fullScreen = NO;
51 nigel 1.1
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 nigel 1.5 // Mouse click in this window. If window is not active,
68     // should the click be passed to this view?
69 nigel 1.1 - (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 nigel 1.4 NSRect box;
119 nigel 1.5 NSPoint loc;
120    
121 nigel 1.4 if ( fullScreen )
122 nigel 1.5 {
123     box = displayBox;
124     loc = [NSEvent mouseLocation];
125     }
126 nigel 1.4 else
127 nigel 1.5 {
128 nigel 1.4 box = [self frame];
129 nigel 1.5 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 nigel 1.1 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 nigel 1.5 - (void) startedFullScreen: (CGDirectDisplayID) display
240 nigel 1.4 {
241 nigel 1.5 CGRect displayBounds = CGDisplayBounds(display);
242    
243 nigel 1.4 fullScreen = YES;
244 nigel 1.5 memcpy(&displayBox, &displayBounds, sizeof(displayBox));
245     screen_height = (int)displayBounds.size.height;
246 nigel 1.4 }
247    
248 nigel 1.1 - (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 nigel 1.4 - (BOOL) isFullScreen
259     {
260     return fullScreen;
261     }
262    
263 nigel 1.1 - (BOOL) isOpaque
264     {
265     return drawView;
266     }
267    
268     - (BOOL) processKeyEvent: (NSEvent *) event
269     {
270 nigel 1.4 if ( fullScreen || [self acceptsFirstMouse: event] )
271 nigel 1.1 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 nigel 1.2 {
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 nigel 1.1 }
294    
295     - (void) keyUp: (NSEvent *) event
296     {
297     if ( [self processKeyEvent: event] )
298 nigel 1.2 {
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 nigel 1.1 }
309    
310     static NSPoint mouse; // Previous/current mouse location
311    
312     - (BOOL) processMouseMove: (NSEvent *) event
313     {
314 nigel 1.5 NSPoint location;
315 nigel 1.1
316 nigel 1.4 if ( fullScreen )
317 nigel 1.5 location = [NSEvent mouseLocation];
318 nigel 1.1 else
319 nigel 1.5 location = [self convertPoint: [event locationInWindow] fromView:nil];
320 nigel 1.1
321 nigel 1.5 if ( NSEqualPoints(location, mouse) )
322 nigel 1.1 return NO;
323    
324 nigel 1.5 mouse = location;
325 nigel 1.1
326 nigel 1.4 if ( fullScreen )
327 nigel 1.1 {
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 nigel 1.3 @end