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 
  45 AwtCanvas::AwtCanvas() {
  46     m_eraseBackground = JNI_TRUE;
  47     m_eraseBackgroundOnResize = JNI_TRUE;
  48 }
  49 
  50 AwtCanvas::~AwtCanvas() {
  51 }
  52 
  53 LPCTSTR AwtCanvas::GetClassName() {
  54     return TEXT("SunAwtCanvas");
  55 }
  56 
  57 /*
  58  * Create a new AwtCanvas object and window.
  59  */
  60 AwtCanvas* AwtCanvas::Create(jobject self, jobject hParent)
  61 {
  62     TRY;
  63     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  64 
  65     jobject target = NULL;
  66     jobject graphicsConfig = NULL;
  67     jclass canvasClass = NULL;
  68     jclass win32cls = NULL;
  69 
  70     AwtCanvas *canvas = NULL;
  71 
  72     try {
  73         if (env->EnsureLocalCapacity(1) < 0) {
  74             return NULL;
  75         }
  76 
  77         AwtComponent* parent;
  78 
  79         JNI_CHECK_NULL_GOTO(hParent, "null hParent", done);
  80 
  81         parent = (AwtComponent*)JNI_GET_PDATA(hParent);
  82         JNI_CHECK_NULL_GOTO(parent, "null parent", done);
  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 
 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  */
 190 MsgRouting AwtCanvas::WmPaint(HDC)
 191 {
 192     PaintUpdateRgn(NULL);
 193     return mrConsume;
 194 }
 195 
 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 
 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
 234 Java_sun_awt_windows_WCanvasPeer_create(JNIEnv *env, jobject self,
 235                                         jobject parent)
 236 {
 237     TRY;
 238 
 239     PDATA pData;
 240     JNI_CHECK_PEER_RETURN(parent);
 241     AwtToolkit::CreateComponent(self, parent,
 242                                 (AwtToolkit::ComponentFactory)
 243                                 AwtCanvas::Create);
 244     JNI_CHECK_PEER_CREATION_RETURN(self);
 245 
 246     CATCH_BAD_ALLOC;
 247 }
 248 
 249 /*
 250  * Class:     sun_awt_windows_WCanvasPeer
 251  * Method:    setNativeBackgroundErase
 252  * Signature: (Z)V
 253  */
 254  JNIEXPORT void JNICALL
 255  Java_sun_awt_windows_WCanvasPeer_setNativeBackgroundErase(JNIEnv *env,
 256                                                            jobject self,
 257                                                            jboolean doErase,
 258                                                            jboolean doEraseOnResize)
 259 {
 260     TRY;
 261 
 262     SetEraseBackgroundStruct *sebs = new SetEraseBackgroundStruct;
 263     sebs->canvas = env->NewGlobalRef(self);
 264     sebs->doErase = doErase;
 265     sebs->doEraseOnResize = doEraseOnResize;
 266 
 267     AwtToolkit::GetInstance().SyncCall(AwtCanvas::_SetEraseBackground, sebs);
 268     // sebs and global ref are deleted in _SetEraseBackground()
 269 
 270     CATCH_BAD_ALLOC;
 271 }
 272 
 273 } /* extern "C" */