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 
26 #include "awt_Toolkit.h"
27 #include "awt_Canvas.h"
28 #include "awt_Win32GraphicsConfig.h"
29 #include "awt_Window.h"
30 
31 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
32  */
33 
34 // Struct for _SetEraseBackground() method
35 struct SetEraseBackgroundStruct {
36     jobject canvas;
37     jboolean doErase;
38     jboolean doEraseOnResize;
39 };
40 
41 /************************************************************************
42  * AwtCanvas methods
43  */
44 
AwtCanvas()45 AwtCanvas::AwtCanvas() {
46     m_eraseBackground = JNI_TRUE;
47     m_eraseBackgroundOnResize = JNI_TRUE;
48 }
49 
~AwtCanvas()50 AwtCanvas::~AwtCanvas() {
51 }
52 
GetClassName()53 LPCTSTR AwtCanvas::GetClassName() {
54     return TEXT("SunAwtCanvas");
55 }
56 
57 /*
58  * Create a new AwtCanvas object and window.
59  */
Create(jobject self,jobject hParent)60 AwtCanvas* AwtCanvas::Create(jobject self, jobject hParent)
61 {
62     DASSERT(AwtToolkit::IsMainThread());
63     TRY;
64     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
65 
66     jobject target = NULL;
67     jobject graphicsConfig = NULL;
68     jclass canvasClass = NULL;
69     jclass win32cls = NULL;
70 
71     AwtCanvas *canvas = NULL;
72 
73     try {
74         if (env->EnsureLocalCapacity(1) < 0) {
75             return NULL;
76         }
77 
78         PDATA pData;
79         AwtComponent* parent;
80 
81         JNI_CHECK_PEER_GOTO(hParent, done);
82         parent = (AwtCanvas*)pData;
83 
84         target = env->GetObjectField(self, AwtObject::targetID);
85         JNI_CHECK_NULL_GOTO(target, "null target", done);
86 
87         canvas = new AwtCanvas();
88 
89         {
90             jint x = env->GetIntField(target, AwtComponent::xID);
91             jint y = env->GetIntField(target, AwtComponent::yID);
92             jint width = env->GetIntField(target, AwtComponent::widthID);
93             jint height = env->GetIntField(target, AwtComponent::heightID);
94 
95             canvas->CreateHWnd(env, L"",
96                                WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0,
97                                x, y, width, height,
98                                parent->GetHWnd(),
99                                NULL,
100                                ::GetSysColor(COLOR_WINDOWTEXT),
101                                ::GetSysColor(COLOR_WINDOW),
102                                self);
103 
104         // Set the pixel format of the HWND if a GraphicsConfiguration
105         // was provided to the Canvas constructor.
106 
107         canvasClass = env->FindClass("java/awt/Canvas");
108         DASSERT(canvasClass != NULL);
109         if (!canvasClass) {
110             throw std::bad_alloc();
111         }
112 
113         if ( env->IsInstanceOf( target, canvasClass ) ) {
114 
115             // Get GraphicsConfig from our target
116             graphicsConfig = env->GetObjectField(target,
117                 AwtComponent::graphicsConfigID);
118             if (graphicsConfig != NULL) {
119 
120                 win32cls = env->FindClass("sun/awt/Win32GraphicsConfig");
121                 DASSERT (win32cls != NULL);
122                 if (!win32cls) {
123                     throw std::bad_alloc();
124                 }
125 
126                 if ( env->IsInstanceOf( graphicsConfig, win32cls ) ) {
127                     // Get the visual ID member from our GC
128                     jint visual = env->GetIntField(graphicsConfig,
129                           AwtWin32GraphicsConfig::win32GCVisualID);
130                     if (visual > 0) {
131                         HDC hdc = ::GetDC(canvas->m_hwnd);
132                         // Set our pixel format
133                         PIXELFORMATDESCRIPTOR pfd;
134                         BOOL ret = ::SetPixelFormat(hdc, (int)visual, &pfd);
135                         ::ReleaseDC(canvas->m_hwnd, hdc);
136                         //Since a GraphicsConfiguration was specified, we should
137                         //throw an exception if the PixelFormat couldn't be set.
138                         if (ret == FALSE) {
139                             DASSERT(!safe_ExceptionOccurred(env));
140                             jclass excCls = env->FindClass(
141                              "java/lang/RuntimeException");
142                             DASSERT(excCls);
143                             env->ExceptionClear();
144                             env->ThrowNew(excCls,
145                              "\nUnable to set Pixel format on Canvas");
146                             env->DeleteLocalRef(excCls);
147                         }
148                     }
149                 }
150             }
151         }
152     }
153     } catch (...) {
154         env->DeleteLocalRef(target);
155         env->DeleteLocalRef(graphicsConfig);
156         env->DeleteLocalRef(canvasClass);
157         env->DeleteLocalRef(win32cls);
158 
159         env->DeleteGlobalRef(self);
160         env->DeleteGlobalRef(hParent);
161         throw;
162     }
163 
164 done:
165     env->DeleteLocalRef(target);
166     env->DeleteLocalRef(graphicsConfig);
167     env->DeleteLocalRef(canvasClass);
168     env->DeleteLocalRef(win32cls);
169     return canvas;
170     CATCH_BAD_ALLOC_RET(0);
171 }
172 
WmEraseBkgnd(HDC hDC,BOOL & didErase)173 MsgRouting AwtCanvas::WmEraseBkgnd(HDC hDC, BOOL& didErase)
174 {
175     if (m_eraseBackground ||
176         (m_eraseBackgroundOnResize && AwtWindow::IsResizing()))
177     {
178        RECT     rc;
179        ::GetClipBox(hDC, &rc);
180        ::FillRect(hDC, &rc, this->GetBackgroundBrush());
181     }
182 
183     didErase = TRUE;
184     return mrConsume;
185 }
186 
187 /*
188  * This routine is duplicated in AwtWindow.
189  */
WmPaint(HDC)190 MsgRouting AwtCanvas::WmPaint(HDC)
191 {
192     PaintUpdateRgn(NULL);
193     return mrConsume;
194 }
195 
HandleEvent(MSG * msg,BOOL synthetic)196 MsgRouting AwtCanvas::HandleEvent(MSG *msg, BOOL synthetic)
197 {
198     if (IsFocusingMouseMessage(msg)) {
199         delete msg;
200         return mrConsume;
201     }
202     return AwtComponent::HandleEvent(msg, synthetic);
203 }
204 
_SetEraseBackground(void * param)205 void AwtCanvas::_SetEraseBackground(void *param)
206 {
207     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
208 
209     SetEraseBackgroundStruct *sebs = (SetEraseBackgroundStruct *)param;
210     jobject canvas = sebs->canvas;
211     jboolean doErase = sebs->doErase;
212     jboolean doEraseOnResize = sebs->doEraseOnResize;
213 
214     PDATA pData;
215     JNI_CHECK_PEER_GOTO(canvas, ret);
216 
217     AwtCanvas *c = (AwtCanvas*)pData;
218     c->m_eraseBackground = doErase;
219     c->m_eraseBackgroundOnResize = doEraseOnResize;
220 
221 ret:
222     env->DeleteGlobalRef(canvas);
223     delete sebs;
224 }
225 
226 
227 /************************************************************************
228  * WCanvasPeer native methods
229  */
230 
231 extern "C" {
232 
233 JNIEXPORT void JNICALL
Java_sun_awt_windows_WCanvasPeer_create(JNIEnv * env,jobject self,jobject parent)234 Java_sun_awt_windows_WCanvasPeer_create(JNIEnv *env, jobject self,
235                                         jobject parent)
236 {
237     TRY;
238 
239     AwtToolkit::CreateComponent(self, parent,
240                                 (AwtToolkit::ComponentFactory)
241                                 AwtCanvas::Create);
242 
243     CATCH_BAD_ALLOC;
244 }
245 
246 /*
247  * Class:     sun_awt_windows_WCanvasPeer
248  * Method:    setNativeBackgroundErase
249  * Signature: (Z)V
250  */
251  JNIEXPORT void JNICALL
Java_sun_awt_windows_WCanvasPeer_setNativeBackgroundErase(JNIEnv * env,jobject self,jboolean doErase,jboolean doEraseOnResize)252  Java_sun_awt_windows_WCanvasPeer_setNativeBackgroundErase(JNIEnv *env,
253                                                            jobject self,
254                                                            jboolean doErase,
255                                                            jboolean doEraseOnResize)
256 {
257     TRY;
258 
259     SetEraseBackgroundStruct *sebs = new SetEraseBackgroundStruct;
260     sebs->canvas = env->NewGlobalRef(self);
261     sebs->doErase = doErase;
262     sebs->doEraseOnResize = doEraseOnResize;
263 
264     AwtToolkit::GetInstance().SyncCall(AwtCanvas::_SetEraseBackground, sebs);
265     // sebs and global ref are deleted in _SetEraseBackground()
266 
267     CATCH_BAD_ALLOC;
268 }
269 
270 } /* extern "C" */
271