| /* | |
| * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| #include "awt_Toolkit.h" | |
| #include "awt_Canvas.h" | |
| #include "awt_Win32GraphicsConfig.h" | |
| #include "awt_Window.h" | |
| /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. | |
| */ | |
| // Struct for _SetEraseBackground() method | |
| struct SetEraseBackgroundStruct { | |
| jobject canvas; | |
| jboolean doErase; | |
| jboolean doEraseOnResize; | |
| }; | |
| /************************************************************************ | |
| * AwtCanvas methods | |
| */ | |
| AwtCanvas::AwtCanvas() { | |
| m_eraseBackground = JNI_TRUE; | |
| m_eraseBackgroundOnResize = JNI_TRUE; | |
| } | |
| AwtCanvas::~AwtCanvas() { | |
| } | |
| LPCTSTR AwtCanvas::GetClassName() { | |
| return TEXT("SunAwtCanvas"); | |
| } | |
| /* | |
| * Create a new AwtCanvas object and window. | |
| */ | |
| AwtCanvas* AwtCanvas::Create(jobject self, jobject hParent) | |
| { | |
| DASSERT(AwtToolkit::IsMainThread()); | |
| TRY; | |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); | |
| jobject target = NULL; | |
| jobject graphicsConfig = NULL; | |
| jclass canvasClass = NULL; | |
| jclass win32cls = NULL; | |
| AwtCanvas *canvas = NULL; | |
| try { | |
| if (env->EnsureLocalCapacity(1) < 0) { | |
| return NULL; | |
| } | |
| PDATA pData; | |
| AwtComponent* parent; | |
| JNI_CHECK_PEER_GOTO(hParent, done); | |
| parent = (AwtCanvas*)pData; | |
| target = env->GetObjectField(self, AwtObject::targetID); | |
| JNI_CHECK_NULL_GOTO(target, "null target", done); | |
| canvas = new AwtCanvas(); | |
| { | |
| jint x = env->GetIntField(target, AwtComponent::xID); | |
| jint y = env->GetIntField(target, AwtComponent::yID); | |
| jint width = env->GetIntField(target, AwtComponent::widthID); | |
| jint height = env->GetIntField(target, AwtComponent::heightID); | |
| canvas->CreateHWnd(env, L"", | |
| WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, | |
| x, y, width, height, | |
| parent->GetHWnd(), | |
| NULL, | |
| ::GetSysColor(COLOR_WINDOWTEXT), | |
| ::GetSysColor(COLOR_WINDOW), | |
| self); | |
| // Set the pixel format of the HWND if a GraphicsConfiguration | |
| // was provided to the Canvas constructor. | |
| canvasClass = env->FindClass("java/awt/Canvas"); | |
| DASSERT(canvasClass != NULL); | |
| if (!canvasClass) { | |
| throw std::bad_alloc(); | |
| } | |
| if ( env->IsInstanceOf( target, canvasClass ) ) { | |
| // Get GraphicsConfig from our target | |
| graphicsConfig = env->GetObjectField(target, | |
| AwtComponent::graphicsConfigID); | |
| if (graphicsConfig != NULL) { | |
| win32cls = env->FindClass("sun/awt/Win32GraphicsConfig"); | |
| DASSERT (win32cls != NULL); | |
| if (!win32cls) { | |
| throw std::bad_alloc(); | |
| } | |
| if ( env->IsInstanceOf( graphicsConfig, win32cls ) ) { | |
| // Get the visual ID member from our GC | |
| jint visual = env->GetIntField(graphicsConfig, | |
| AwtWin32GraphicsConfig::win32GCVisualID); | |
| if (visual > 0) { | |
| HDC hdc = ::GetDC(canvas->m_hwnd); | |
| // Set our pixel format | |
| PIXELFORMATDESCRIPTOR pfd; | |
| BOOL ret = ::SetPixelFormat(hdc, (int)visual, &pfd); | |
| ::ReleaseDC(canvas->m_hwnd, hdc); | |
| //Since a GraphicsConfiguration was specified, we should | |
| //throw an exception if the PixelFormat couldn't be set. | |
| if (ret == FALSE) { | |
| DASSERT(!safe_ExceptionOccurred(env)); | |
| jclass excCls = env->FindClass( | |
| "java/lang/RuntimeException"); | |
| DASSERT(excCls); | |
| env->ExceptionClear(); | |
| env->ThrowNew(excCls, | |
| "\nUnable to set Pixel format on Canvas"); | |
| env->DeleteLocalRef(excCls); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } catch (...) { | |
| env->DeleteLocalRef(target); | |
| env->DeleteLocalRef(graphicsConfig); | |
| env->DeleteLocalRef(canvasClass); | |
| env->DeleteLocalRef(win32cls); | |
| env->DeleteGlobalRef(self); | |
| env->DeleteGlobalRef(hParent); | |
| throw; | |
| } | |
| done: | |
| env->DeleteLocalRef(target); | |
| env->DeleteLocalRef(graphicsConfig); | |
| env->DeleteLocalRef(canvasClass); | |
| env->DeleteLocalRef(win32cls); | |
| return canvas; | |
| CATCH_BAD_ALLOC_RET(0); | |
| } | |
| MsgRouting AwtCanvas::WmEraseBkgnd(HDC hDC, BOOL& didErase) | |
| { | |
| if (m_eraseBackground || | |
| (m_eraseBackgroundOnResize && AwtWindow::IsResizing())) | |
| { | |
| RECT rc; | |
| ::GetClipBox(hDC, &rc); | |
| ::FillRect(hDC, &rc, this->GetBackgroundBrush()); | |
| } | |
| didErase = TRUE; | |
| return mrConsume; | |
| } | |
| /* | |
| * This routine is duplicated in AwtWindow. | |
| */ | |
| MsgRouting AwtCanvas::WmPaint(HDC) | |
| { | |
| PaintUpdateRgn(NULL); | |
| return mrConsume; | |
| } | |
| MsgRouting AwtCanvas::HandleEvent(MSG *msg, BOOL synthetic) | |
| { | |
| if (IsFocusingMouseMessage(msg)) { | |
| delete msg; | |
| return mrConsume; | |
| } | |
| return AwtComponent::HandleEvent(msg, synthetic); | |
| } | |
| void AwtCanvas::_SetEraseBackground(void *param) | |
| { | |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); | |
| SetEraseBackgroundStruct *sebs = static_cast<SetEraseBackgroundStruct *>(param); | |
| jobject canvas = sebs->canvas; | |
| jboolean doErase = sebs->doErase; | |
| jboolean doEraseOnResize = sebs->doEraseOnResize; | |
| AwtCanvas *c = NULL; | |
| if (canvas == NULL) { | |
| env->ExceptionClear(); | |
| JNU_ThrowNullPointerException(env, "canvas"); | |
| delete sebs; | |
| return; | |
| } else { | |
| c = (AwtCanvas*)JNI_GET_PDATA(canvas); | |
| if (c == NULL) { | |
| THROW_NULL_PDATA_IF_NOT_DESTROYED(canvas); | |
| env->DeleteGlobalRef(canvas); | |
| delete sebs; | |
| return; | |
| } | |
| } | |
| c->m_eraseBackground = doErase; | |
| c->m_eraseBackgroundOnResize = doEraseOnResize; | |
| env->DeleteGlobalRef(canvas); | |
| delete sebs; | |
| } | |
| /************************************************************************ | |
| * WCanvasPeer native methods | |
| */ | |
| extern "C" { | |
| JNIEXPORT void JNICALL | |
| Java_sun_awt_windows_WCanvasPeer_create(JNIEnv *env, jobject self, | |
| jobject parent) | |
| { | |
| TRY; | |
| AwtToolkit::CreateComponent(self, parent, | |
| (AwtToolkit::ComponentFactory) | |
| AwtCanvas::Create); | |
| CATCH_BAD_ALLOC; | |
| } | |
| /* | |
| * Class: sun_awt_windows_WCanvasPeer | |
| * Method: setNativeBackgroundErase | |
| * Signature: (Z)V | |
| */ | |
| JNIEXPORT void JNICALL | |
| Java_sun_awt_windows_WCanvasPeer_setNativeBackgroundErase(JNIEnv *env, | |
| jobject self, | |
| jboolean doErase, | |
| jboolean doEraseOnResize) | |
| { | |
| TRY; | |
| SetEraseBackgroundStruct *sebs = new SetEraseBackgroundStruct; | |
| sebs->canvas = env->NewGlobalRef(self); | |
| sebs->doErase = doErase; | |
| sebs->doEraseOnResize = doEraseOnResize; | |
| AwtToolkit::GetInstance().SyncCall(AwtCanvas::_SetEraseBackground, sebs); | |
| // sebs and global ref are deleted in _SetEraseBackground() | |
| CATCH_BAD_ALLOC; | |
| } | |
| } /* extern "C" */ |