1 /* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #import "common.h" 27 #import "com_sun_glass_events_DndEvent.h" 28 #import "com_sun_glass_events_KeyEvent.h" 29 #import "com_sun_glass_events_MouseEvent.h" 30 #import "com_sun_glass_ui_mac_MacGestureSupport.h" 31 32 #import "GlassMacros.h" 33 #import "GlassView2D.h" 34 35 //#define VERBOSE 36 #ifndef VERBOSE 37 #define LOG(MSG, ...) 38 #else 39 #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__); 40 #endif 41 42 @implementation GlassView2D 43 44 - (id)initWithFrame:(NSRect)frame withJview:(jobject)jView withJproperties:(jobject)jproperties 45 { 46 self = [super initWithFrame:frame]; 47 if (self != nil) 48 { 49 self->delegate = [[GlassViewDelegate alloc] initWithView:self withJview:jView]; 50 51 self->trackingArea = [[NSTrackingArea alloc] initWithRect:frame 52 options:(NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingInVisibleRect) 53 owner:self userInfo:nil]; 54 [self addTrackingArea: self->trackingArea]; 55 } 56 return self; 57 } 58 59 - (void)dealloc 60 { 61 [self->delegate release]; 62 self->delegate = nil; 63 64 [self removeTrackingArea: self->trackingArea]; 65 [self->trackingArea release]; 66 self->trackingArea = nil; 67 68 [super dealloc]; 69 } 70 71 - (BOOL)becomeFirstResponder 72 { 73 return YES; 74 } 75 76 - (BOOL)acceptsFirstResponder 77 { 78 return YES; 79 } 80 81 - (BOOL)canBecomeKeyView 82 { 83 return YES; 84 } 85 86 - (BOOL)postsBoundsChangedNotifications 87 { 88 return NO; 89 } 90 91 - (BOOL)postsFrameChangedNotifications 92 { 93 return NO; 94 } 95 96 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent 97 { 98 return YES; 99 } 100 101 - (BOOL)isFlipped 102 { 103 return YES; 104 } 105 106 - (BOOL)isOpaque 107 { 108 return NO; 109 } 110 111 - (BOOL)mouseDownCanMoveWindow 112 { 113 return NO; 114 } 115 116 // also called when closing window, when [self window] == nil 117 - (void)viewDidMoveToWindow 118 { 119 [self->delegate viewDidMoveToWindow]; 120 } 121 122 - (void)setFrameOrigin:(NSPoint)newOrigin 123 { 124 [super setFrameOrigin:newOrigin]; 125 [self->delegate setFrameOrigin:newOrigin]; 126 } 127 128 - (void)setFrameSize:(NSSize)newSize 129 { 130 [super setFrameSize:newSize]; 131 [self->delegate setFrameSize:newSize]; 132 } 133 134 - (void)setFrame:(NSRect)frameRect 135 { 136 [super setFrame:frameRect]; 137 [self->delegate setFrame:frameRect]; 138 } 139 140 - (void)updateTrackingAreas 141 { 142 [super updateTrackingAreas]; 143 [self->delegate updateTrackingAreas]; 144 } 145 146 - (NSMenu *)menuForEvent:(NSEvent *)theEvent 147 { 148 [self->delegate sendJavaMenuEvent:theEvent]; 149 return [super menuForEvent: theEvent]; 150 } 151 152 - (void)mouseEntered:(NSEvent *)theEvent 153 { 154 [self->delegate sendJavaMouseEvent:theEvent]; 155 } 156 157 - (void)mouseMoved:(NSEvent *)theEvent 158 { 159 [self->delegate sendJavaMouseEvent:theEvent]; 160 } 161 162 - (void)mouseExited:(NSEvent *)theEvent 163 { 164 [self->delegate sendJavaMouseEvent:theEvent]; 165 } 166 167 - (void)mouseDown:(NSEvent *)theEvent 168 { 169 [self->delegate sendJavaMouseEvent:theEvent]; 170 } 171 172 - (void)mouseDragged:(NSEvent *)theEvent 173 { 174 [self->delegate sendJavaMouseEvent:theEvent]; 175 } 176 177 - (void)mouseUp:(NSEvent *)theEvent 178 { 179 [self->delegate sendJavaMouseEvent:theEvent]; 180 } 181 182 - (void)rightMouseDown:(NSEvent *)theEvent 183 { 184 [self->delegate sendJavaMouseEvent:theEvent]; 185 // By default, calling rightMouseDown: generates menuForEvent: but none of the other glass mouse handlers call the super 186 // To be consistent with the rest of glass, call the menu event handler directly rather than letting the operating system do it 187 [self->delegate sendJavaMenuEvent:theEvent]; 188 // return [super rightMouseDown: theEvent]; 189 } 190 191 - (void)rightMouseDragged:(NSEvent *)theEvent 192 { 193 [self->delegate sendJavaMouseEvent:theEvent]; 194 } 195 196 - (void)rightMouseUp:(NSEvent *)theEvent 197 { 198 [self->delegate sendJavaMouseEvent:theEvent]; 199 } 200 201 - (void)otherMouseDown:(NSEvent *)theEvent 202 { 203 [self->delegate sendJavaMouseEvent:theEvent]; 204 } 205 206 - (void)otherMouseDragged:(NSEvent *)theEvent 207 { 208 [self->delegate sendJavaMouseEvent:theEvent]; 209 } 210 211 - (void)otherMouseUp:(NSEvent *)theEvent 212 { 213 [self->delegate sendJavaMouseEvent:theEvent]; 214 } 215 216 - (void)rotateWithEvent:(NSEvent *)theEvent 217 { 218 [self->delegate sendJavaGestureEvent:theEvent type:com_sun_glass_ui_mac_MacGestureSupport_GESTURE_ROTATE]; 219 } 220 221 - (void)swipeWithEvent:(NSEvent *)theEvent 222 { 223 [self->delegate sendJavaGestureEvent:theEvent type:com_sun_glass_ui_mac_MacGestureSupport_GESTURE_SWIPE]; 224 } 225 226 - (void)magnifyWithEvent:(NSEvent *)theEvent 227 { 228 [self->delegate sendJavaGestureEvent:theEvent type:com_sun_glass_ui_mac_MacGestureSupport_GESTURE_MAGNIFY]; 229 } 230 231 - (void)endGestureWithEvent:(NSEvent *)theEvent 232 { 233 [self->delegate sendJavaGestureEndEvent:theEvent]; 234 } 235 236 - (void)beginGestureWithEvent:(NSEvent *)theEvent 237 { 238 [self->delegate sendJavaGestureBeginEvent:theEvent]; 239 } 240 241 - (void)scrollWheel:(NSEvent *)theEvent 242 { 243 [self->delegate sendJavaMouseEvent:theEvent]; 244 } 245 246 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent 247 { 248 [self->delegate sendJavaKeyEvent:theEvent isDown:YES]; 249 return NO; // return NO to allow system-default processing of Cmd+Q, etc. 250 } 251 252 - (void)keyDown:(NSEvent *)theEvent 253 { 254 [self->delegate sendJavaKeyEvent:theEvent isDown:YES]; 255 } 256 257 - (void)keyUp:(NSEvent *)theEvent 258 { 259 [self->delegate sendJavaKeyEvent:theEvent isDown:NO]; 260 } 261 262 - (void)flagsChanged:(NSEvent *)theEvent 263 { 264 [self->delegate sendJavaModifierKeyEvent:theEvent]; 265 } 266 267 - (BOOL)wantsPeriodicDraggingUpdates 268 { 269 // we only want want updated drag operations when the mouse position changes 270 return NO; 271 } 272 273 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender 274 { 275 return YES; 276 } 277 278 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender 279 { 280 [self->delegate sendJavaDndEvent:sender type:com_sun_glass_events_DndEvent_PERFORM]; 281 282 return YES; 283 } 284 285 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender 286 { 287 288 } 289 290 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender 291 { 292 return [self->delegate sendJavaDndEvent:sender type:com_sun_glass_events_DndEvent_ENTER]; 293 } 294 295 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender 296 { 297 return [self->delegate sendJavaDndEvent:sender type:com_sun_glass_events_DndEvent_UPDATE]; 298 } 299 300 - (void)draggingEnded:(id <NSDraggingInfo>)sender 301 { 302 [self->delegate draggingEnded]; 303 } 304 305 - (void)draggingExited:(id <NSDraggingInfo>)sender 306 { 307 [self->delegate sendJavaDndEvent:sender type:com_sun_glass_events_DndEvent_EXIT]; 308 } 309 310 - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal 311 { 312 return [self->delegate draggingSourceOperationMaskForLocal:isLocal]; 313 } 314 315 - (void)drawRect:(NSRect)dirtyRect 316 { 317 [self->delegate drawRect:dirtyRect]; 318 } 319 320 - (void)enterFullscreenWithAnimate:(BOOL)animate withKeepRatio:(BOOL)keepRatio withHideCursor:(BOOL)hideCursor 321 { 322 [self->delegate enterFullscreenWithAnimate:animate withKeepRatio:keepRatio withHideCursor:hideCursor]; 323 } 324 325 - (void)exitFullscreenWithAnimate:(BOOL)animate 326 { 327 [self->delegate exitFullscreenWithAnimate:animate]; 328 } 329 330 // below are methods that are 2D specific 331 - (void)begin 332 { 333 CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort]; 334 CGContextSaveGState(cgContext); 335 { 336 #if 0 337 NSRect bounds = [self bounds]; 338 fprintf(stderr, "bounds: %f,%f %fx%f\n", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); 339 NSRect frame = [self frame]; 340 fprintf(stderr, "frame: %f,%f %fx%f\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); 341 342 CGRect bbox = CGContextGetClipBoundingBox(cgContext); 343 fprintf(stderr, "bbox: %f,%f %fx%f\n", bbox.origin.x, bbox.origin.y, bbox.size.width, bbox.size.height); 344 CGAffineTransform ctm = CGContextGetCTM(cgContext); 345 fprintf(stderr, "ctm: a:%f, b:%f, c:%f, d:%f, tx:%f, ty:%f\n", ctm.a, ctm.b, ctm.c, ctm.d, ctm.tx, ctm.ty); 346 #endif 347 // gznote: we could clear the surface for the client, but the client should be responsible for drawing 348 // and if garbage appears on the screen it's because the client is not drawing in response to system repaints 349 //CGContextClearRect(cgContext, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height)); 350 } 351 } 352 353 - (void)end 354 { 355 CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort]; 356 { 357 #if 0 358 [[NSColor blackColor] setStroke]; 359 NSBezierPath *path = [NSBezierPath bezierPath]; 360 [path moveToPoint:NSMakePoint(0.0f, 0.0f)]; 361 [path lineToPoint:NSMakePoint([self bounds].size.width, [self bounds].size.height)]; 362 [path moveToPoint:NSMakePoint(0.0f, [self bounds].size.height)]; 363 [path lineToPoint:NSMakePoint([self bounds].size.width, 0.0f)]; 364 [path stroke]; 365 #endif 366 #if 0 367 CGContextFillRect(cgContext, CGRectMake(0, 0, 128, 128)); 368 #endif 369 370 CGContextFlush(cgContext); 371 } 372 CGContextRestoreGState(cgContext); 373 } 374 375 - (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScaleX:(GLfloat)scalex withScaleY:(GLfloat)scaley withEnv:(JNIEnv *)env 376 { 377 assert([NSGraphicsContext currentContext] != nil); 378 379 CGContextRef cgContext = [[NSGraphicsContext currentContext] graphicsPort]; 380 { 381 CGImageRef cgImage = NULL; 382 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 383 { 384 CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, width*height*4, NULL); 385 { 386 cgImage = CGImageCreate(width, height, 8, 32, 4*width, colorSpace, kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Little, provider, NULL, true, kCGRenderingIntentDefault); 387 { 388 NSSize size = [self bounds].size; 389 if ((size.width != width) || (size.height != height)) 390 { 391 //NSLog(@"Glass View2D size: %dx%d, but pixels size: %dx%d", (int)size.width, (int)size.height, width, height); 392 //CGContextClearRect(cgContext, CGRectMake(0, 0, size.width, size.height)); 393 } 394 395 CGContextSaveGState(cgContext); 396 { 397 CGContextTranslateCTM(cgContext, 0, size.height); 398 CGContextScaleCTM(cgContext, 1, -1); 399 CGContextSetBlendMode(cgContext, kCGBlendModeCopy); 400 CGContextDrawImage(cgContext, CGRectMake(0, 0, width/scalex, height/scaley), cgImage); 401 } 402 CGContextRestoreGState(cgContext); 403 } 404 CGImageRelease(cgImage); 405 } 406 CGDataProviderRelease(provider); 407 } 408 CGColorSpaceRelease(colorSpace); 409 } 410 CGContextFlush(cgContext); // implicit flush 411 } 412 413 - (GlassViewDelegate*)delegate 414 { 415 return self->delegate; 416 } 417 418 - (void)setInputMethodEnabled:(BOOL)enabled 419 { 420 // Just a no-op here, GlassView2D does not support the IM interface 421 } 422 423 - (void)notifyScaleFactorChanged:(CGFloat)scale 424 { 425 // no-op 426 } 427 428 @end