blob: b7afe1aa510658c9edd891c2934dfacab112cfda [file] [log] [blame]
/*
* Copyright (c) 1996, 2008, 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_Object.h"
#include "ObjectList.h"
#ifdef DEBUG
static BOOL reportEvents = FALSE;
#endif
/************************************************************************
* AwtObject fields
*/
jfieldID AwtObject::pDataID;
jfieldID AwtObject::destroyedID;
jfieldID AwtObject::targetID;
jclass AwtObject::wObjectPeerClass;
jmethodID AwtObject::getPeerForTargetMID;
jfieldID AwtObject::createErrorID;
/************************************************************************
* AwtObject methods
*/
AwtObject::AwtObject()
{
theAwtObjectList.Add(this);
m_peerObject = NULL;
m_callbacksEnabled = TRUE;
}
AwtObject::~AwtObject()
{
}
void AwtObject::Dispose()
{
theAwtObjectList.Remove(this);
// value 0 of lParam means that we should not attempt to enter the
// SyncCall critical section, as it was entered someshere earlier
AwtToolkit::GetInstance().PostMessage(WM_AWT_DELETEOBJECT, (WPARAM)this, (LPARAM)0);
}
void AwtObject::_Dispose(PDATA pData)
{
TRY_NO_VERIFY;
CriticalSection::Lock l(AwtToolkit::GetInstance().GetSyncCS());
if (pData != NULL) {
AwtObject *o = (AwtObject *)pData;
AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSE, (WPARAM)o, (LPARAM)0);
}
CATCH_BAD_ALLOC;
}
/*
* Return the peer associated with some target. This information is
* maintained in a hashtable at the java level.
*/
jobject AwtObject::GetPeerForTarget(JNIEnv *env, jobject target)
{
jobject result =
env->CallStaticObjectMethod(AwtObject::wObjectPeerClass,
AwtObject::getPeerForTargetMID,
target);
DASSERT(!safe_ExceptionOccurred(env));
return result;
}
/* Execute a callback to the associated Java peer. */
void
AwtObject::DoCallback(const char* methodName, const char* methodSig, ...)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
/* don't callback during the create & initialization process */
if (m_peerObject != NULL && m_callbacksEnabled) {
va_list args;
va_start(args, methodSig);
#ifdef DEBUG
if (reportEvents) {
jstring targetStr =
(jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
"getName",
"()Ljava/lang/String;").l;
DASSERT(!safe_ExceptionOccurred(env));
LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
printf("Posting %s%s method to %S\n", methodName, methodSig, targetStrW);
JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
}
#endif
/* caching would do much good here */
JNU_CallMethodByNameV(env, NULL, GetPeer(env),
methodName, methodSig, args);
{
jthrowable exc = safe_ExceptionOccurred(env);
if (exc) {
env->DeleteLocalRef(exc);
env->ExceptionDescribe();
env->ExceptionClear();
}
}
DASSERT(!safe_ExceptionOccurred(env));
va_end(args);
}
}
void AwtObject::SendEvent(jobject event)
{
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
#ifdef DEBUG
if (reportEvents) {
jstring eventStr = JNU_ToString(env, event);
DASSERT(!safe_ExceptionOccurred(env));
jstring targetStr =
(jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),"getName",
"()Ljava/lang/String;").l;
DASSERT(!safe_ExceptionOccurred(env));
LPCWSTR eventStrW = JNU_GetStringPlatformChars(env, eventStr, NULL);
LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
printf("Posting %S to %S\n", eventStrW, targetStrW);
JNU_ReleaseStringPlatformChars(env, eventStr, eventStrW);
JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
}
#endif
/* Post event to the system EventQueue. */
JNU_CallMethodByName(env, NULL, GetPeer(env), "postEvent",
"(Ljava/awt/AWTEvent;)V", event);
{
jthrowable exc = safe_ExceptionOccurred(env);
if (exc) {
env->DeleteLocalRef(exc);
env->ExceptionDescribe();
}
}
DASSERT(!safe_ExceptionOccurred(env));
}
//
// (static)
// Switches to Windows thread via SendMessage and synchronously
// calls AwtObject::WinThreadExecProc with the given command id
// and parameters.
//
// Useful for writing code that needs to be synchronized with
// what's happening on the Windows thread.
//
LRESULT AwtObject::WinThreadExec(
jobject peerObject,
UINT cmdId,
LPARAM param1,
LPARAM param2,
LPARAM param3,
LPARAM param4 )
{
DASSERT( peerObject != NULL);
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
// since we pass peerObject to another thread we must
// make a global ref
jobject peerObjectGlobalRef = env->NewGlobalRef(peerObject);
ExecuteArgs args;
LRESULT retVal;
// setup arguments
args.cmdId = cmdId;
args.param1 = param1;
args.param2 = param2;
args.param3 = param3;
args.param4 = param4;
// call WinThreadExecProc on the toolkit thread
retVal = AwtToolkit::GetInstance().SendMessage(WM_AWT_EXECUTE_SYNC,
(WPARAM)peerObjectGlobalRef,
(LPARAM)&args);
return retVal;
}
LRESULT AwtObject::WinThreadExecProc(ExecuteArgs * args)
{
DASSERT(FALSE); // no default handler
return 0L;
}
/************************************************************************
* WObjectPeer native methods
*/
extern "C" {
JNIEXPORT void JNICALL
Java_sun_awt_windows_WObjectPeer_initIDs(JNIEnv *env, jclass cls) {
TRY;
AwtObject::wObjectPeerClass = (jclass)env->NewGlobalRef(cls);
AwtObject::pDataID = env->GetFieldID(cls, "pData", "J");
AwtObject::destroyedID = env->GetFieldID(cls, "destroyed", "Z");
AwtObject::targetID = env->GetFieldID(cls, "target",
"Ljava/lang/Object;");
AwtObject::getPeerForTargetMID =
env->GetStaticMethodID(cls, "getPeerForTarget",
"(Ljava/lang/Object;)Lsun/awt/windows/WObjectPeer;");
AwtObject::createErrorID = env->GetFieldID(cls, "createError", "Ljava/lang/Error;");
DASSERT(AwtObject::pDataID != NULL);
DASSERT(AwtObject::destroyedID != NULL);
DASSERT(AwtObject::targetID != NULL);
DASSERT(AwtObject::getPeerForTargetMID != NULL);
DASSERT(AwtObject::createErrorID != NULL);
CATCH_BAD_ALLOC;
}
} /* extern "C" */