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
30 static BOOL reportEvents = FALSE;
31 #endif
32 
33 
34 /************************************************************************
35  * AwtObject fields
36  */
37 
38 jfieldID AwtObject::pDataID;
39 jfieldID AwtObject::destroyedID;
40 jfieldID AwtObject::targetID;
41 jclass AwtObject::wObjectPeerClass;
42 jmethodID AwtObject::getPeerForTargetMID;
43 jfieldID AwtObject::createErrorID;
44 
45 
46 /************************************************************************
47  * AwtObject methods
48  */
49 
AwtObject()50 AwtObject::AwtObject()
51 {
52     theAwtObjectList.Add(this);
53     m_peerObject = NULL;
54     m_callbacksEnabled = TRUE;
55 }
56 
~AwtObject()57 AwtObject::~AwtObject()
58 {
59 }
60 
Dispose()61 void AwtObject::Dispose()
62 {
63     AwtToolkit::GetInstance().PostMessage(WM_AWT_DELETEOBJECT, (WPARAM)this, (LPARAM)0);
64 }
65 
_Dispose(jobject self)66 void 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 
_Dispose(PDATA pData)82 void 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  */
GetPeerForTarget(JNIEnv * env,jobject target)96 jobject 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. */
108 void
DoCallback(const char * methodName,const char * methodSig,...)109 AwtObject::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 
SendEvent(jobject event)145 void 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 //
WinThreadExec(jobject peerObject,UINT cmdId,LPARAM param1,LPARAM param2,LPARAM param3,LPARAM param4)186 LRESULT 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 
WinThreadExecProc(ExecuteArgs * args)218 LRESULT AwtObject::WinThreadExecProc(ExecuteArgs * args)
219 {
220     DASSERT(FALSE); // no default handler
221     return 0L;
222 }
223 
224 /************************************************************************
225  * WObjectPeer native methods
226  */
227 
228 extern "C" {
229 
230 JNIEXPORT void JNICALL
Java_sun_awt_windows_WObjectPeer_initIDs(JNIEnv * env,jclass cls)231 Java_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