1 /*
2  * Copyright (c) 1996, 2014, 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 package sun.awt.windows;
26 
27 import java.awt.*;
28 import java.awt.peer.*;
29 import java.awt.image.VolatileImage;
30 import sun.awt.RepaintArea;
31 import sun.awt.CausedFocusEvent;
32 import sun.awt.image.SunVolatileImage;
33 import sun.awt.image.ToolkitImage;
34 import java.awt.image.BufferedImage;
35 import java.awt.image.ImageProducer;
36 import java.awt.image.ImageObserver;
37 import java.awt.image.ColorModel;
38 import java.awt.event.PaintEvent;
39 import java.awt.event.InvocationEvent;
40 import java.awt.event.KeyEvent;
41 import java.awt.event.FocusEvent;
42 import java.awt.event.MouseEvent;
43 import java.awt.event.MouseWheelEvent;
44 import java.awt.event.InputEvent;
45 import sun.awt.Win32GraphicsConfig;
46 import sun.awt.Win32GraphicsEnvironment;
47 import sun.java2d.InvalidPipeException;
48 import sun.java2d.SurfaceData;
49 import sun.java2d.ScreenUpdateManager;
50 import sun.java2d.d3d.D3DSurfaceData;
51 import sun.java2d.opengl.OGLSurfaceData;
52 import sun.java2d.pipe.Region;
53 import sun.awt.PaintEventDispatcher;
54 import sun.awt.SunToolkit;
55 import sun.awt.event.IgnorePaintEvent;
56 
57 import java.awt.dnd.DropTarget;
58 import java.awt.dnd.peer.DropTargetPeer;
59 import sun.awt.AWTAccessor;
60 
61 import sun.util.logging.PlatformLogger;
62 
63 public abstract class WComponentPeer extends WObjectPeer
64     implements ComponentPeer, DropTargetPeer
65 {
66     /**
67      * Handle to native window
68      */
69     protected volatile long hwnd;
70 
71     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WComponentPeer");
72     private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.windows.shape.WComponentPeer");
73     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.windows.focus.WComponentPeer");
74 
75     // ComponentPeer implementation
76     SurfaceData surfaceData;
77 
78     private RepaintArea paintArea;
79 
80     protected Win32GraphicsConfig winGraphicsConfig;
81 
82     boolean isLayouting = false;
83     boolean paintPending = false;
84     int     oldWidth = -1;
85     int     oldHeight = -1;
86     private int numBackBuffers = 0;
87     private VolatileImage backBuffer = null;
88     private BufferCapabilities backBufferCaps = null;
89 
90     // foreground, background and color are cached to avoid calling back
91     // into the Component.
92     private Color foreground;
93     private Color background;
94     private Font font;
95 
96     @Override
isObscured()97     public native boolean isObscured();
98     @Override
canDetermineObscurity()99     public boolean canDetermineObscurity() { return true; }
100 
101     // DropTarget support
102 
103     int nDropTargets;
104     long nativeDropTargetContext; // native pointer
105 
pShow()106     private synchronized native void pShow();
hide()107     synchronized native void hide();
enable()108     synchronized native void enable();
disable()109     synchronized native void disable();
110 
getHWnd()111     public long getHWnd() {
112         return hwnd;
113     }
114 
115     /* New 1.1 API */
116     @Override
getLocationOnScreen()117     public native Point getLocationOnScreen();
118 
119     /* New 1.1 API */
120     @Override
setVisible(boolean b)121     public void setVisible(boolean b) {
122         if (b) {
123             show();
124         } else {
125             hide();
126         }
127     }
128 
show()129     public void show() {
130         Dimension s = ((Component)target).getSize();
131         oldHeight = s.height;
132         oldWidth = s.width;
133         pShow();
134     }
135 
136     /* New 1.1 API */
137     @Override
setEnabled(boolean b)138     public void setEnabled(boolean b) {
139         if (b) {
140             enable();
141         } else {
142             disable();
143         }
144     }
145 
146     public int serialNum = 0;
147 
reshapeNoCheck(int x, int y, int width, int height)148     private native void reshapeNoCheck(int x, int y, int width, int height);
149 
150     /* New 1.1 API */
151     @Override
setBounds(int x, int y, int width, int height, int op)152     public void setBounds(int x, int y, int width, int height, int op) {
153         // Should set paintPending before reahape to prevent
154         // thread race between paint events
155         // Native components do redraw after resize
156         paintPending = (width != oldWidth) || (height != oldHeight);
157 
158         if ( (op & NO_EMBEDDED_CHECK) != 0 ) {
159             reshapeNoCheck(x, y, width, height);
160         } else {
161             reshape(x, y, width, height);
162         }
163         if ((width != oldWidth) || (height != oldHeight)) {
164             // Only recreate surfaceData if this setBounds is called
165             // for a resize; a simple move should not trigger a recreation
166             try {
167                 replaceSurfaceData();
168             } catch (InvalidPipeException e) {
169                 // REMIND : what do we do if our surface creation failed?
170             }
171             oldWidth = width;
172             oldHeight = height;
173         }
174 
175         serialNum++;
176     }
177 
178     /*
179      * Called from native code (on Toolkit thread) in order to
180      * dynamically layout the Container during resizing
181      */
dynamicallyLayoutContainer()182     void dynamicallyLayoutContainer() {
183         // If we got the WM_SIZING, this must be a Container, right?
184         // In fact, it must be the top-level Container.
185         if (log.isLoggable(PlatformLogger.Level.FINE)) {
186             Container parent = WToolkit.getNativeContainer((Component)target);
187             if (parent != null) {
188                 log.fine("Assertion (parent == null) failed");
189             }
190         }
191         final Container cont = (Container)target;
192 
193         WToolkit.executeOnEventHandlerThread(cont, new Runnable() {
194             @Override
195             public void run() {
196                 // Discarding old paint events doesn't seem to be necessary.
197                 cont.invalidate();
198                 cont.validate();
199 
200                 if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData ||
201                     surfaceData instanceof OGLSurfaceData)
202                 {
203                     // When OGL or D3D is enabled, it is necessary to
204                     // replace the SurfaceData for each dynamic layout
205                     // request so that the viewport stays in sync
206                     // with the window bounds.
207                     try {
208                         replaceSurfaceData();
209                     } catch (InvalidPipeException e) {
210                         // REMIND: this is unlikely to occur for OGL, but
211                         // what do we do if surface creation fails?
212                     }
213                 }
214 
215                 // Forcing a paint here doesn't seem to be necessary.
216                 // paintDamagedAreaImmediately();
217             }
218         });
219     }
220 
221     /*
222      * Paints any portion of the component that needs updating
223      * before the call returns (similar to the Win32 API UpdateWindow)
224      */
paintDamagedAreaImmediately()225     void paintDamagedAreaImmediately() {
226         // force Windows to send any pending WM_PAINT events so
227         // the damage area is updated on the Java side
228         updateWindow();
229         // make sure paint events are transferred to main event queue
230         // for coalescing
231         SunToolkit.flushPendingEvents();
232         // paint the damaged area
233         paintArea.paint(target, shouldClearRectBeforePaint());
234     }
235 
updateWindow()236     native synchronized void updateWindow();
237 
238     @Override
paint(Graphics g)239     public void paint(Graphics g) {
240         ((Component)target).paint(g);
241     }
242 
repaint(long tm, int x, int y, int width, int height)243     public void repaint(long tm, int x, int y, int width, int height) {
244     }
245 
246     private static final double BANDING_DIVISOR = 4.0;
createPrintedPixels(int srcX, int srcY, int srcW, int srcH, int alpha)247     private native int[] createPrintedPixels(int srcX, int srcY,
248                                              int srcW, int srcH,
249                                              int alpha);
250     @Override
print(Graphics g)251     public void print(Graphics g) {
252 
253         Component comp = (Component)target;
254 
255         // To conserve memory usage, we will band the image.
256 
257         int totalW = comp.getWidth();
258         int totalH = comp.getHeight();
259 
260         int hInc = (int)(totalH / BANDING_DIVISOR);
261         if (hInc == 0) {
262             hInc = totalH;
263         }
264 
265         for (int startY = 0; startY < totalH; startY += hInc) {
266             int endY = startY + hInc - 1;
267             if (endY >= totalH) {
268                 endY = totalH - 1;
269             }
270             int h = endY - startY + 1;
271 
272             Color bgColor = comp.getBackground();
273             int[] pix = createPrintedPixels(0, startY, totalW, h,
274                                             bgColor == null ? 255 : bgColor.getAlpha());
275             if (pix != null) {
276                 BufferedImage bim = new BufferedImage(totalW, h,
277                                               BufferedImage.TYPE_INT_ARGB);
278                 bim.setRGB(0, 0, totalW, h, pix, 0, totalW);
279                 g.drawImage(bim, 0, startY, null);
280                 bim.flush();
281             }
282         }
283 
284         comp.print(g);
285     }
286 
287     @Override
coalescePaintEvent(PaintEvent e)288     public void coalescePaintEvent(PaintEvent e) {
289         Rectangle r = e.getUpdateRect();
290         if (!(e instanceof IgnorePaintEvent)) {
291             paintArea.add(r, e.getID());
292         }
293 
294         if (log.isLoggable(PlatformLogger.Level.FINEST)) {
295             switch(e.getID()) {
296             case PaintEvent.UPDATE:
297                 log.finest("coalescePaintEvent: UPDATE: add: x = " +
298                     r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
299                 return;
300             case PaintEvent.PAINT:
301                 log.finest("coalescePaintEvent: PAINT: add: x = " +
302                     r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
303                 return;
304             }
305         }
306     }
307 
reshape(int x, int y, int width, int height)308     public synchronized native void reshape(int x, int y, int width, int height);
309 
310     // returns true if the event has been handled and shouldn't be propagated
311     // though handleEvent method chain - e.g. WTextFieldPeer returns true
312     // on handling '\n' to prevent it from being passed to native code
handleJavaKeyEvent(KeyEvent e)313     public boolean handleJavaKeyEvent(KeyEvent e) { return false; }
314 
handleJavaMouseEvent(MouseEvent e)315     public void handleJavaMouseEvent(MouseEvent e) {
316         switch (e.getID()) {
317           case MouseEvent.MOUSE_PRESSED:
318               // Note that Swing requests focus in its own mouse event handler.
319               if (target == e.getSource() &&
320                   !((Component)target).isFocusOwner() &&
321                   WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target))
322               {
323                   WKeyboardFocusManagerPeer.requestFocusFor((Component)target,
324                                                             CausedFocusEvent.Cause.MOUSE_EVENT);
325               }
326               break;
327         }
328     }
329 
nativeHandleEvent(AWTEvent e)330     native void nativeHandleEvent(AWTEvent e);
331 
332     @Override
333     @SuppressWarnings("fallthrough")
handleEvent(AWTEvent e)334     public void handleEvent(AWTEvent e) {
335         int id = e.getID();
336 
337         if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() &&
338             ((Component)target).isEnabled())
339         {
340             if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) {
341                 handleJavaMouseEvent((MouseEvent) e);
342             } else if (e instanceof KeyEvent) {
343                 if (handleJavaKeyEvent((KeyEvent)e)) {
344                     return;
345                 }
346             }
347         }
348 
349         switch(id) {
350             case PaintEvent.PAINT:
351                 // Got native painting
352                 paintPending = false;
353                 // Fallthrough to next statement
354             case PaintEvent.UPDATE:
355                 // Skip all painting while layouting and all UPDATEs
356                 // while waiting for native paint
357                 if (!isLayouting && ! paintPending) {
358                     paintArea.paint(target,shouldClearRectBeforePaint());
359                 }
360                 return;
361             case FocusEvent.FOCUS_LOST:
362             case FocusEvent.FOCUS_GAINED:
363                 handleJavaFocusEvent((FocusEvent)e);
364             default:
365             break;
366         }
367 
368         // Call the native code
369         nativeHandleEvent(e);
370     }
371 
handleJavaFocusEvent(FocusEvent fe)372     void handleJavaFocusEvent(FocusEvent fe) {
373         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
374             focusLog.finer(fe.toString());
375         }
376         setFocus(fe.getID() == FocusEvent.FOCUS_GAINED);
377     }
378 
setFocus(boolean doSetFocus)379     native void setFocus(boolean doSetFocus);
380 
381     @Override
getMinimumSize()382     public Dimension getMinimumSize() {
383         return ((Component)target).getSize();
384     }
385 
386     @Override
getPreferredSize()387     public Dimension getPreferredSize() {
388         return getMinimumSize();
389     }
390 
391     // Do nothing for heavyweight implementation
392     @Override
layout()393     public void layout() {}
394 
getBounds()395     public Rectangle getBounds() {
396         return ((Component)target).getBounds();
397     }
398 
399     @Override
isFocusable()400     public boolean isFocusable() {
401         return false;
402     }
403 
404     /*
405      * Return the GraphicsConfiguration associated with this peer, either
406      * the locally stored winGraphicsConfig, or that of the target Component.
407      */
408     @Override
getGraphicsConfiguration()409     public GraphicsConfiguration getGraphicsConfiguration() {
410         if (winGraphicsConfig != null) {
411             return winGraphicsConfig;
412         }
413         else {
414             // we don't need a treelock here, since
415             // Component.getGraphicsConfiguration() gets it itself.
416             return ((Component)target).getGraphicsConfiguration();
417         }
418     }
419 
getSurfaceData()420     public SurfaceData getSurfaceData() {
421         return surfaceData;
422     }
423 
424     /**
425      * Creates new surfaceData object and invalidates the previous
426      * surfaceData object.
427      * Replacing the surface data should never lock on any resources which are
428      * required by other threads which may have them and may require
429      * the tree-lock.
430      * This is a degenerate version of replaceSurfaceData(numBackBuffers), so
431      * just call that version with our current numBackBuffers.
432      */
replaceSurfaceData()433     public void replaceSurfaceData() {
434         replaceSurfaceData(this.numBackBuffers, this.backBufferCaps);
435     }
436 
createScreenSurface(boolean isResize)437     public void createScreenSurface(boolean isResize)
438     {
439         Win32GraphicsConfig gc = (Win32GraphicsConfig)getGraphicsConfiguration();
440         ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
441 
442         surfaceData = mgr.createScreenSurface(gc, this, numBackBuffers, isResize);
443     }
444 
445 
446     /**
447      * Multi-buffer version of replaceSurfaceData.  This version is called
448      * by createBuffers(), which needs to acquire the same locks in the same
449      * order, but also needs to perform additional functions inside the
450      * locks.
451      */
replaceSurfaceData(int newNumBackBuffers, BufferCapabilities caps)452     public void replaceSurfaceData(int newNumBackBuffers,
453                                    BufferCapabilities caps)
454     {
455         SurfaceData oldData = null;
456         VolatileImage oldBB = null;
457         synchronized(((Component)target).getTreeLock()) {
458             synchronized(this) {
459                 if (pData == 0) {
460                     return;
461                 }
462                 numBackBuffers = newNumBackBuffers;
463                 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
464                 oldData = surfaceData;
465                 mgr.dropScreenSurface(oldData);
466                 createScreenSurface(true);
467                 if (oldData != null) {
468                     oldData.invalidate();
469                 }
470 
471                 oldBB = backBuffer;
472                 if (numBackBuffers > 0) {
473                     // set the caps first, they're used when creating the bb
474                     backBufferCaps = caps;
475                     Win32GraphicsConfig gc =
476                         (Win32GraphicsConfig)getGraphicsConfiguration();
477                     backBuffer = gc.createBackBuffer(this);
478                 } else if (backBuffer != null) {
479                     backBufferCaps = null;
480                     backBuffer = null;
481                 }
482             }
483         }
484         // it would be better to do this before we create new ones,
485         // but then we'd run into deadlock issues
486         if (oldData != null) {
487             oldData.flush();
488             // null out the old data to make it collected faster
489             oldData = null;
490         }
491         if (oldBB != null) {
492             oldBB.flush();
493             // null out the old data to make it collected faster
494             oldData = null;
495         }
496     }
497 
replaceSurfaceDataLater()498     public void replaceSurfaceDataLater() {
499         Runnable r = new Runnable() {
500             @Override
501             public void run() {
502                 // Shouldn't do anything if object is disposed in meanwhile
503                 // No need for sync as disposeAction in Window is performed
504                 // on EDT
505                 if (!isDisposed()) {
506                     try {
507                         replaceSurfaceData();
508                     } catch (InvalidPipeException e) {
509                         // REMIND : what do we do if our surface creation failed?
510                     }
511                 }
512             }
513         };
514         Component c = (Component)target;
515         // Fix 6255371.
516         if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) {
517             postEvent(new InvocationEvent(c, r));
518         }
519     }
520 
521     @Override
updateGraphicsData(GraphicsConfiguration gc)522     public boolean updateGraphicsData(GraphicsConfiguration gc) {
523         winGraphicsConfig = (Win32GraphicsConfig)gc;
524         try {
525             replaceSurfaceData();
526         } catch (InvalidPipeException e) {
527             // REMIND : what do we do if our surface creation failed?
528         }
529         return false;
530     }
531 
532     //This will return null for Components not yet added to a Container
533     @Override
getColorModel()534     public ColorModel getColorModel() {
535         GraphicsConfiguration gc = getGraphicsConfiguration();
536         if (gc != null) {
537             return gc.getColorModel();
538         }
539         else {
540             return null;
541         }
542     }
543 
544     //This will return null for Components not yet added to a Container
getDeviceColorModel()545     public ColorModel getDeviceColorModel() {
546         Win32GraphicsConfig gc =
547             (Win32GraphicsConfig)getGraphicsConfiguration();
548         if (gc != null) {
549             return gc.getDeviceColorModel();
550         }
551         else {
552             return null;
553         }
554     }
555 
556     //Returns null for Components not yet added to a Container
getColorModel(int transparency)557     public ColorModel getColorModel(int transparency) {
558 //      return WToolkit.config.getColorModel(transparency);
559         GraphicsConfiguration gc = getGraphicsConfiguration();
560         if (gc != null) {
561             return gc.getColorModel(transparency);
562         }
563         else {
564             return null;
565         }
566     }
567 
568     // fallback default font object
569     final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
570 
571     @Override
572     @SuppressWarnings("deprecation")
getGraphics()573     public Graphics getGraphics() {
574         if (isDisposed()) {
575             return null;
576         }
577 
578         Component target = (Component)getTarget();
579         Window window = SunToolkit.getContainingWindow(target);
580         if (window != null) {
581             Graphics g =
582                 ((WWindowPeer)window.getPeer()).getTranslucentGraphics();
583             // getTranslucentGraphics() returns non-null value for non-opaque windows only
584             if (g != null) {
585                 // Non-opaque windows do not support heavyweight children.
586                 // Redirect all painting to the Window's Graphics instead.
587                 // The caller is responsible for calling the
588                 // WindowPeer.updateWindow() after painting has finished.
589                 int x = 0, y = 0;
590                 for (Component c = target; c != window; c = c.getParent()) {
591                     x += c.getX();
592                     y += c.getY();
593                 }
594 
595                 g.translate(x, y);
596                 g.clipRect(0, 0, target.getWidth(), target.getHeight());
597 
598                 return g;
599             }
600         }
601 
602         SurfaceData surfaceData = this.surfaceData;
603         if (surfaceData != null) {
604             /* Fix for bug 4746122. Color and Font shouldn't be null */
605             Color bgColor = background;
606             if (bgColor == null) {
607                 bgColor = SystemColor.window;
608             }
609             Color fgColor = foreground;
610             if (fgColor == null) {
611                 fgColor = SystemColor.windowText;
612             }
613             Font font = this.font;
614             if (font == null) {
615                 font = defaultFont;
616             }
617             ScreenUpdateManager mgr =
618                 ScreenUpdateManager.getInstance();
619             return mgr.createGraphics(surfaceData, this, fgColor,
620                                       bgColor, font);
621         }
622         return null;
623     }
624     @Override
getFontMetrics(Font font)625     public FontMetrics getFontMetrics(Font font) {
626         return WFontMetrics.getFontMetrics(font);
627     }
628 
_dispose()629     private synchronized native void _dispose();
630     @Override
disposeImpl()631     protected void disposeImpl() {
632         SurfaceData oldData = surfaceData;
633         surfaceData = null;
634         ScreenUpdateManager.getInstance().dropScreenSurface(oldData);
635         oldData.invalidate();
636         // remove from updater before calling targetDisposedPeer
637         WToolkit.targetDisposedPeer(target, this);
638         _dispose();
639     }
640 
disposeLater()641     public void disposeLater() {
642         postEvent(new InvocationEvent(target, new Runnable() {
643             @Override
644             public void run() {
645                 dispose();
646             }
647         }));
648     }
649 
650     @Override
setForeground(Color c)651     public synchronized void setForeground(Color c) {
652         foreground = c;
653         _setForeground(c.getRGB());
654     }
655 
656     @Override
setBackground(Color c)657     public synchronized void setBackground(Color c) {
658         background = c;
659         _setBackground(c.getRGB());
660     }
661 
662     /**
663      * This method is intentionally not synchronized as it is called while
664      * holding other locks.
665      *
666      * @see sun.java2d.d3d.D3DScreenUpdateManager#validate(D3DWindowSurfaceData)
667      */
getBackgroundNoSync()668     public Color getBackgroundNoSync() {
669         return background;
670     }
671 
_setForeground(int rgb)672     private native void _setForeground(int rgb);
_setBackground(int rgb)673     private native void _setBackground(int rgb);
674 
675     @Override
setFont(Font f)676     public synchronized void setFont(Font f) {
677         font = f;
678         _setFont(f);
679     }
_setFont(Font f)680     synchronized native void _setFont(Font f);
681     @Override
updateCursorImmediately()682     public void updateCursorImmediately() {
683         WGlobalCursorManager.getCursorManager().updateCursorImmediately();
684     }
685 
686     // TODO: consider moving it to KeyboardFocusManagerPeerImpl
687     @Override
688     @SuppressWarnings("deprecation")
requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)689     public boolean requestFocus(Component lightweightChild, boolean temporary,
690                                 boolean focusedWindowChangeAllowed, long time,
691                                 CausedFocusEvent.Cause cause)
692     {
693         if (WKeyboardFocusManagerPeer.
694             processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
695                                                   focusedWindowChangeAllowed, time))
696         {
697             return true;
698         }
699 
700         int result = WKeyboardFocusManagerPeer
701             .shouldNativelyFocusHeavyweight((Component)target, lightweightChild,
702                                             temporary, focusedWindowChangeAllowed,
703                                             time, cause);
704 
705         switch (result) {
706           case WKeyboardFocusManagerPeer.SNFH_FAILURE:
707               return false;
708           case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
709               if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
710                   focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target);
711               }
712               Window parentWindow = SunToolkit.getContainingWindow((Component)target);
713               if (parentWindow == null) {
714                   return rejectFocusRequestHelper("WARNING: Parent window is null");
715               }
716               WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer();
717               if (wpeer == null) {
718                   return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
719               }
720               boolean res = wpeer.requestWindowFocus(cause);
721 
722               if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
723                   focusLog.finer("Requested window focus: " + res);
724               }
725               // If parent window can be made focused and has been made focused(synchronously)
726               // then we can proceed with children, otherwise we retreat.
727               if (!(res && parentWindow.isFocused())) {
728                   return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
729               }
730               return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
731                                                             (Component)target,
732                                                             temporary,
733                                                             focusedWindowChangeAllowed,
734                                                             time, cause);
735 
736           case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
737               // Either lightweight or excessive request - all events are generated.
738               return true;
739         }
740         return false;
741     }
742 
rejectFocusRequestHelper(String logMsg)743     private boolean rejectFocusRequestHelper(String logMsg) {
744         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
745             focusLog.finer(logMsg);
746         }
747         WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target);
748         return false;
749     }
750 
751     @Override
createImage(ImageProducer producer)752     public Image createImage(ImageProducer producer) {
753         return new ToolkitImage(producer);
754     }
755 
756     @Override
createImage(int width, int height)757     public Image createImage(int width, int height) {
758         Win32GraphicsConfig gc =
759             (Win32GraphicsConfig)getGraphicsConfiguration();
760         return gc.createAcceleratedImage((Component)target, width, height);
761     }
762 
763     @Override
createVolatileImage(int width, int height)764     public VolatileImage createVolatileImage(int width, int height) {
765         return new SunVolatileImage((Component)target, width, height);
766     }
767 
768     @Override
prepareImage(Image img, int w, int h, ImageObserver o)769     public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
770         return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
771     }
772 
773     @Override
checkImage(Image img, int w, int h, ImageObserver o)774     public int checkImage(Image img, int w, int h, ImageObserver o) {
775         return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
776     }
777 
778     // Object overrides
779 
toString()780     public String toString() {
781         return getClass().getName() + "[" + target + "]";
782     }
783 
784     // Toolkit & peer internals
785 
786     private int updateX1, updateY1, updateX2, updateY2;
787 
WComponentPeer(Component target)788     WComponentPeer(Component target) {
789         this.target = target;
790         this.paintArea = new RepaintArea();
791         create(getNativeParent());
792         // fix for 5088782: check if window object is created successfully
793         checkCreation();
794 
795         createScreenSurface(false);
796         initialize();
797         start();  // Initialize enable/disable state, turn on callbacks
798     }
create(WComponentPeer parent)799     abstract void create(WComponentPeer parent);
800 
801     /**
802      * Gets the native parent of this peer. We use the term "parent" explicitly,
803      * because we override the method in top-level window peer implementations.
804      *
805      * @return the parent container/owner of this peer.
806      */
getNativeParent()807     WComponentPeer getNativeParent() {
808         Container parent = SunToolkit.getNativeContainer((Component) target);
809         return (WComponentPeer) WToolkit.targetToPeer(parent);
810     }
811 
checkCreation()812     protected void checkCreation()
813     {
814         if ((hwnd == 0) || (pData == 0))
815         {
816             if (createError != null)
817             {
818                 throw createError;
819             }
820             else
821             {
822                 throw new InternalError("couldn't create component peer");
823             }
824         }
825     }
826 
start()827     synchronized native void start();
828 
initialize()829     void initialize() {
830         if (((Component)target).isVisible()) {
831             show();  // the wnd starts hidden
832         }
833         Color fg = ((Component)target).getForeground();
834         if (fg != null) {
835             setForeground(fg);
836         }
837         // Set background color in C++, to avoid inheriting a parent's color.
838         Font  f = ((Component)target).getFont();
839         if (f != null) {
840             setFont(f);
841         }
842         if (! ((Component)target).isEnabled()) {
843             disable();
844         }
845         Rectangle r = ((Component)target).getBounds();
846         setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
847     }
848 
849     // Callbacks for window-system events to the frame
850 
851     // Invoke a update() method call on the target
handleRepaint(int x, int y, int w, int h)852     void handleRepaint(int x, int y, int w, int h) {
853         // Repaints are posted from updateClient now...
854     }
855 
856     // Invoke a paint() method call on the target, after clearing the
857     // damaged area.
handleExpose(int x, int y, int w, int h)858     void handleExpose(int x, int y, int w, int h) {
859         // Bug ID 4081126 & 4129709 - can't do the clearRect() here,
860         // since it interferes with the java thread working in the
861         // same window on multi-processor NT machines.
862 
863         postPaintIfNecessary(x, y, w, h);
864     }
865 
866     /* Invoke a paint() method call on the target, without clearing the
867      * damaged area.  This is normally called by a native control after
868      * it has painted itself.
869      *
870      * NOTE: This is called on the privileged toolkit thread. Do not
871      *       call directly into user code using this thread!
872      */
handlePaint(int x, int y, int w, int h)873     public void handlePaint(int x, int y, int w, int h) {
874         postPaintIfNecessary(x, y, w, h);
875     }
876 
postPaintIfNecessary(int x, int y, int w, int h)877     private void postPaintIfNecessary(int x, int y, int w, int h) {
878         if ( !AWTAccessor.getComponentAccessor().getIgnoreRepaint( (Component) target) ) {
879             PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
880                 createPaintEvent((Component)target, x, y, w, h);
881             if (event != null) {
882                 postEvent(event);
883             }
884         }
885     }
886 
887     /*
888      * Post an event. Queue it for execution by the callback thread.
889      */
postEvent(AWTEvent event)890     void postEvent(AWTEvent event) {
891         preprocessPostEvent(event);
892         WToolkit.postEvent(WToolkit.targetToAppContext(target), event);
893     }
894 
preprocessPostEvent(AWTEvent event)895     void preprocessPostEvent(AWTEvent event) {}
896 
897     // Routines to support deferred window positioning.
beginLayout()898     public void beginLayout() {
899         // Skip all painting till endLayout
900         isLayouting = true;
901     }
902 
endLayout()903     public void endLayout() {
904         if(!paintArea.isEmpty() && !paintPending &&
905             !((Component)target).getIgnoreRepaint()) {
906             // if not waiting for native painting repaint damaged area
907             postEvent(new PaintEvent((Component)target, PaintEvent.PAINT,
908                           new Rectangle()));
909         }
910         isLayouting = false;
911     }
912 
beginValidate()913     public native void beginValidate();
endValidate()914     public native void endValidate();
915 
916     /**
917      * DEPRECATED
918      */
preferredSize()919     public Dimension preferredSize() {
920         return getPreferredSize();
921     }
922 
923     /**
924      * register a DropTarget with this native peer
925      */
926 
927     @Override
addDropTarget(DropTarget dt)928     public synchronized void addDropTarget(DropTarget dt) {
929         if (nDropTargets == 0) {
930             nativeDropTargetContext = addNativeDropTarget();
931         }
932         nDropTargets++;
933     }
934 
935     /**
936      * unregister a DropTarget with this native peer
937      */
938 
939     @Override
removeDropTarget(DropTarget dt)940     public synchronized void removeDropTarget(DropTarget dt) {
941         nDropTargets--;
942         if (nDropTargets == 0) {
943             removeNativeDropTarget();
944             nativeDropTargetContext = 0;
945         }
946     }
947 
948     /**
949      * add the native peer's AwtDropTarget COM object
950      * @return reference to AwtDropTarget object
951      */
952 
addNativeDropTarget()953     native long addNativeDropTarget();
954 
955     /**
956      * remove the native peer's AwtDropTarget COM object
957      */
958 
removeNativeDropTarget()959     native void removeNativeDropTarget();
nativeHandlesWheelScrolling()960     native boolean nativeHandlesWheelScrolling();
961 
962     @Override
handlesWheelScrolling()963     public boolean handlesWheelScrolling() {
964         // should this be cached?
965         return nativeHandlesWheelScrolling();
966     }
967 
968     // Returns true if we are inside begin/endLayout and
969     // are waiting for native painting
isPaintPending()970     public boolean isPaintPending() {
971         return paintPending && isLayouting;
972     }
973 
974     /**
975      * The following multibuffering-related methods delegate to our
976      * associated GraphicsConfig (Win or WGL) to handle the appropriate
977      * native windowing system specific actions.
978      */
979 
980     @Override
createBuffers(int numBuffers, BufferCapabilities caps)981     public void createBuffers(int numBuffers, BufferCapabilities caps)
982         throws AWTException
983     {
984         Win32GraphicsConfig gc =
985             (Win32GraphicsConfig)getGraphicsConfiguration();
986         gc.assertOperationSupported((Component)target, numBuffers, caps);
987 
988         // Re-create the primary surface with the new number of back buffers
989         try {
990             replaceSurfaceData(numBuffers - 1, caps);
991         } catch (InvalidPipeException e) {
992             throw new AWTException(e.getMessage());
993         }
994     }
995 
996     @Override
destroyBuffers()997     public void destroyBuffers() {
998         replaceSurfaceData(0, null);
999     }
1000 
1001     @Override
flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction)1002     public void flip(int x1, int y1, int x2, int y2,
1003                                   BufferCapabilities.FlipContents flipAction)
1004     {
1005         VolatileImage backBuffer = this.backBuffer;
1006         if (backBuffer == null) {
1007             throw new IllegalStateException("Buffers have not been created");
1008         }
1009         Win32GraphicsConfig gc =
1010             (Win32GraphicsConfig)getGraphicsConfiguration();
1011         gc.flip(this, (Component)target, backBuffer, x1, y1, x2, y2, flipAction);
1012     }
1013 
1014     @Override
getBackBuffer()1015     public synchronized Image getBackBuffer() {
1016         Image backBuffer = this.backBuffer;
1017         if (backBuffer == null) {
1018             throw new IllegalStateException("Buffers have not been created");
1019         }
1020         return backBuffer;
1021     }
getBackBufferCaps()1022     public BufferCapabilities getBackBufferCaps() {
1023         return backBufferCaps;
1024     }
getBackBuffersNum()1025     public int getBackBuffersNum() {
1026         return numBackBuffers;
1027     }
1028 
1029     /* override and return false on components that DO NOT require
1030        a clearRect() before painting (i.e. native components) */
shouldClearRectBeforePaint()1031     public boolean shouldClearRectBeforePaint() {
1032         return true;
1033     }
1034 
pSetParent(ComponentPeer newNativeParent)1035     native void pSetParent(ComponentPeer newNativeParent);
1036 
1037     /**
1038      * @see java.awt.peer.ComponentPeer#reparent
1039      */
1040     @Override
reparent(ContainerPeer newNativeParent)1041     public void reparent(ContainerPeer newNativeParent) {
1042         pSetParent(newNativeParent);
1043     }
1044 
1045     /**
1046      * @see java.awt.peer.ComponentPeer#isReparentSupported
1047      */
1048     @Override
isReparentSupported()1049     public boolean isReparentSupported() {
1050         return true;
1051     }
1052 
setBoundsOperation(int operation)1053     public void setBoundsOperation(int operation) {
1054     }
1055 
1056     private volatile boolean isAccelCapable = true;
1057 
1058     /**
1059      * Returns whether this component is capable of being hw accelerated.
1060      * More specifically, whether rendering to this component or a
1061      * BufferStrategy's back-buffer for this component can be hw accelerated.
1062      *
1063      * Conditions which could prevent hw acceleration include the toplevel
1064      * window containing this component being
1065      * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
1066      * PERPIXEL_TRANSLUCENT}.
1067      *
1068      * Another condition is if Xor paint mode was detected when rendering
1069      * to an on-screen accelerated surface associated with this peer.
1070      * in this case both on- and off-screen acceleration for this peer is
1071      * disabled.
1072      *
1073      * @return {@code true} if this component is capable of being hw
1074      * accelerated, {@code false} otherwise
1075      * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
1076      */
isAccelCapable()1077     public boolean isAccelCapable() {
1078         if (!isAccelCapable ||
1079             !isContainingTopLevelAccelCapable((Component)target))
1080         {
1081             return false;
1082         }
1083 
1084         boolean isTranslucent =
1085             SunToolkit.isContainingTopLevelTranslucent((Component)target);
1086         // D3D/OGL and translucent windows interacted poorly in Windows XP;
1087         // these problems are no longer present in Vista
1088         return !isTranslucent || Win32GraphicsEnvironment.isVistaOS();
1089     }
1090 
1091     /**
1092      * Disables acceleration for this peer.
1093      */
disableAcceleration()1094     public void disableAcceleration() {
1095         isAccelCapable = false;
1096     }
1097 
1098 
setRectangularShape(int lox, int loy, int hix, int hiy, Region region)1099     native void setRectangularShape(int lox, int loy, int hix, int hiy,
1100                      Region region);
1101 
1102 
1103     // REMIND: Temp workaround for issues with using HW acceleration
1104     // in the browser on Vista when DWM is enabled.
1105     // @return true if the toplevel container is not an EmbeddedFrame or
1106     // if this EmbeddedFrame is acceleration capable, false otherwise
1107     @SuppressWarnings("deprecation")
isContainingTopLevelAccelCapable(Component c)1108     private static final boolean isContainingTopLevelAccelCapable(Component c) {
1109         while (c != null && !(c instanceof WEmbeddedFrame)) {
1110             c = c.getParent();
1111         }
1112         if (c == null) {
1113             return true;
1114         }
1115         return ((WEmbeddedFramePeer)c.getPeer()).isAccelCapable();
1116     }
1117 
1118     /**
1119      * Applies the shape to the native component window.
1120      * @since 1.7
1121      */
1122     @Override
1123     @SuppressWarnings("deprecation")
applyShape(Region shape)1124     public void applyShape(Region shape) {
1125         if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1126             shapeLog.finer("*** INFO: Setting shape: PEER: " + this
1127                             + "; TARGET: " + target
1128                             + "; SHAPE: " + shape);
1129         }
1130 
1131         if (shape != null) {
1132             setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(),
1133                     (shape.isRectangular() ? null : shape));
1134         } else {
1135             setRectangularShape(0, 0, 0, 0, null);
1136         }
1137     }
1138 
1139     /**
1140      * Lowers this component at the bottom of the above component. If the above parameter
1141      * is null then the method places this component at the top of the Z-order.
1142      */
1143     @Override
setZOrder(ComponentPeer above)1144     public void setZOrder(ComponentPeer above) {
1145         long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0;
1146 
1147         setZOrder(aboveHWND);
1148     }
1149 
setZOrder(long above)1150     private native void setZOrder(long above);
1151 
isLightweightFramePeer()1152     public boolean isLightweightFramePeer() {
1153         return false;
1154     }
1155 }
1156