Print this page
Added gradle and cmake project
Split |
Close |
Expand all |
Collapse all |
--- old/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java
+++ new/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java
1 1 /*
2 2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26
27 27 package sun.lwawt;
28 28
29 29 import java.awt.*;
30 30
31 31 import java.awt.dnd.DropTarget;
32 32 import java.awt.dnd.peer.DropTargetPeer;
33 33 import java.awt.event.*;
34 34
35 35 import java.awt.image.ColorModel;
36 36 import java.awt.image.ImageObserver;
37 37 import java.awt.image.ImageProducer;
38 38 import java.awt.image.VolatileImage;
39 39
40 40 import java.awt.peer.ComponentPeer;
41 41 import java.awt.peer.ContainerPeer;
42 42
43 43 import java.awt.peer.KeyboardFocusManagerPeer;
44 44 import java.util.concurrent.atomic.AtomicBoolean;
45 45 import java.lang.reflect.Field;
46 46 import java.security.AccessController;
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
47 47 import java.security.PrivilegedAction;
48 48
49 49 import sun.awt.*;
50 50
51 51 import sun.awt.event.IgnorePaintEvent;
52 52
53 53 import sun.awt.image.SunVolatileImage;
54 54 import sun.awt.image.ToolkitImage;
55 55
56 56 import sun.java2d.SunGraphics2D;
57 +import sun.java2d.macos.MacOSFlags;
58 +import sun.java2d.metal.MTLRenderQueue;
57 59 import sun.java2d.opengl.OGLRenderQueue;
58 60 import sun.java2d.pipe.Region;
59 61
62 +import sun.java2d.pipe.RenderQueue;
60 63 import sun.util.logging.PlatformLogger;
61 64
62 65 import javax.swing.JComponent;
63 66 import javax.swing.SwingUtilities;
64 67 import javax.swing.RepaintManager;
65 68
66 69 import com.sun.java.swing.SwingUtilities3;
67 70
68 71 public abstract class LWComponentPeer<T extends Component, D extends JComponent>
69 72 implements ComponentPeer, DropTargetPeer
70 73 {
71 74 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");
72 75
73 76 /**
74 77 * State lock is to be used for modifications to this peer's fields (e.g.
75 78 * bounds, background, font, etc.) It should be the last lock in the lock
76 79 * chain
77 80 */
78 81 private final Object stateLock = new Object();
79 82
80 83 /**
81 84 * The lock to operate with the peers hierarchy. AWT tree lock is not used
82 85 * as there are many peers related ops to be done on the toolkit thread, and
83 86 * we don't want to depend on a public lock on this thread
84 87 */
85 88 private static final Object peerTreeLock = new Object();
86 89
87 90 /**
88 91 * The associated AWT object.
89 92 */
90 93 private final T target;
91 94
92 95 /**
93 96 * Container peer. It may not be the peer of the target's direct parent, for
94 97 * example, in the case of hw/lw mixing. However, let's skip this scenario
95 98 * for the time being. We also assume the container peer is not null, which
96 99 * might also be false if addNotify() is called for a component outside of
97 100 * the hierarchy. The exception is LWWindowPeers: their containers are
98 101 * always null
99 102 */
100 103 private final LWContainerPeer<?, ?> containerPeer;
101 104
102 105 /**
103 106 * Handy reference to the top-level window peer. Window peer is borrowed
104 107 * from the containerPeer in constructor, and should also be updated when
105 108 * the component is reparented to another container
106 109 */
107 110 private final LWWindowPeer windowPeer;
108 111
109 112 private final AtomicBoolean disposed = new AtomicBoolean(false);
110 113
111 114 // Bounds are relative to parent peer
112 115 private final Rectangle bounds = new Rectangle();
113 116 private Region region;
114 117
115 118 // Component state. Should be accessed under the state lock
116 119 private boolean visible = false;
117 120 private boolean enabled = true;
118 121
119 122 private Color background;
120 123 private Color foreground;
121 124 private Font font;
122 125
123 126 /**
124 127 * Paint area to coalesce all the paint events and store the target dirty
125 128 * area.
126 129 */
127 130 private final RepaintArea targetPaintArea;
128 131
129 132 // private volatile boolean paintPending;
130 133 private volatile boolean isLayouting;
131 134
132 135 private final D delegate;
133 136 private Container delegateContainer;
134 137 private Component delegateDropTarget;
135 138 private final Object dropTargetLock = new Object();
136 139
137 140 private int fNumDropTargets = 0;
138 141 private PlatformDropTarget fDropTarget = null;
139 142
140 143 private final PlatformComponent platformComponent;
141 144
142 145 /**
143 146 * Character with reasonable value between the minimum width and maximum.
144 147 */
145 148 static final char WIDE_CHAR = '0';
146 149
147 150 /**
148 151 * The back buffer provide user with a BufferStrategy.
149 152 */
150 153 private Image backBuffer;
151 154
152 155 /**
153 156 * All Swing delegates use delegateContainer as a parent. This container
154 157 * intentionally do not use parent of the peer.
155 158 */
156 159 @SuppressWarnings("serial")// Safe: outer class is non-serializable.
157 160 private final class DelegateContainer extends Container {
158 161 {
159 162 enableEvents(0xFFFFFFFF);
160 163 }
161 164
162 165 @Override
163 166 public boolean isLightweight() {
164 167 return false;
165 168 }
166 169
167 170 @Override
168 171 public Point getLocation() {
169 172 return getLocationOnScreen();
170 173 }
171 174
172 175 @Override
173 176 public Point getLocationOnScreen() {
174 177 return LWComponentPeer.this.getLocationOnScreen();
175 178 }
176 179
177 180 @Override
178 181 public int getX() {
179 182 return getLocation().x;
180 183 }
181 184
182 185 @Override
183 186 public int getY() {
184 187 return getLocation().y;
185 188 }
186 189 }
187 190
188 191 LWComponentPeer(final T target, final PlatformComponent platformComponent) {
189 192 targetPaintArea = new LWRepaintArea();
190 193 this.target = target;
191 194 this.platformComponent = platformComponent;
192 195
193 196 // Container peer is always null for LWWindowPeers, so
194 197 // windowPeer is always null for them as well. On the other
195 198 // hand, LWWindowPeer shouldn't use windowPeer at all
196 199 final Container container = SunToolkit.getNativeContainer(target);
197 200 containerPeer = (LWContainerPeer) LWToolkit.targetToPeer(container);
198 201 windowPeer = containerPeer != null ? containerPeer.getWindowPeerOrSelf()
199 202 : null;
200 203 // don't bother about z-order here as updateZOrder()
201 204 // will be called from addNotify() later anyway
202 205 if (containerPeer != null) {
203 206 containerPeer.addChildPeer(this);
204 207 }
205 208
206 209 // the delegate must be created after the target is set
207 210 AWTEventListener toolkitListener = null;
208 211 synchronized (Toolkit.getDefaultToolkit()) {
209 212 try {
210 213 toolkitListener = getToolkitAWTEventListener();
211 214 setToolkitAWTEventListener(null);
212 215
213 216 synchronized (getDelegateLock()) {
214 217 delegate = createDelegate();
215 218 if (delegate != null) {
216 219 delegate.setVisible(false);
217 220 delegateContainer = new DelegateContainer();
218 221 delegateContainer.add(delegate);
219 222 delegateContainer.addNotify();
220 223 delegate.addNotify();
221 224 resetColorsAndFont(delegate);
222 225 delegate.setOpaque(true);
223 226 } else {
224 227 return;
225 228 }
226 229 }
227 230
228 231 } finally {
229 232 setToolkitAWTEventListener(toolkitListener);
230 233 }
231 234
232 235 // todo swing: later on we will probably have one global RM
233 236 SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
234 237 @Override
235 238 public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
236 239 repaintPeer(SwingUtilities.convertRectangle(
237 240 c, new Rectangle(x, y, w, h), getDelegate()));
238 241 }
239 242 });
240 243 }
241 244 }
242 245
243 246 /**
244 247 * This method must be called under Toolkit.getDefaultToolkit() lock
245 248 * and followed by setToolkitAWTEventListener()
246 249 */
247 250 protected final AWTEventListener getToolkitAWTEventListener() {
248 251 return AccessController.doPrivileged(new PrivilegedAction<AWTEventListener>() {
249 252 public AWTEventListener run() {
250 253 Toolkit toolkit = Toolkit.getDefaultToolkit();
251 254 try {
252 255 Field field = Toolkit.class.getDeclaredField("eventListener");
253 256 field.setAccessible(true);
254 257 return (AWTEventListener) field.get(toolkit);
255 258 } catch (Exception e) {
256 259 throw new InternalError(e.toString());
257 260 }
258 261 }
259 262 });
260 263 }
261 264
262 265 protected final void setToolkitAWTEventListener(final AWTEventListener listener) {
263 266 AccessController.doPrivileged(new PrivilegedAction<Void>() {
264 267 public Void run() {
265 268 Toolkit toolkit = Toolkit.getDefaultToolkit();
266 269 try {
267 270 Field field = Toolkit.class.getDeclaredField("eventListener");
268 271 field.setAccessible(true);
269 272 field.set(toolkit, listener);
270 273 } catch (Exception e) {
271 274 throw new InternalError(e.toString());
272 275 }
273 276 return null;
274 277 }
275 278 });
276 279 }
277 280
278 281 /**
279 282 * This method is called under getDelegateLock().
280 283 * Overridden in subclasses.
281 284 */
282 285 D createDelegate() {
283 286 return null;
284 287 }
285 288
286 289 final D getDelegate() {
287 290 return delegate;
288 291 }
289 292
290 293 /**
291 294 * This method should be called under getDelegateLock().
292 295 */
293 296 Component getDelegateFocusOwner() {
294 297 return getDelegate();
295 298 }
296 299
297 300 /**
298 301 * Initializes this peer. The call to initialize() is not placed to
299 302 * LWComponentPeer ctor to let the subclass ctor to finish completely first.
300 303 * Instead, it's the LWToolkit object who is responsible for initialization.
301 304 * Note that we call setVisible() at the end of initialization.
302 305 */
303 306 public final void initialize() {
304 307 platformComponent.initialize(getPlatformWindow());
305 308 initializeImpl();
306 309 setVisible(target.isVisible());
307 310 }
308 311
309 312 /**
310 313 * Fetching general properties from the target. Should be overridden in
311 314 * subclasses to initialize specific peers properties.
312 315 */
313 316 void initializeImpl() {
314 317 // note that these methods can be overridden by the user and
315 318 // can return some strange values like null.
316 319 setBackground(target.getBackground());
317 320 setForeground(target.getForeground());
318 321 setFont(target.getFont());
319 322 setBounds(target.getBounds());
320 323 setEnabled(target.isEnabled());
321 324 }
322 325
323 326 private static void resetColorsAndFont(final Container c) {
324 327 c.setBackground(null);
325 328 c.setForeground(null);
326 329 c.setFont(null);
327 330 for (int i = 0; i < c.getComponentCount(); i++) {
328 331 resetColorsAndFont((Container) c.getComponent(i));
329 332 }
330 333 }
331 334
332 335 final Object getStateLock() {
333 336 return stateLock;
334 337 }
335 338
336 339 /**
337 340 * Synchronize all operations with the Swing delegates under AWT tree lock,
338 341 * using a new separate lock to synchronize access to delegates may lead
339 342 * deadlocks. Think of it as a 'virtual EDT'.
340 343 *
341 344 * @return DelegateLock
342 345 */
343 346 final Object getDelegateLock() {
344 347 return getTarget().getTreeLock();
345 348 }
346 349
347 350 protected static final Object getPeerTreeLock() {
348 351 return peerTreeLock;
349 352 }
350 353
351 354 public final T getTarget() {
352 355 return target;
353 356 }
354 357
355 358 // Just a helper method
356 359 // Returns the window peer or null if this is a window peer
357 360 protected final LWWindowPeer getWindowPeer() {
358 361 return windowPeer;
359 362 }
360 363
361 364 // Returns the window peer or 'this' if this is a window peer
362 365 protected LWWindowPeer getWindowPeerOrSelf() {
363 366 return getWindowPeer();
364 367 }
365 368
366 369 // Just a helper method
367 370 protected final LWContainerPeer<?, ?> getContainerPeer() {
368 371 return containerPeer;
369 372 }
370 373
371 374 public PlatformWindow getPlatformWindow() {
372 375 LWWindowPeer windowPeer = getWindowPeer();
373 376 return windowPeer.getPlatformWindow();
374 377 }
375 378
376 379 // ---- PEER METHODS ---- //
377 380
378 381 // Just a helper method
379 382 public LWToolkit getLWToolkit() {
380 383 return LWToolkit.getLWToolkit();
381 384 }
382 385
383 386 @Override
384 387 public final void dispose() {
385 388 if (disposed.compareAndSet(false, true)) {
386 389 disposeImpl();
387 390 }
388 391 }
389 392
390 393 protected void disposeImpl() {
391 394 destroyBuffers();
392 395 LWContainerPeer<?, ?> cp = getContainerPeer();
393 396 if (cp != null) {
394 397 cp.removeChildPeer(this);
395 398 }
396 399 platformComponent.dispose();
397 400 LWToolkit.targetDisposedPeer(getTarget(), this);
398 401 }
399 402
400 403 public final boolean isDisposed() {
401 404 return disposed.get();
402 405 }
403 406
404 407 /*
405 408 * GraphicsConfiguration is borrowed from the parent peer. The
406 409 * return value must not be null.
407 410 *
408 411 * Overridden in LWWindowPeer.
409 412 */
410 413 @Override
411 414 public GraphicsConfiguration getGraphicsConfiguration() {
412 415 // Don't check windowPeer for null as it can only happen
413 416 // for windows, but this method is overridden in
414 417 // LWWindowPeer and doesn't call super()
415 418 return getWindowPeer().getGraphicsConfiguration();
416 419 }
417 420
418 421
419 422 // Just a helper method
420 423 public final LWGraphicsConfig getLWGC() {
421 424 return (LWGraphicsConfig) getGraphicsConfiguration();
422 425 }
423 426
424 427 /*
425 428 * Overridden in LWWindowPeer to replace its surface
426 429 * data and back buffer.
427 430 */
428 431 @Override
429 432 public boolean updateGraphicsData(GraphicsConfiguration gc) {
430 433 // TODO: not implemented
431 434 // throw new RuntimeException("Has not been implemented yet.");
432 435 return false;
433 436 }
434 437
435 438 @Override
436 439 public Graphics getGraphics() {
437 440 final Graphics g = getOnscreenGraphics();
438 441 if (g != null) {
439 442 synchronized (getPeerTreeLock()){
440 443 applyConstrain(g);
441 444 }
442 445 }
443 446 return g;
444 447 }
445 448
446 449 /*
447 450 * Peer Graphics is borrowed from the parent peer, while
448 451 * foreground and background colors and font are specific to
449 452 * this peer.
450 453 */
451 454 public final Graphics getOnscreenGraphics() {
452 455 final LWWindowPeer wp = getWindowPeerOrSelf();
453 456 return wp.getOnscreenGraphics(getForeground(), getBackground(),
454 457 getFont());
455 458
456 459 }
457 460
458 461 private void applyConstrain(final Graphics g) {
459 462 final SunGraphics2D sg2d = (SunGraphics2D) g;
460 463 final Rectangle size = localToWindow(getSize());
461 464 sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion());
462 465 }
463 466
464 467 Region getVisibleRegion() {
465 468 return computeVisibleRect(this, getRegion());
466 469 }
467 470
468 471 static final Region computeVisibleRect(final LWComponentPeer<?, ?> c,
469 472 Region region) {
470 473 final LWContainerPeer<?, ?> p = c.getContainerPeer();
471 474 if (p != null) {
472 475 final Rectangle r = c.getBounds();
473 476 region = region.getTranslatedRegion(r.x, r.y);
474 477 region = region.getIntersection(p.getRegion());
475 478 region = region.getIntersection(p.getContentSize());
476 479 region = p.cutChildren(region, c);
477 480 region = computeVisibleRect(p, region);
478 481 region = region.getTranslatedRegion(-r.x, -r.y);
479 482 }
480 483 return region;
481 484 }
482 485
483 486 @Override
484 487 public ColorModel getColorModel() {
485 488 // Is it a correct implementation?
486 489 return getGraphicsConfiguration().getColorModel();
487 490 }
488 491
489 492 public boolean isTranslucent() {
490 493 // Translucent windows of the top level are supported only
491 494 return false;
492 495 }
493 496
494 497 @Override
495 498 public final void createBuffers(int numBuffers, BufferCapabilities caps)
496 499 throws AWTException {
497 500 getLWGC().assertOperationSupported(numBuffers, caps);
498 501 final Image buffer = getLWGC().createBackBuffer(this);
499 502 synchronized (getStateLock()) {
500 503 backBuffer = buffer;
501 504 }
502 505 }
503 506
504 507 @Override
505 508 public final Image getBackBuffer() {
506 509 synchronized (getStateLock()) {
507 510 if (backBuffer != null) {
508 511 return backBuffer;
509 512 }
510 513 }
511 514 throw new IllegalStateException("Buffers have not been created");
512 515 }
513 516
514 517 @Override
515 518 public final void flip(int x1, int y1, int x2, int y2,
516 519 BufferCapabilities.FlipContents flipAction) {
517 520 getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction);
518 521 }
519 522
520 523 @Override
521 524 public final void destroyBuffers() {
522 525 final Image oldBB;
523 526 synchronized (getStateLock()) {
524 527 oldBB = backBuffer;
525 528 backBuffer = null;
526 529 }
527 530 getLWGC().destroyBackBuffer(oldBB);
528 531 }
529 532
530 533 // Helper method
531 534 public void setBounds(Rectangle r) {
532 535 setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
533 536 }
534 537
535 538 /**
536 539 * This method could be called on the toolkit thread.
537 540 */
538 541 @Override
539 542 public void setBounds(int x, int y, int w, int h, int op) {
540 543 setBounds(x, y, w, h, op, true, false);
541 544 }
542 545
543 546 protected void setBounds(int x, int y, int w, int h, int op, boolean notify,
544 547 final boolean updateTarget) {
545 548 Rectangle oldBounds;
546 549 synchronized (getStateLock()) {
547 550 oldBounds = new Rectangle(bounds);
548 551 if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) {
549 552 bounds.x = x;
550 553 bounds.y = y;
551 554 }
552 555 if ((op & (SET_SIZE | SET_BOUNDS)) != 0) {
553 556 bounds.width = w;
554 557 bounds.height = h;
555 558 }
556 559 }
557 560 boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
558 561 boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
559 562 if (!moved && !resized) {
560 563 return;
561 564 }
562 565 final D delegate = getDelegate();
563 566 if (delegate != null) {
564 567 synchronized (getDelegateLock()) {
565 568 delegateContainer.setBounds(0, 0, w, h);
566 569 delegate.setBounds(delegateContainer.getBounds());
567 570 // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
568 571 delegate.validate();
569 572 }
570 573 }
571 574
572 575 final Point locationInWindow = localToWindow(0, 0);
573 576 platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,
574 577 h);
575 578 if (notify) {
576 579 repaintOldNewBounds(oldBounds);
577 580 if (resized) {
578 581 handleResize(w, h, updateTarget);
579 582 }
580 583 if (moved) {
581 584 handleMove(x, y, updateTarget);
582 585 }
583 586 }
584 587 }
585 588
586 589 public final Rectangle getBounds() {
587 590 synchronized (getStateLock()) {
588 591 // Return a copy to prevent subsequent modifications
589 592 return bounds.getBounds();
590 593 }
591 594 }
592 595
593 596 public final Rectangle getSize() {
594 597 synchronized (getStateLock()) {
595 598 // Return a copy to prevent subsequent modifications
596 599 return new Rectangle(bounds.width, bounds.height);
597 600 }
598 601 }
599 602
600 603 @Override
601 604 public Point getLocationOnScreen() {
602 605 Point windowLocation = getWindowPeer().getLocationOnScreen();
603 606 Point locationInWindow = localToWindow(0, 0);
604 607 return new Point(windowLocation.x + locationInWindow.x,
605 608 windowLocation.y + locationInWindow.y);
606 609 }
607 610
608 611 /**
609 612 * Returns the cursor of the peer, which is cursor of the target by default,
610 613 * but peer can override this behavior.
611 614 *
612 615 * @param p Point relative to the peer.
613 616 * @return Cursor of the peer or null if default cursor should be used.
614 617 */
615 618 Cursor getCursor(final Point p) {
616 619 return getTarget().getCursor();
617 620 }
618 621
619 622 @Override
620 623 public void setBackground(final Color c) {
621 624 final Color oldBg = getBackground();
622 625 if (oldBg == c || (oldBg != null && oldBg.equals(c))) {
623 626 return;
624 627 }
625 628 synchronized (getStateLock()) {
626 629 background = c;
627 630 }
628 631 final D delegate = getDelegate();
629 632 if (delegate != null) {
630 633 synchronized (getDelegateLock()) {
631 634 // delegate will repaint the target
632 635 delegate.setBackground(c);
633 636 }
634 637 } else {
635 638 repaintPeer();
636 639 }
637 640 }
638 641
639 642 public final Color getBackground() {
640 643 synchronized (getStateLock()) {
641 644 return background;
642 645 }
643 646 }
644 647
645 648 @Override
646 649 public void setForeground(final Color c) {
647 650 final Color oldFg = getForeground();
648 651 if (oldFg == c || (oldFg != null && oldFg.equals(c))) {
649 652 return;
650 653 }
651 654 synchronized (getStateLock()) {
652 655 foreground = c;
653 656 }
654 657 final D delegate = getDelegate();
655 658 if (delegate != null) {
656 659 synchronized (getDelegateLock()) {
657 660 // delegate will repaint the target
658 661 delegate.setForeground(c);
659 662 }
660 663 } else {
661 664 repaintPeer();
662 665 }
663 666 }
664 667
665 668 protected final Color getForeground() {
666 669 synchronized (getStateLock()) {
667 670 return foreground;
668 671 }
669 672 }
670 673
671 674 @Override
672 675 public void setFont(final Font f) {
673 676 final Font oldF = getFont();
674 677 if (oldF == f || (oldF != null && oldF.equals(f))) {
675 678 return;
676 679 }
677 680 synchronized (getStateLock()) {
678 681 font = f;
679 682 }
680 683 final D delegate = getDelegate();
681 684 if (delegate != null) {
682 685 synchronized (getDelegateLock()) {
683 686 // delegate will repaint the target
684 687 delegate.setFont(f);
685 688 }
686 689 } else {
687 690 repaintPeer();
688 691 }
689 692 }
690 693
691 694 protected final Font getFont() {
692 695 synchronized (getStateLock()) {
693 696 return font;
694 697 }
695 698 }
696 699
697 700 @Override
698 701 public FontMetrics getFontMetrics(final Font f) {
699 702 // Borrow the metrics from the top-level window
700 703 // return getWindowPeer().getFontMetrics(f);
701 704 // Obtain the metrics from the offscreen window where this peer is
702 705 // mostly drawn to.
703 706 // TODO: check for "use platform metrics" settings
704 707 final Graphics g = getOnscreenGraphics();
705 708 if (g != null) {
706 709 try {
707 710 return g.getFontMetrics(f);
708 711 } finally {
709 712 g.dispose();
710 713 }
711 714 }
712 715 synchronized (getDelegateLock()) {
713 716 return delegateContainer.getFontMetrics(f);
714 717 }
715 718 }
716 719
717 720 @Override
718 721 public void setEnabled(final boolean e) {
719 722 boolean status = e;
720 723 final LWComponentPeer<?, ?> cp = getContainerPeer();
721 724 if (cp != null) {
722 725 status &= cp.isEnabled();
723 726 }
724 727 synchronized (getStateLock()) {
725 728 if (enabled == status) {
726 729 return;
727 730 }
728 731 enabled = status;
729 732 }
730 733
731 734 final D delegate = getDelegate();
732 735
733 736 if (delegate != null) {
734 737 synchronized (getDelegateLock()) {
735 738 delegate.setEnabled(status);
736 739 }
737 740 } else {
738 741 repaintPeer();
739 742 }
740 743 }
741 744
742 745 // Helper method
743 746 public final boolean isEnabled() {
744 747 synchronized (getStateLock()) {
745 748 return enabled;
746 749 }
747 750 }
748 751
749 752 @Override
750 753 public void setVisible(final boolean v) {
751 754 synchronized (getStateLock()) {
752 755 if (visible == v) {
753 756 return;
754 757 }
755 758 visible = v;
756 759 }
757 760 setVisibleImpl(v);
758 761 }
759 762
760 763 protected void setVisibleImpl(final boolean v) {
761 764 final D delegate = getDelegate();
762 765
763 766 if (delegate != null) {
764 767 synchronized (getDelegateLock()) {
765 768 delegate.setVisible(v);
766 769 }
767 770 }
768 771 if (visible) {
769 772 repaintPeer();
770 773 } else {
771 774 repaintParent(getBounds());
772 775 }
773 776 }
774 777
775 778 // Helper method
776 779 public final boolean isVisible() {
777 780 synchronized (getStateLock()) {
778 781 return visible;
779 782 }
780 783 }
781 784
782 785 @Override
783 786 public void paint(final Graphics g) {
784 787 getTarget().paint(g);
785 788 }
786 789
787 790 @Override
788 791 public void print(final Graphics g) {
789 792 getTarget().print(g);
790 793 }
791 794
792 795 @Override
793 796 public void reparent(ContainerPeer newContainer) {
794 797 // TODO: not implemented
795 798 throw new UnsupportedOperationException("ComponentPeer.reparent()");
796 799 }
797 800
798 801 @Override
799 802 public boolean isReparentSupported() {
800 803 // TODO: not implemented
801 804 return false;
802 805 }
803 806
804 807 @Override
805 808 public void setZOrder(final ComponentPeer above) {
806 809 LWContainerPeer<?, ?> cp = getContainerPeer();
807 810 // Don't check containerPeer for null as it can only happen
808 811 // for windows, but this method is overridden in
809 812 // LWWindowPeer and doesn't call super()
810 813 cp.setChildPeerZOrder(this, (LWComponentPeer<?, ?>) above);
811 814 }
812 815
813 816 @Override
814 817 public void coalescePaintEvent(PaintEvent e) {
815 818 if (!(e instanceof IgnorePaintEvent)) {
816 819 Rectangle r = e.getUpdateRect();
817 820 if ((r != null) && !r.isEmpty()) {
818 821 targetPaintArea.add(r, e.getID());
819 822 }
820 823 }
821 824 }
822 825
823 826 /*
824 827 * Should be overridden in subclasses which use complex Swing components.
825 828 */
826 829 @Override
827 830 public void layout() {
828 831 // TODO: not implemented
829 832 }
830 833
831 834 @Override
832 835 public boolean isObscured() {
833 836 // TODO: not implemented
834 837 return false;
835 838 }
836 839
837 840 @Override
838 841 public boolean canDetermineObscurity() {
839 842 // TODO: not implemented
840 843 return false;
841 844 }
842 845
843 846 /**
844 847 * Determines the preferred size of the component. By default forwards the
845 848 * request to the Swing helper component. Should be overridden in subclasses
846 849 * if required.
847 850 */
848 851 @Override
849 852 public Dimension getPreferredSize() {
850 853 final Dimension size;
851 854 synchronized (getDelegateLock()) {
852 855 size = getDelegate().getPreferredSize();
853 856 }
854 857 return validateSize(size);
855 858 }
856 859
857 860 /**
858 861 * Determines the minimum size of the component. By default forwards the
859 862 * request to the Swing helper component. Should be overridden in subclasses
860 863 * if required.
861 864 */
862 865 @Override
863 866 public Dimension getMinimumSize() {
864 867 final Dimension size;
865 868 synchronized (getDelegateLock()) {
866 869 size = getDelegate().getMinimumSize();
867 870 }
868 871 return validateSize(size);
869 872 }
870 873
871 874 /**
872 875 * In some situations delegates can return empty minimum/preferred size.
873 876 * (For example: empty JLabel, etc), but awt components never should be
874 877 * empty. In the XPeers or WPeers we use some magic constants, but here we
875 878 * try to use something more useful,
876 879 */
877 880 private Dimension validateSize(final Dimension size) {
878 881 if (size.width == 0 || size.height == 0) {
879 882 final FontMetrics fm = getFontMetrics(getFont());
880 883 size.width = fm.charWidth(WIDE_CHAR);
881 884 size.height = fm.getHeight();
882 885 }
883 886 return size;
884 887 }
885 888
886 889 @Override
887 890 public void updateCursorImmediately() {
888 891 getLWToolkit().getCursorManager().updateCursor();
889 892 }
890 893
891 894 @Override
892 895 public boolean isFocusable() {
893 896 // Overridden in focusable subclasses like buttons
894 897 return false;
895 898 }
896 899
897 900 @Override
898 901 public boolean requestFocus(Component lightweightChild, boolean temporary,
899 902 boolean focusedWindowChangeAllowed, long time,
900 903 FocusEvent.Cause cause)
901 904 {
902 905 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
903 906 focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
904 907 ", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +
905 908 ", time= " + time + ", cause=" + cause);
906 909 }
907 910 if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(
908 911 getTarget(), lightweightChild, temporary,
909 912 focusedWindowChangeAllowed, time)) {
910 913 return true;
911 914 }
912 915
913 916 int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
914 917 getTarget(), lightweightChild, temporary,
915 918 focusedWindowChangeAllowed, time, cause);
916 919 switch (result) {
917 920 case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
918 921 return false;
919 922 case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
920 923 Window parentWindow = SunToolkit.getContainingWindow(getTarget());
921 924 if (parentWindow == null) {
922 925 focusLog.fine("request rejected, parentWindow is null");
923 926 LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
924 927 return false;
925 928 }
926 929 final LWWindowPeer parentPeer =
927 930 AWTAccessor.getComponentAccessor()
928 931 .getPeer(parentWindow);
929 932 if (parentPeer == null) {
930 933 focusLog.fine("request rejected, parentPeer is null");
931 934 LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
932 935 return false;
933 936 }
934 937
935 938 // A fix for 7145768. Ensure the parent window is currently natively focused.
936 939 // The more evident place to perform this check is in KFM.shouldNativelyFocusHeavyweight,
937 940 // however that is the shared code and this particular problem's reproducibility has
938 941 // platform specifics. So, it was decided to narrow down the fix to lwawt (OSX) in
939 942 // current release. TODO: consider fixing it in the shared code.
940 943 if (!focusedWindowChangeAllowed) {
941 944 LWWindowPeer decoratedPeer = parentPeer.isSimpleWindow() ?
942 945 LWWindowPeer.getOwnerFrameDialog(parentPeer) : parentPeer;
943 946
944 947 if (decoratedPeer == null || !decoratedPeer.getPlatformWindow().isActive()) {
945 948 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
946 949 focusLog.fine("request rejected, focusedWindowChangeAllowed==false, " +
947 950 "decoratedPeer is inactive: " + decoratedPeer);
948 951 }
949 952 LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
950 953 return false;
951 954 }
952 955 }
953 956
954 957 boolean res = parentPeer.requestWindowFocus(cause);
955 958 // If parent window can be made focused and has been made focused (synchronously)
956 959 // then we can proceed with children, otherwise we retreat
957 960 if (!res || !parentWindow.isFocused()) {
958 961 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
959 962 focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +
960 963 parentWindow.isFocused());
961 964 }
962 965 LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
963 966 return false;
964 967 }
965 968
966 969 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
967 970 Component focusOwner = kfmPeer.getCurrentFocusOwner();
968 971 return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
969 972 getTarget(), temporary,
970 973 focusedWindowChangeAllowed,
971 974 time, cause, focusOwner);
972 975
973 976 case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
974 977 return true;
975 978 }
976 979
977 980 return false;
978 981 }
979 982
980 983 @Override
981 984 public final Image createImage(final ImageProducer producer) {
982 985 return new ToolkitImage(producer);
983 986 }
984 987
985 988 @Override
986 989 public final Image createImage(final int width, final int height) {
987 990 return getLWGC().createAcceleratedImage(getTarget(), width, height);
988 991 }
989 992
990 993 @Override
991 994 public final VolatileImage createVolatileImage(final int w, final int h) {
992 995 return new SunVolatileImage(getTarget(), w, h);
993 996 }
994 997
995 998 @Override
996 999 public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
997 1000 // TODO: is it a right/complete implementation?
998 1001 return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
999 1002 }
1000 1003
1001 1004 @Override
1002 1005 public int checkImage(Image img, int w, int h, ImageObserver o) {
1003 1006 // TODO: is it a right/complete implementation?
1004 1007 return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
1005 1008 }
1006 1009
1007 1010 @Override
1008 1011 public boolean handlesWheelScrolling() {
1009 1012 // TODO: not implemented
1010 1013 return false;
1011 1014 }
1012 1015
1013 1016 @Override
1014 1017 public final void applyShape(final Region shape) {
1015 1018 synchronized (getStateLock()) {
1016 1019 if (region == shape || (region != null && region.equals(shape))) {
1017 1020 return;
1018 1021 }
1019 1022 }
1020 1023 applyShapeImpl(shape);
1021 1024 }
1022 1025
1023 1026 void applyShapeImpl(final Region shape) {
1024 1027 synchronized (getStateLock()) {
1025 1028 if (shape != null) {
1026 1029 region = Region.WHOLE_REGION.getIntersection(shape);
1027 1030 } else {
1028 1031 region = null;
1029 1032 }
1030 1033 }
1031 1034 repaintParent(getBounds());
1032 1035 }
1033 1036
1034 1037 protected final Region getRegion() {
1035 1038 synchronized (getStateLock()) {
1036 1039 return isShaped() ? region : Region.getInstance(getSize());
1037 1040 }
1038 1041 }
1039 1042
1040 1043 public boolean isShaped() {
1041 1044 synchronized (getStateLock()) {
1042 1045 return region != null;
1043 1046 }
1044 1047 }
1045 1048
1046 1049 // DropTargetPeer Method
1047 1050 @Override
1048 1051 public void addDropTarget(DropTarget dt) {
1049 1052 LWWindowPeer winPeer = getWindowPeerOrSelf();
1050 1053 if (winPeer != null && winPeer != this) {
1051 1054 // We need to register the DropTarget in the
1052 1055 // peer of the window ancestor of the component
1053 1056 winPeer.addDropTarget(dt);
1054 1057 } else {
1055 1058 synchronized (dropTargetLock) {
1056 1059 // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
1057 1060 // if it's the first (or last) one for the component. Otherwise this call is a no-op.
1058 1061 if (++fNumDropTargets == 1) {
1059 1062 // Having a non-null drop target would be an error but let's check just in case:
1060 1063 if (fDropTarget != null) {
1061 1064 throw new IllegalStateException("Current drop target is not null");
1062 1065 }
1063 1066 // Create a new drop target:
1064 1067 fDropTarget = LWToolkit.getLWToolkit().createDropTarget(dt, target, this);
1065 1068 }
1066 1069 }
1067 1070 }
1068 1071 }
1069 1072
1070 1073 // DropTargetPeer Method
1071 1074 @Override
1072 1075 public void removeDropTarget(DropTarget dt) {
1073 1076 LWWindowPeer winPeer = getWindowPeerOrSelf();
1074 1077 if (winPeer != null && winPeer != this) {
1075 1078 // We need to unregister the DropTarget in the
1076 1079 // peer of the window ancestor of the component
1077 1080 winPeer.removeDropTarget(dt);
1078 1081 } else {
1079 1082 synchronized (dropTargetLock){
1080 1083 // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
1081 1084 // if it's the first (or last) one for the component. Otherwise this call is a no-op.
1082 1085 if (--fNumDropTargets == 0) {
1083 1086 // Having a null drop target would be an error but let's check just in case:
1084 1087 if (fDropTarget != null) {
1085 1088 // Dispose of the drop target:
1086 1089 fDropTarget.dispose();
1087 1090 fDropTarget = null;
1088 1091 } else
1089 1092 System.err.println("CComponent.removeDropTarget(): current drop target is null.");
1090 1093 }
1091 1094 }
1092 1095 }
1093 1096 }
1094 1097
1095 1098 // ---- PEER NOTIFICATIONS ---- //
1096 1099
1097 1100 /**
1098 1101 * Called when this peer's location has been changed either as a result
1099 1102 * of target.setLocation() or as a result of user actions (window is
1100 1103 * dragged with mouse).
1101 1104 *
1102 1105 * This method could be called on the toolkit thread.
1103 1106 */
1104 1107 protected final void handleMove(final int x, final int y,
1105 1108 final boolean updateTarget) {
1106 1109 if (updateTarget) {
1107 1110 AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
1108 1111 }
1109 1112 postEvent(new ComponentEvent(getTarget(),
1110 1113 ComponentEvent.COMPONENT_MOVED));
1111 1114 }
1112 1115
1113 1116 /**
1114 1117 * Called when this peer's size has been changed either as a result of
1115 1118 * target.setSize() or as a result of user actions (window is resized).
1116 1119 *
1117 1120 * This method could be called on the toolkit thread.
1118 1121 */
1119 1122 protected final void handleResize(final int w, final int h,
1120 1123 final boolean updateTarget) {
1121 1124 Image oldBB = null;
1122 1125 synchronized (getStateLock()) {
1123 1126 if (backBuffer != null) {
1124 1127 oldBB = backBuffer;
1125 1128 backBuffer = getLWGC().createBackBuffer(this);
1126 1129 }
1127 1130 }
1128 1131 getLWGC().destroyBackBuffer(oldBB);
1129 1132
1130 1133 if (updateTarget) {
1131 1134 AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
1132 1135 }
1133 1136 postEvent(new ComponentEvent(getTarget(),
1134 1137 ComponentEvent.COMPONENT_RESIZED));
1135 1138 }
1136 1139
1137 1140 protected final void repaintOldNewBounds(final Rectangle oldB) {
1138 1141 repaintParent(oldB);
1139 1142 repaintPeer(getSize());
1140 1143 }
1141 1144
1142 1145 protected final void repaintParent(final Rectangle oldB) {
1143 1146 final LWContainerPeer<?, ?> cp = getContainerPeer();
1144 1147 if (cp != null) {
1145 1148 // Repaint unobscured part of the parent
1146 1149 cp.repaintPeer(cp.getContentSize().intersection(oldB));
1147 1150 }
1148 1151 }
1149 1152
1150 1153 // ---- EVENTS ---- //
1151 1154
1152 1155 /**
1153 1156 * Post an event to the proper Java EDT.
1154 1157 */
1155 1158 public void postEvent(final AWTEvent event) {
1156 1159 LWToolkit.postEvent(event);
1157 1160 }
1158 1161
1159 1162 protected void postPaintEvent(int x, int y, int w, int h) {
1160 1163 // TODO: call getIgnoreRepaint() directly with the right ACC
1161 1164 if (AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {
1162 1165 return;
1163 1166 }
1164 1167 PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
1165 1168 createPaintEvent(getTarget(), x, y, w, h);
1166 1169 if (event != null) {
1167 1170 postEvent(event);
1168 1171 }
1169 1172 }
1170 1173
1171 1174 /*
1172 1175 * Gives a chance for the peer to handle the event after it's been
1173 1176 * processed by the target.
1174 1177 */
1175 1178 @Override
1176 1179 public void handleEvent(AWTEvent e) {
1177 1180 if ((e instanceof InputEvent) && ((InputEvent) e).isConsumed()) {
1178 1181 return;
1179 1182 }
1180 1183 switch (e.getID()) {
1181 1184 case FocusEvent.FOCUS_GAINED:
1182 1185 case FocusEvent.FOCUS_LOST:
1183 1186 handleJavaFocusEvent((FocusEvent) e);
1184 1187 break;
1185 1188 case PaintEvent.PAINT:
1186 1189 // Got a native paint event
1187 1190 // paintPending = false;
1188 1191 // fall through to the next statement
1189 1192 case PaintEvent.UPDATE:
1190 1193 handleJavaPaintEvent();
1191 1194 break;
1192 1195 case MouseEvent.MOUSE_PRESSED:
1193 1196 handleJavaMouseEvent((MouseEvent)e);
1194 1197 }
1195 1198
1196 1199 sendEventToDelegate(e);
1197 1200 }
1198 1201
1199 1202 protected void sendEventToDelegate(final AWTEvent e) {
1200 1203 if (getDelegate() == null || !isShowing() || !isEnabled()) {
1201 1204 return;
1202 1205 }
1203 1206 synchronized (getDelegateLock()) {
1204 1207 AWTEvent delegateEvent = createDelegateEvent(e);
1205 1208 if (delegateEvent != null) {
1206 1209 AWTAccessor.getComponentAccessor()
1207 1210 .processEvent((Component) delegateEvent.getSource(),
1208 1211 delegateEvent);
1209 1212 if (delegateEvent instanceof KeyEvent) {
1210 1213 KeyEvent ke = (KeyEvent) delegateEvent;
1211 1214 SwingUtilities.processKeyBindings(ke);
1212 1215 }
1213 1216 }
1214 1217 }
1215 1218 }
1216 1219
1217 1220 /**
1218 1221 * Changes the target of the AWTEvent from awt component to appropriate
1219 1222 * swing delegate.
1220 1223 */
1221 1224 @SuppressWarnings("deprecation")
1222 1225 private AWTEvent createDelegateEvent(final AWTEvent e) {
1223 1226 // TODO modifiers should be changed to getModifiers()|getModifiersEx()?
1224 1227 AWTEvent delegateEvent = null;
1225 1228 if (e instanceof MouseWheelEvent) {
1226 1229 MouseWheelEvent me = (MouseWheelEvent) e;
1227 1230 delegateEvent = new MouseWheelEvent(
1228 1231 delegate, me.getID(), me.getWhen(),
1229 1232 me.getModifiers(),
1230 1233 me.getX(), me.getY(),
1231 1234 me.getXOnScreen(), me.getYOnScreen(),
1232 1235 me.getClickCount(),
1233 1236 me.isPopupTrigger(),
1234 1237 me.getScrollType(),
1235 1238 me.getScrollAmount(),
1236 1239 me.getWheelRotation(),
1237 1240 me.getPreciseWheelRotation());
1238 1241 } else if (e instanceof MouseEvent) {
1239 1242 MouseEvent me = (MouseEvent) e;
1240 1243
1241 1244 Component eventTarget = SwingUtilities.getDeepestComponentAt(delegate, me.getX(), me.getY());
1242 1245
1243 1246 if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
1244 1247 if (delegateDropTarget == null) {
1245 1248 delegateDropTarget = eventTarget;
1246 1249 } else {
1247 1250 eventTarget = delegateDropTarget;
1248 1251 }
1249 1252 }
1250 1253 if (me.getID() == MouseEvent.MOUSE_RELEASED && delegateDropTarget != null) {
1251 1254 eventTarget = delegateDropTarget;
1252 1255 delegateDropTarget = null;
1253 1256 }
1254 1257 if (eventTarget == null) {
1255 1258 eventTarget = delegate;
1256 1259 }
1257 1260 delegateEvent = SwingUtilities.convertMouseEvent(getTarget(), me, eventTarget);
1258 1261 } else if (e instanceof KeyEvent) {
1259 1262 KeyEvent ke = (KeyEvent) e;
1260 1263 delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(),
1261 1264 ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation());
1262 1265 AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent,
1263 1266 ke.getExtendedKeyCode());
1264 1267 } else if (e instanceof FocusEvent) {
1265 1268 FocusEvent fe = (FocusEvent) e;
1266 1269 delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary());
1267 1270 }
1268 1271 return delegateEvent;
1269 1272 }
1270 1273
1271 1274 protected void handleJavaMouseEvent(MouseEvent e) {
1272 1275 Component target = getTarget();
1273 1276 assert (e.getSource() == target);
1274 1277
1275 1278 if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
1276 1279 LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
1277 1280 }
1278 1281 }
1279 1282
1280 1283 /**
1281 1284 * Handler for FocusEvents.
1282 1285 */
1283 1286 void handleJavaFocusEvent(final FocusEvent e) {
1284 1287 // Note that the peer receives all the FocusEvents from
1285 1288 // its lightweight children as well
1286 1289 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
1287 1290 kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);
1288 1291 }
1289 1292
1290 1293 /**
1291 1294 * All peers should clear background before paint.
1292 1295 *
1293 1296 * @return false on components that DO NOT require a clearRect() before
1294 1297 * painting.
1295 1298 */
1296 1299 protected final boolean shouldClearRectBeforePaint() {
1297 1300 // TODO: sun.awt.noerasebackground
1298 1301 return true;
1299 1302 }
1300 1303
1301 1304 /**
1302 1305 * Handler for PAINT and UPDATE PaintEvents.
1303 1306 */
1304 1307 private void handleJavaPaintEvent() {
1305 1308 // Skip all painting while layouting and all UPDATEs
1306 1309 // while waiting for native paint
1307 1310 // if (!isLayouting && !paintPending) {
1308 1311 if (!isLayouting()) {
1309 1312 targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());
1310 1313 }
1311 1314 }
1312 1315
1313 1316 // ---- UTILITY METHODS ---- //
1314 1317
1315 1318 /**
1316 1319 * Finds a top-most visible component for the given point. The location is
1317 1320 * specified relative to the peer's parent.
1318 1321 */
1319 1322 LWComponentPeer<?, ?> findPeerAt(final int x, final int y) {
1320 1323 final Rectangle r = getBounds();
1321 1324 final Region sh = getRegion();
1322 1325 final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);
1323 1326 return found ? this : null;
1324 1327 }
1325 1328
1326 1329 /*
1327 1330 * Translated the given point in Window coordinates to the point in
1328 1331 * coordinates local to this component. The given window peer must be
1329 1332 * the window where this component is in.
1330 1333 */
1331 1334 public Point windowToLocal(int x, int y, LWWindowPeer wp) {
1332 1335 return windowToLocal(new Point(x, y), wp);
1333 1336 }
1334 1337
1335 1338 public Point windowToLocal(Point p, LWWindowPeer wp) {
1336 1339 LWComponentPeer<?, ?> cp = this;
1337 1340 while (cp != wp) {
1338 1341 Rectangle cpb = cp.getBounds();
1339 1342 p.x -= cpb.x;
1340 1343 p.y -= cpb.y;
1341 1344 cp = cp.getContainerPeer();
1342 1345 }
1343 1346 // Return a copy to prevent subsequent modifications
1344 1347 return new Point(p);
1345 1348 }
1346 1349
1347 1350 public Rectangle windowToLocal(Rectangle r, LWWindowPeer wp) {
1348 1351 Point p = windowToLocal(r.getLocation(), wp);
1349 1352 return new Rectangle(p, r.getSize());
1350 1353 }
1351 1354
1352 1355 public Point localToWindow(int x, int y) {
1353 1356 return localToWindow(new Point(x, y));
1354 1357 }
1355 1358
1356 1359 public Point localToWindow(Point p) {
1357 1360 LWComponentPeer<?, ?> cp = getContainerPeer();
1358 1361 Rectangle r = getBounds();
1359 1362 while (cp != null) {
1360 1363 p.x += r.x;
1361 1364 p.y += r.y;
1362 1365 r = cp.getBounds();
1363 1366 cp = cp.getContainerPeer();
1364 1367 }
1365 1368 // Return a copy to prevent subsequent modifications
1366 1369 return new Point(p);
1367 1370 }
1368 1371
1369 1372 public Rectangle localToWindow(Rectangle r) {
1370 1373 Point p = localToWindow(r.getLocation());
1371 1374 return new Rectangle(p, r.getSize());
1372 1375 }
1373 1376
1374 1377 public final void repaintPeer() {
1375 1378 repaintPeer(getSize());
1376 1379 }
1377 1380
1378 1381 void repaintPeer(final Rectangle r) {
1379 1382 final Rectangle toPaint = getSize().intersection(r);
1380 1383 if (!isShowing() || toPaint.isEmpty()) {
1381 1384 return;
1382 1385 }
1383 1386
1384 1387 postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
1385 1388 }
1386 1389
1387 1390 /**
1388 1391 * Determines whether this peer is showing on screen. This means that the
1389 1392 * peer must be visible, and it must be in a container that is visible and
1390 1393 * showing.
1391 1394 *
1392 1395 * @see #isVisible()
1393 1396 */
1394 1397 protected final boolean isShowing() {
1395 1398 synchronized (getPeerTreeLock()) {
1396 1399 if (isVisible()) {
1397 1400 final LWContainerPeer<?, ?> container = getContainerPeer();
1398 1401 return (container == null) || container.isShowing();
1399 1402 }
1400 1403 }
1401 1404 return false;
1402 1405 }
1403 1406
1404 1407 /**
1405 1408 * Paints the peer. Delegate the actual painting to Swing components.
1406 1409 */
1407 1410 protected final void paintPeer(final Graphics g) {
1408 1411 final D delegate = getDelegate();
1409 1412 if (delegate != null) {
1410 1413 if (!SwingUtilities.isEventDispatchThread()) {
↓ open down ↓ |
1341 lines elided |
↑ open up ↑ |
1411 1414 throw new InternalError("Painting must be done on EDT");
1412 1415 }
1413 1416 synchronized (getDelegateLock()) {
1414 1417 // JComponent.print() is guaranteed to not affect the double buffer
1415 1418 getDelegate().print(g);
1416 1419 }
1417 1420 }
1418 1421 }
1419 1422
1420 1423 protected static final void flushOnscreenGraphics(){
1421 - final OGLRenderQueue rq = OGLRenderQueue.getInstance();
1424 + RenderQueue rq = MacOSFlags.isMetalEnabled() ?
1425 + MTLRenderQueue.getInstance() : OGLRenderQueue.getInstance();
1422 1426 rq.lock();
1423 1427 try {
1424 1428 rq.flushNow();
1425 1429 } finally {
1426 1430 rq.unlock();
1427 1431 }
1428 1432 }
1429 1433
1430 1434 /**
1431 1435 * Used by ContainerPeer to skip all the paint events during layout.
1432 1436 *
1433 1437 * @param isLayouting layouting state.
1434 1438 */
1435 1439 protected final void setLayouting(final boolean isLayouting) {
1436 1440 this.isLayouting = isLayouting;
1437 1441 }
1438 1442
1439 1443 /**
1440 1444 * Returns layouting state. Used by ComponentPeer to skip all the paint
1441 1445 * events during layout.
1442 1446 *
1443 1447 * @return true during layout, false otherwise.
1444 1448 */
1445 1449 private boolean isLayouting() {
1446 1450 return isLayouting;
1447 1451 }
1448 1452 }
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX