1/*
2 * Copyright (c) 1996, 2011, 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_Object.h"
27#include "ObjectList.h"
28
29#ifdef DEBUG
30static BOOL reportEvents = FALSE;
31#endif
32
33
34/************************************************************************
35 * AwtObject fields
36 */
37
38jfieldID AwtObject::pDataID;
39jfieldID AwtObject::destroyedID;
40jfieldID AwtObject::targetID;
41jclass AwtObject::wObjectPeerClass;
42jmethodID AwtObject::getPeerForTargetMID;
43jfieldID AwtObject::createErrorID;
44
45
46/************************************************************************
47 * AwtObject methods
48 */
49
50AwtObject::AwtObject()
51{
52    theAwtObjectList.Add(this);
53    m_peerObject = NULL;
54    m_callbacksEnabled = TRUE;
55}
56
57AwtObject::~AwtObject()
58{
59}
60
61void AwtObject::Dispose()
62{
63    AwtToolkit::GetInstance().PostMessage(WM_AWT_DELETEOBJECT, (WPARAM)this, (LPARAM)0);
64}
65
66void AwtObject::_Dispose(jobject self)
67{
68    TRY_NO_VERIFY;
69
70    CriticalSection::Lock l(AwtToolkit::GetInstance().GetSyncCS());
71
72    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
73    jobject selfGlobalRef = env->NewGlobalRef(self);
74
75    // value 0 of lParam means that we should not attempt to enter the
76    // SyncCall critical section, as it was entered someshere earlier
77    AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSE, (WPARAM)selfGlobalRef, (LPARAM)0);
78
79    CATCH_BAD_ALLOC;
80}
81
82void AwtObject::_Dispose(PDATA pData)
83{
84    TRY_NO_VERIFY;
85
86    CriticalSection::Lock l(AwtToolkit::GetInstance().GetSyncCS());
87
88    AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSEPDATA, (WPARAM)pData, (LPARAM)0);
89
90    CATCH_BAD_ALLOC;
91}
92/*
93 * Return the peer associated with some target.  This information is
94 * maintained in a hashtable at the java level.
95 */
96jobject AwtObject::GetPeerForTarget(JNIEnv *env, jobject target)
97{
98    jobject result =
99        env->CallStaticObjectMethod(AwtObject::wObjectPeerClass,
100                                    AwtObject::getPeerForTargetMID,
101                                    target);
102
103    DASSERT(!safe_ExceptionOccurred(env));
104    return result;
105}
106
107/* Execute a callback to the associated Java peer. */
108void
109AwtObject::DoCallback(const char* methodName, const char* methodSig, ...)
110{
111    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
112
113    /* don't callback during the create & initialization process */
114    if (m_peerObject != NULL && m_callbacksEnabled) {
115        va_list args;
116        va_start(args, methodSig);
117#ifdef DEBUG
118        if (reportEvents) {
119            jstring targetStr =
120                (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
121                                              "getName",
122                                              "()Ljava/lang/String;").l;
123            DASSERT(!safe_ExceptionOccurred(env));
124            LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
125            printf("Posting %s%s method to %S\n", methodName, methodSig, targetStrW);
126            JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
127        }
128#endif
129        /* caching would do much good here */
130        JNU_CallMethodByNameV(env, NULL, GetPeer(env),
131                              methodName, methodSig, args);
132        {
133            jthrowable exc = safe_ExceptionOccurred(env);
134            if (exc) {
135                env->DeleteLocalRef(exc);
136                env->ExceptionDescribe();
137                env->ExceptionClear();
138            }
139        }
140        DASSERT(!safe_ExceptionOccurred(env));
141        va_end(args);
142    }
143}
144
145void AwtObject::SendEvent(jobject event)
146{
147    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
148
149#ifdef DEBUG
150    if (reportEvents) {
151        jstring eventStr = JNU_ToString(env, event);
152        DASSERT(!safe_ExceptionOccurred(env));
153        jstring targetStr =
154            (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),"getName",
155                                          "()Ljava/lang/String;").l;
156        DASSERT(!safe_ExceptionOccurred(env));
157        LPCWSTR eventStrW = JNU_GetStringPlatformChars(env, eventStr, NULL);
158        LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
159        printf("Posting %S to %S\n", eventStrW, targetStrW);
160        JNU_ReleaseStringPlatformChars(env, eventStr, eventStrW);
161        JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
162    }
163#endif
164    /* Post event to the system EventQueue. */
165    JNU_CallMethodByName(env, NULL, GetPeer(env), "postEvent",
166                         "(Ljava/awt/AWTEvent;)V", event);
167    {
168        jthrowable exc = safe_ExceptionOccurred(env);
169        if (exc) {
170            env->DeleteLocalRef(exc);
171            env->ExceptionDescribe();
172        }
173    }
174    DASSERT(!safe_ExceptionOccurred(env));
175}
176
177//
178// (static)
179// Switches to Windows thread via SendMessage and synchronously
180// calls AwtObject::WinThreadExecProc with the given command id
181// and parameters.
182//
183// Useful for writing code that needs to be synchronized with
184// what's happening on the Windows thread.
185//
186LRESULT AwtObject::WinThreadExec(
187    jobject                             peerObject,
188    UINT                                cmdId,
189    LPARAM                              param1,
190    LPARAM                              param2,
191    LPARAM                              param3,
192    LPARAM                              param4 )
193{
194    DASSERT( peerObject != NULL);
195
196    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
197    // since we pass peerObject to another thread we must
198    //   make a global ref
199    jobject peerObjectGlobalRef = env->NewGlobalRef(peerObject);
200
201    ExecuteArgs         args;
202    LRESULT         retVal;
203
204    // setup arguments
205    args.cmdId = cmdId;
206    args.param1 = param1;
207    args.param2 = param2;
208    args.param3 = param3;
209    args.param4 = param4;
210
211    // call WinThreadExecProc on the toolkit thread
212    retVal = AwtToolkit::GetInstance().SendMessage(WM_AWT_EXECUTE_SYNC,
213                                                   (WPARAM)peerObjectGlobalRef,
214                                                   (LPARAM)&args);
215    return retVal;
216}
217
218LRESULT AwtObject::WinThreadExecProc(ExecuteArgs * args)
219{
220    DASSERT(FALSE); // no default handler
221    return 0L;
222}
223
224/************************************************************************
225 * WObjectPeer native methods
226 */
227
228extern "C" {
229
230JNIEXPORT void JNICALL
231Java_sun_awt_windows_WObjectPeer_initIDs(JNIEnv *env, jclass cls) {
232    TRY;
233
234    AwtObject::wObjectPeerClass = (jclass)env->NewGlobalRef(cls);
235    DASSERT(AwtObject::wObjectPeerClass != NULL);
236    CHECK_NULL(AwtObject::wObjectPeerClass);
237
238    AwtObject::pDataID = env->GetFieldID(cls, "pData", "J");
239    DASSERT(AwtObject::pDataID != NULL);
240    CHECK_NULL(AwtObject::pDataID);
241
242    AwtObject::destroyedID = env->GetFieldID(cls, "destroyed", "Z");
243    DASSERT(AwtObject::destroyedID != NULL);
244    CHECK_NULL(AwtObject::destroyedID);
245
246    AwtObject::targetID = env->GetFieldID(cls, "target",
247                                              "Ljava/lang/Object;");
248    DASSERT(AwtObject::targetID != NULL);
249    CHECK_NULL(AwtObject::targetID);
250
251    AwtObject::getPeerForTargetMID =
252        env->GetStaticMethodID(cls, "getPeerForTarget",
253                         "(Ljava/lang/Object;)Lsun/awt/windows/WObjectPeer;");
254    DASSERT(AwtObject::getPeerForTargetMID != NULL);
255    CHECK_NULL(AwtObject::getPeerForTargetMID);
256
257    AwtObject::createErrorID = env->GetFieldID(cls, "createError", "Ljava/lang/Error;");
258    DASSERT(AwtObject::createErrorID != NULL);
259    CHECK_NULL(AwtObject::createErrorID);
260
261    CATCH_BAD_ALLOC;
262}
263
264} /* extern "C" */
265