1 /* GdkQuartzView.m 2 * 3 * Copyright (C) 2005-2007 Imendio AB 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 * Boston, MA 02111-1307, USA. 19 */ 20 21 #import "GdkQuartzView.h" 22 #include "gdkregion.h" 23 #include "gdkregion-generic.h" 24 #include "gdkwindow-quartz.h" 25 #include "gdkprivate-quartz.h" 26 #include "gdkquartz.h" 27 28 @implementation GdkQuartzView 29 30 -(id)initWithFrame: (NSRect)frameRect 31 { 32 if ((self = [super initWithFrame: frameRect])) 33 { 34 markedRange = NSMakeRange (NSNotFound, 0); 35 selectedRange = NSMakeRange (NSNotFound, 0); 36 } 37 38 return self; 39 } 40 41 -(BOOL)acceptsFirstResponder 42 { 43 GDK_NOTE (EVENTS, g_print ("acceptsFirstResponder\n")); 44 return YES; 45 } 46 47 -(BOOL)becomeFirstResponder 48 { 49 GDK_NOTE (EVENTS, g_print ("becomeFirstResponder\n")); 50 return YES; 51 } 52 53 -(BOOL)resignFirstResponder 54 { 55 GDK_NOTE (EVENTS, g_print ("resignFirstResponder\n")); 56 return YES; 57 } 58 59 -(void) keyDown: (NSEvent *) theEvent 60 { 61 GDK_NOTE (EVENTS, g_print ("keyDown\n")); 62 [self interpretKeyEvents: [NSArray arrayWithObject: theEvent]]; 63 } 64 65 -(void)flagsChanged: (NSEvent *) theEvent 66 { 67 } 68 69 -(NSUInteger)characterIndexForPoint: (NSPoint)aPoint 70 { 71 GDK_NOTE (EVENTS, g_print ("characterIndexForPoint\n")); 72 return 0; 73 } 74 75 -(NSRect)firstRectForCharacterRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange 76 { 77 GDK_NOTE (EVENTS, g_print ("firstRectForCharacterRange\n")); 78 gint ns_x, ns_y; 79 GdkRectangle *rect; 80 81 rect = g_object_get_data (G_OBJECT (gdk_window), GIC_CURSOR_RECT); 82 if (rect) 83 { 84 _gdk_quartz_window_gdk_xy_to_xy (rect->x, rect->y + rect->height, 85 &ns_x, &ns_y); 86 87 return NSMakeRect (ns_x, ns_y, rect->width, rect->height); 88 } 89 else 90 { 91 return NSMakeRect (0, 0, 0, 0); 92 } 93 } 94 95 -(NSArray *)validAttributesForMarkedText 96 { 97 GDK_NOTE (EVENTS, g_print ("validAttributesForMarkedText\n")); 98 return [NSArray arrayWithObjects: NSUnderlineStyleAttributeName, nil]; 99 } 100 101 -(NSAttributedString *)attributedSubstringForProposedRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange 102 { 103 GDK_NOTE (EVENTS, g_print ("attributedSubstringForProposedRange\n")); 104 return nil; 105 } 106 107 -(BOOL)hasMarkedText 108 { 109 GDK_NOTE (EVENTS, g_print ("hasMarkedText\n")); 110 return markedRange.location != NSNotFound && markedRange.length != 0; 111 } 112 113 -(NSRange)markedRange 114 { 115 GDK_NOTE (EVENTS, g_print ("markedRange\n")); 116 return markedRange; 117 } 118 119 -(NSRange)selectedRange 120 { 121 GDK_NOTE (EVENTS, g_print ("selectedRange\n")); 122 return selectedRange; 123 } 124 125 -(void)unmarkText 126 { 127 GDK_NOTE (EVENTS, g_print ("unmarkText\n")); 128 gchar *prev_str; 129 markedRange = selectedRange = NSMakeRange (NSNotFound, 0); 130 131 prev_str = g_object_get_data (G_OBJECT (gdk_window), TIC_MARKED_TEXT); 132 if (prev_str) 133 g_free (prev_str); 134 g_object_set_data (G_OBJECT (gdk_window), TIC_MARKED_TEXT, NULL); 135 } 136 137 -(void)setMarkedText: (id)aString selectedRange: (NSRange)newSelection replacementRange: (NSRange)replacementRange 138 { 139 GDK_NOTE (EVENTS, g_print ("setMarkedText\n")); 140 const char *str; 141 gchar *prev_str; 142 143 if (replacementRange.location == NSNotFound) 144 { 145 markedRange = NSMakeRange (newSelection.location, [aString length]); 146 selectedRange = NSMakeRange (newSelection.location, newSelection.length); 147 } 148 else { 149 markedRange = NSMakeRange (replacementRange.location, [aString length]); 150 selectedRange = NSMakeRange (replacementRange.location + newSelection.location, newSelection.length); 151 } 152 153 if ([aString isKindOfClass: [NSAttributedString class]]) 154 { 155 str = [[aString string] UTF8String]; 156 } 157 else { 158 str = [aString UTF8String]; 159 } 160 161 prev_str = g_object_get_data (G_OBJECT (gdk_window), TIC_MARKED_TEXT); 162 if (prev_str) 163 g_free (prev_str); 164 g_object_set_data (G_OBJECT (gdk_window), TIC_MARKED_TEXT, g_strdup (str)); 165 g_object_set_data (G_OBJECT (gdk_window), TIC_SELECTED_POS, 166 GUINT_TO_POINTER (selectedRange.location)); 167 g_object_set_data (G_OBJECT (gdk_window), TIC_SELECTED_LEN, 168 GUINT_TO_POINTER (selectedRange.length)); 169 170 GDK_NOTE (EVENTS, g_print ("setMarkedText: set %s (%p, nsview %p): %s\n", 171 TIC_MARKED_TEXT, gdk_window, self, 172 str ? str : "(empty)")); 173 174 /* handle text input changes by mouse events */ 175 if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_window), 176 TIC_IN_KEY_DOWN))) 177 { 178 _gdk_quartz_synthesize_null_key_event(gdk_window); 179 } 180 } 181 182 -(void)doCommandBySelector: (SEL)aSelector 183 { 184 GDK_NOTE (EVENTS, g_print ("doCommandBySelector\n")); 185 if ([self respondsToSelector: aSelector]) 186 [self performSelector: aSelector]; 187 } 188 189 /* This gets called on OS X 10.6 and upwards from interpretKeyEvents */ 190 -(void)insertText: (id)aString replacementRange: (NSRange)replacementRange 191 { 192 [self insertText:aString]; 193 } 194 195 /* This gets called on OS X 10.5 from interpretKeyEvents, although 10.5 196 * is supposed to support NSTextInputClient */ 197 -(void)insertText: (id)aString 198 { 199 GDK_NOTE (EVENTS, g_print ("insertText\n")); 200 const char *str; 201 NSString *string; 202 gchar *prev_str; 203 204 if ([self hasMarkedText]) 205 [self unmarkText]; 206 207 if ([aString isKindOfClass: [NSAttributedString class]]) 208 string = [aString string]; 209 else 210 string = aString; 211 212 NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet]; 213 NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 214 if ([string rangeOfCharacterFromSet:ctrlChars].length && 215 [string rangeOfCharacterFromSet:wsnlChars].length == 0) 216 { 217 /* discard invalid text input with Chinese input methods */ 218 str = ""; 219 [self unmarkText]; 220 NSInputManager *currentInputManager = [NSInputManager currentInputManager]; 221 [currentInputManager markedTextAbandoned:self]; 222 } 223 else 224 { 225 str = [string UTF8String]; 226 } 227 228 prev_str = g_object_get_data (G_OBJECT (gdk_window), TIC_INSERT_TEXT); 229 if (prev_str) 230 g_free (prev_str); 231 g_object_set_data (G_OBJECT (gdk_window), TIC_INSERT_TEXT, g_strdup (str)); 232 GDK_NOTE (EVENTS, g_print ("insertText: set %s (%p, nsview %p): %s\n", 233 TIC_INSERT_TEXT, gdk_window, self, 234 str ? str : "(empty)")); 235 236 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 237 GUINT_TO_POINTER (GIC_FILTER_FILTERED)); 238 239 /* handle text input changes by mouse events */ 240 if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_window), 241 TIC_IN_KEY_DOWN))) 242 { 243 _gdk_quartz_synthesize_null_key_event(gdk_window); 244 } 245 } 246 247 -(void)deleteBackward: (id)sender 248 { 249 GDK_NOTE (EVENTS, g_print ("deleteBackward\n")); 250 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 251 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 252 } 253 254 -(void)deleteForward: (id)sender 255 { 256 GDK_NOTE (EVENTS, g_print ("deleteForward\n")); 257 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 258 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 259 } 260 261 -(void)deleteToBeginningOfLine: (id)sender 262 { 263 GDK_NOTE (EVENTS, g_print ("deleteToBeginningOfLine\n")); 264 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 265 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 266 } 267 268 -(void)deleteToEndOfLine: (id)sender 269 { 270 GDK_NOTE (EVENTS, g_print ("deleteToEndOfLine\n")); 271 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 272 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 273 } 274 275 -(void)deleteWordBackward: (id)sender 276 { 277 GDK_NOTE (EVENTS, g_print ("deleteWordBackward\n")); 278 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 279 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 280 } 281 282 -(void)deleteWordForward: (id)sender 283 { 284 GDK_NOTE (EVENTS, g_print ("deleteWordForward\n")); 285 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 286 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 287 } 288 289 -(void)insertBacktab: (id)sender 290 { 291 GDK_NOTE (EVENTS, g_print ("insertBacktab\n")); 292 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 293 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 294 } 295 296 -(void)insertNewline: (id)sender 297 { 298 GDK_NOTE (EVENTS, g_print ("insertNewline\n")); 299 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 300 } 301 302 -(void)insertTab: (id)sender 303 { 304 GDK_NOTE (EVENTS, g_print ("insertTab\n")); 305 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 306 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 307 } 308 309 -(void)moveBackward: (id)sender 310 { 311 GDK_NOTE (EVENTS, g_print ("moveBackward\n")); 312 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 313 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 314 } 315 316 -(void)moveBackwardAndModifySelection: (id)sender 317 { 318 GDK_NOTE (EVENTS, g_print ("moveBackwardAndModifySelection\n")); 319 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 320 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 321 } 322 323 -(void)moveDown: (id)sender 324 { 325 GDK_NOTE (EVENTS, g_print ("moveDown\n")); 326 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 327 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 328 } 329 330 -(void)moveDownAndModifySelection: (id)sender 331 { 332 GDK_NOTE (EVENTS, g_print ("moveDownAndModifySelection\n")); 333 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 334 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 335 } 336 337 -(void)moveForward: (id)sender 338 { 339 GDK_NOTE (EVENTS, g_print ("moveForward\n")); 340 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 341 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 342 } 343 344 -(void)moveForwardAndModifySelection: (id)sender 345 { 346 GDK_NOTE (EVENTS, g_print ("moveForwardAndModifySelection\n")); 347 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 348 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 349 } 350 351 -(void)moveLeft: (id)sender 352 { 353 GDK_NOTE (EVENTS, g_print ("moveLeft\n")); 354 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 355 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 356 } 357 358 -(void)moveLeftAndModifySelection: (id)sender 359 { 360 GDK_NOTE (EVENTS, g_print ("moveLeftAndModifySelection\n")); 361 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 362 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 363 } 364 365 -(void)moveRight: (id)sender 366 { 367 GDK_NOTE (EVENTS, g_print ("moveRight\n")); 368 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 369 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 370 } 371 372 -(void)moveRightAndModifySelection: (id)sender 373 { 374 GDK_NOTE (EVENTS, g_print ("moveRightAndModifySelection\n")); 375 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 376 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 377 } 378 379 -(void)moveToBeginningOfDocument: (id)sender 380 { 381 GDK_NOTE (EVENTS, g_print ("moveToBeginningOfDocument\n")); 382 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 383 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 384 } 385 386 -(void)moveToBeginningOfDocumentAndModifySelection: (id)sender 387 { 388 GDK_NOTE (EVENTS, g_print ("moveToBeginningOfDocumentAndModifySelection\n")); 389 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 390 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 391 } 392 393 -(void)moveToBeginningOfLine: (id)sender 394 { 395 GDK_NOTE (EVENTS, g_print ("moveToBeginningOfLine\n")); 396 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 397 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 398 } 399 400 -(void)moveToBeginningOfLineAndModifySelection: (id)sender 401 { 402 GDK_NOTE (EVENTS, g_print ("moveToBeginningOfLineAndModifySelection\n")); 403 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 404 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 405 } 406 407 -(void)moveToEndOfDocument: (id)sender 408 { 409 GDK_NOTE (EVENTS, g_print ("moveToEndOfDocument\n")); 410 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 411 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 412 } 413 414 -(void)moveToEndOfDocumentAndModifySelection: (id)sender 415 { 416 GDK_NOTE (EVENTS, g_print ("moveToEndOfDocumentAndModifySelection\n")); 417 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 418 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 419 } 420 421 -(void)moveToEndOfLine: (id)sender 422 { 423 GDK_NOTE (EVENTS, g_print ("moveToEndOfLine\n")); 424 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 425 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 426 } 427 428 -(void)moveToEndOfLineAndModifySelection: (id)sender 429 { 430 GDK_NOTE (EVENTS, g_print ("moveToEndOfLineAndModifySelection\n")); 431 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 432 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 433 } 434 435 -(void)moveUp: (id)sender 436 { 437 GDK_NOTE (EVENTS, g_print ("moveUp\n")); 438 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 439 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 440 } 441 442 -(void)moveUpAndModifySelection: (id)sender 443 { 444 GDK_NOTE (EVENTS, g_print ("moveUpAndModifySelection\n")); 445 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 446 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 447 } 448 449 -(void)moveWordBackward: (id)sender 450 { 451 GDK_NOTE (EVENTS, g_print ("moveWordBackward\n")); 452 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 453 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 454 } 455 456 -(void)moveWordBackwardAndModifySelection: (id)sender 457 { 458 GDK_NOTE (EVENTS, g_print ("moveWordBackwardAndModifySelection\n")); 459 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 460 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 461 } 462 463 -(void)moveWordForward: (id)sender 464 { 465 GDK_NOTE (EVENTS, g_print ("moveWordForward\n")); 466 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 467 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 468 } 469 470 -(void)moveWordForwardAndModifySelection: (id)sender 471 { 472 GDK_NOTE (EVENTS, g_print ("moveWordForwardAndModifySelection\n")); 473 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 474 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 475 } 476 477 -(void)moveWordLeft: (id)sender 478 { 479 GDK_NOTE (EVENTS, g_print ("moveWordLeft\n")); 480 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 481 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 482 } 483 484 -(void)moveWordLeftAndModifySelection: (id)sender 485 { 486 GDK_NOTE (EVENTS, g_print ("moveWordLeftAndModifySelection\n")); 487 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 488 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 489 } 490 491 -(void)moveWordRight: (id)sender 492 { 493 GDK_NOTE (EVENTS, g_print ("moveWordRight\n")); 494 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 495 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 496 } 497 498 -(void)moveWordRightAndModifySelection: (id)sender 499 { 500 GDK_NOTE (EVENTS, g_print ("moveWordRightAndModifySelection\n")); 501 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 502 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 503 } 504 505 -(void)pageDown: (id)sender 506 { 507 GDK_NOTE (EVENTS, g_print ("pageDown\n")); 508 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 509 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 510 } 511 512 -(void)pageDownAndModifySelection: (id)sender 513 { 514 GDK_NOTE (EVENTS, g_print ("pageDownAndModifySelection\n")); 515 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 516 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 517 } 518 519 -(void)pageUp: (id)sender 520 { 521 GDK_NOTE (EVENTS, g_print ("pageUp\n")); 522 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 523 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 524 } 525 526 -(void)pageUpAndModifySelection: (id)sender 527 { 528 GDK_NOTE (EVENTS, g_print ("pageUpAndModifySelection\n")); 529 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 530 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 531 } 532 533 -(void)selectAll: (id)sender 534 { 535 GDK_NOTE (EVENTS, g_print ("selectAll\n")); 536 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 537 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 538 } 539 540 -(void)selectLine: (id)sender 541 { 542 GDK_NOTE (EVENTS, g_print ("selectLine\n")); 543 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 544 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 545 } 546 547 -(void)selectWord: (id)sender 548 { 549 GDK_NOTE (EVENTS, g_print ("selectWord\n")); 550 g_object_set_data (G_OBJECT (gdk_window), GIC_FILTER_KEY, 551 GUINT_TO_POINTER (GIC_FILTER_PASSTHRU)); 552 } 553 554 -(void)noop: (id)sender 555 { 556 GDK_NOTE (EVENTS, g_print ("noop\n")); 557 } 558 559 /* --------------------------------------------------------------- */ 560 561 -(void)dealloc 562 { 563 if (trackingRect) 564 { 565 [self removeTrackingRect: trackingRect]; 566 trackingRect = 0; 567 } 568 569 [super dealloc]; 570 } 571 572 -(void)setGdkWindow: (GdkWindow *)window 573 { 574 gdk_window = window; 575 } 576 577 -(GdkWindow *)gdkWindow 578 { 579 return gdk_window; 580 } 581 582 -(NSTrackingRectTag)trackingRect 583 { 584 return trackingRect; 585 } 586 587 -(BOOL)isFlipped 588 { 589 return YES; 590 } 591 592 -(BOOL)isOpaque 593 { 594 if (GDK_WINDOW_DESTROYED (gdk_window)) 595 return YES; 596 597 /* A view is opaque if its GdkWindow doesn't have the RGBA colormap */ 598 return gdk_drawable_get_colormap (gdk_window) != 599 gdk_screen_get_rgba_colormap (_gdk_screen); 600 } 601 602 -(void)drawRect: (NSRect)rect 603 { 604 GdkRectangle gdk_rect; 605 GdkWindowObject *private = GDK_WINDOW_OBJECT (gdk_window); 606 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); 607 const NSRect *drawn_rects; 608 NSInteger count; 609 int i; 610 GdkRegion *region; 611 612 if (GDK_WINDOW_DESTROYED (gdk_window)) 613 return; 614 615 if (! (private->event_mask & GDK_EXPOSURE_MASK)) 616 return; 617 618 if (NSEqualRects (rect, NSZeroRect)) 619 return; 620 621 if (!GDK_WINDOW_IS_MAPPED (gdk_window)) 622 { 623 /* If the window is not yet mapped, clip_region_with_children 624 * will be empty causing the usual code below to draw nothing. 625 * To not see garbage on the screen, we draw an aesthetic color 626 * here. The garbage would be visible if any widget enabled 627 * the NSView's CALayer in order to add sublayers for custom 628 * native rendering. 629 */ 630 [NSGraphicsContext saveGraphicsState]; 631 632 [[NSColor windowBackgroundColor] setFill]; 633 [NSBezierPath fillRect: rect]; 634 635 [NSGraphicsContext restoreGraphicsState]; 636 637 return; 638 } 639 640 /* Clear our own bookkeeping of regions that need display */ 641 if (impl->needs_display_region) 642 { 643 gdk_region_destroy (impl->needs_display_region); 644 impl->needs_display_region = NULL; 645 } 646 647 [self getRectsBeingDrawn: &drawn_rects count: &count]; 648 region = gdk_region_new (); 649 650 for (i = 0; i < count; i++) 651 { 652 gdk_rect.x = drawn_rects[i].origin.x; 653 gdk_rect.y = drawn_rects[i].origin.y; 654 gdk_rect.width = drawn_rects[i].size.width; 655 gdk_rect.height = drawn_rects[i].size.height; 656 657 gdk_region_union_with_rect (region, &gdk_rect); 658 } 659 660 impl->in_paint_rect_count++; 661 _gdk_window_process_updates_recurse (gdk_window, region); 662 impl->in_paint_rect_count--; 663 664 gdk_region_destroy (region); 665 666 if (needsInvalidateShadow) 667 { 668 [[self window] invalidateShadow]; 669 needsInvalidateShadow = NO; 670 } 671 } 672 673 -(void)setNeedsInvalidateShadow: (BOOL)invalidate 674 { 675 needsInvalidateShadow = invalidate; 676 } 677 678 /* For information on setting up tracking rects properly, see here: 679 * http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventOverview.pdf 680 */ 681 -(void)updateTrackingRect 682 { 683 GdkWindowObject *private = GDK_WINDOW_OBJECT (gdk_window); 684 GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl); 685 NSRect rect; 686 687 if (!impl || !impl->toplevel) 688 return; 689 690 if (trackingRect) 691 { 692 [self removeTrackingRect: trackingRect]; 693 trackingRect = 0; 694 } 695 696 if (!impl->toplevel) 697 return; 698 699 /* Note, if we want to set assumeInside we can use: 700 * NSPointInRect ([[self window] convertScreenToBase:[NSEvent mouseLocation]], rect) 701 */ 702 703 rect = [self bounds]; 704 trackingRect = [self addTrackingRect: rect 705 owner: self 706 userData: nil 707 assumeInside: NO]; 708 } 709 710 -(void)viewDidMoveToWindow 711 { 712 if (![self window]) /* We are destroyed already */ 713 return; 714 715 [self updateTrackingRect]; 716 } 717 718 -(void)viewWillMoveToWindow: (NSWindow *)newWindow 719 { 720 if (newWindow == nil && trackingRect) 721 { 722 [self removeTrackingRect: trackingRect]; 723 trackingRect = 0; 724 } 725 } 726 727 -(void)setFrame: (NSRect)frame 728 { 729 [super setFrame: frame]; 730 731 if ([self window]) 732 [self updateTrackingRect]; 733 } 734 735 @end 736