1 /*
2  * Copyright (c) 1996, 2017, 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.h"
27 
28 #include <windowsx.h>
29 #include <zmouse.h>
30 
31 #include "jlong.h"
32 #include "awt_AWTEvent.h"
33 #include "awt_BitmapUtil.h"
34 #include "awt_Component.h"
35 #include "awt_Cursor.h"
36 #include "awt_Dimension.h"
37 #include "awt_Frame.h"
38 #include "awt_InputEvent.h"
39 #include "awt_InputTextInfor.h"
40 #include "awt_Insets.h"
41 #include "awt_KeyEvent.h"
42 #include "awt_MenuItem.h"
43 #include "awt_MouseEvent.h"
44 #include "awt_Palette.h"
45 #include "awt_Toolkit.h"
46 #include "awt_Window.h"
47 #include "awt_Win32GraphicsDevice.h"
48 #include "Hashtable.h"
49 #include "ComCtl32Util.h"
50 
51 #include <Region.h>
52 
53 #include <jawt.h>
54 
55 #include <java_awt_Toolkit.h>
56 #include <java_awt_FontMetrics.h>
57 #include <java_awt_Color.h>
58 #include <java_awt_Event.h>
59 #include <java_awt_event_KeyEvent.h>
60 #include <java_awt_Insets.h>
61 #include <sun_awt_windows_WPanelPeer.h>
62 #include <java_awt_event_InputEvent.h>
63 #include <java_awt_event_InputMethodEvent.h>
64 #include <sun_awt_windows_WInputMethod.h>
65 #include <java_awt_event_MouseEvent.h>
66 #include <java_awt_event_MouseWheelEvent.h>
67 
68 // Begin -- Win32 SDK include files
69 #include <imm.h>
70 #include <ime.h>
71 // End -- Win32 SDK include files
72 
73 #include <awt_DnDDT.h>
74 
75 LPCTSTR szAwtComponentClassName = TEXT("SunAwtComponent");
76 // register a message that no other window in the process (even in a plugin
77 // scenario) will be using
78 const UINT AwtComponent::WmAwtIsComponent =
79     ::RegisterWindowMessage(szAwtComponentClassName);
80 
81 static HWND g_hwndDown = NULL;
82 static DCList activeDCList;
83 static DCList passiveDCList;
84 
85 extern void CheckFontSmoothingSettings(HWND);
86 
87 extern "C" {
88     // Remember the input language has changed by some user's action
89     // (Alt+Shift or through the language icon on the Taskbar) to control the
90     // race condition between the toolkit thread and the AWT event thread.
91     // This flag remains TRUE until the next WInputMethod.getNativeLocale() is
92     // issued.
93     BOOL g_bUserHasChangedInputLang = FALSE;
94 }
95 
96 BOOL AwtComponent::sm_suppressFocusAndActivation = FALSE;
97 BOOL AwtComponent::sm_restoreFocusAndActivation = FALSE;
98 HWND AwtComponent::sm_focusOwner = NULL;
99 HWND AwtComponent::sm_focusedWindow = NULL;
100 BOOL AwtComponent::sm_bMenuLoop = FALSE;
101 BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
102 
103 /************************************************************************/
104 // Struct for _Reshape() and ReshapeNoCheck() methods
105 struct ReshapeStruct {
106     jobject component;
107     jint x, y;
108     jint w, h;
109 };
110 // Struct for _NativeHandleEvent() method
111 struct NativeHandleEventStruct {
112     jobject component;
113     jobject event;
114 };
115 // Struct for _SetForeground() and _SetBackground() methods
116 struct SetColorStruct {
117     jobject component;
118     jint rgb;
119 };
120 // Struct for _SetFont() method
121 struct SetFontStruct {
122     jobject component;
123     jobject font;
124 };
125 // Struct for _CreatePrintedPixels() method
126 struct CreatePrintedPixelsStruct {
127     jobject component;
128     int srcx, srcy;
129     int srcw, srch;
130     jint alpha;
131 };
132 // Struct for _SetRectangularShape() method
133 struct SetRectangularShapeStruct {
134     jobject component;
135     jint x1, x2, y1, y2;
136     jobject region;
137 };
138 // Struct for _GetInsets function
139 struct GetInsetsStruct {
140     jobject window;
141     RECT *insets;
142 };
143 // Struct for _SetZOrder function
144 struct SetZOrderStruct {
145     jobject component;
146     jlong above;
147 };
148 // Struct for _SetFocus function
149 struct SetFocusStruct {
150     jobject component;
151     jboolean doSetFocus;
152 };
153 // Struct for _SetParent function
154 struct SetParentStruct {
155     jobject component;
156     jobject parentComp;
157 };
158 /************************************************************************/
159 
160 //////////////////////////////////////////////////////////////////////////
161 
162 /*************************************************************************
163  * AwtComponent fields
164  */
165 
166 
167 jfieldID AwtComponent::peerID;
168 jfieldID AwtComponent::xID;
169 jfieldID AwtComponent::yID;
170 jfieldID AwtComponent::widthID;
171 jfieldID AwtComponent::heightID;
172 jfieldID AwtComponent::visibleID;
173 jfieldID AwtComponent::backgroundID;
174 jfieldID AwtComponent::foregroundID;
175 jfieldID AwtComponent::enabledID;
176 jfieldID AwtComponent::parentID;
177 jfieldID AwtComponent::graphicsConfigID;
178 jfieldID AwtComponent::peerGCID;
179 jfieldID AwtComponent::focusableID;
180 jfieldID AwtComponent::appContextID;
181 jfieldID AwtComponent::cursorID;
182 jfieldID AwtComponent::hwndID;
183 
184 jmethodID AwtComponent::getFontMID;
185 jmethodID AwtComponent::getToolkitMID;
186 jmethodID AwtComponent::isEnabledMID;
187 jmethodID AwtComponent::getLocationOnScreenMID;
188 jmethodID AwtComponent::replaceSurfaceDataMID;
189 jmethodID AwtComponent::replaceSurfaceDataLaterMID;
190 jmethodID AwtComponent::disposeLaterMID;
191 
192 HKL    AwtComponent::m_hkl = ::GetKeyboardLayout(0);
193 LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0));
194 UINT   AwtComponent::m_CodePage
195                        = AwtComponent::LangToCodePage(m_idLang);
196 
197 jint *AwtComponent::masks;
198 
199 static BOOL bLeftShiftIsDown = false;
200 static BOOL bRightShiftIsDown = false;
201 static UINT lastShiftKeyPressed = 0; // init to safe value
202 
203 // Added by waleed to initialize the RTL Flags
204 BOOL AwtComponent::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC ||
205                             PRIMARYLANGID(GetInputLanguage()) == LANG_HEBREW;
206 BOOL AwtComponent::sm_rtlReadingOrder =
207     PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC;
208 
209 BOOL AwtComponent::sm_PrimaryDynamicTableBuilt = FALSE;
210 
211 HWND AwtComponent::sm_cursorOn;
212 BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE;
213 
214 CriticalSection windowMoveLock;
215 BOOL windowMoveLockHeld = FALSE;
216 
217 /************************************************************************
218  * AwtComponent methods
219  */
220 
AwtComponent()221 AwtComponent::AwtComponent()
222 {
223     m_mouseButtonClickAllowed = 0;
224     m_touchDownOccurred = FALSE;
225     m_touchUpOccurred = FALSE;
226     m_touchDownPoint.x = m_touchDownPoint.y = 0;
227     m_touchUpPoint.x = m_touchUpPoint.y = 0;
228     m_callbacksEnabled = FALSE;
229     m_hwnd = NULL;
230 
231     m_colorForeground = 0;
232     m_colorBackground = 0;
233     m_backgroundColorSet = FALSE;
234     m_penForeground = NULL;
235     m_brushBackground = NULL;
236     m_DefWindowProc = NULL;
237     m_nextControlID = 1;
238     m_childList = NULL;
239     m_myControlID = 0;
240     m_hdwp = NULL;
241     m_validationNestCount = 0;
242 
243     m_dropTarget = NULL;
244 
245     m_InputMethod = NULL;
246     m_useNativeCompWindow = TRUE;
247     m_PendingLeadByte = 0;
248     m_bitsCandType = 0;
249 
250     windowMoveLockPosX = 0;
251     windowMoveLockPosY = 0;
252     windowMoveLockPosCX = 0;
253     windowMoveLockPosCY = 0;
254 
255     m_hCursorCache = NULL;
256 
257     m_bSubclassed = FALSE;
258     m_bPauseDestroy = FALSE;
259 
260     m_MessagesProcessing = 0;
261     m_wheelRotationAmount = 0;
262     if (!sm_PrimaryDynamicTableBuilt) {
263         // do it once.
264         AwtComponent::BuildPrimaryDynamicTable();
265         sm_PrimaryDynamicTableBuilt = TRUE;
266     }
267 
268     deadKeyActive = FALSE;
269 }
270 
~AwtComponent()271 AwtComponent::~AwtComponent()
272 {
273     DASSERT(AwtToolkit::IsMainThread());
274 
275     /*
276      * All the messages for this component are processed, native
277      * resources are freed, and Java object is not connected to
278      * the native one anymore. So we can safely destroy component's
279      * handle.
280      */
281     DestroyHWnd();
282 }
283 
Dispose()284 void AwtComponent::Dispose()
285 {
286     DASSERT(AwtToolkit::IsMainThread());
287 
288     // NOTE: in case the component/toplevel was focused, Java should
289     // have already taken care of proper transferring it or clearing.
290 
291     if (m_hdwp != NULL) {
292     // end any deferred window positioning, regardless
293     // of m_validationNestCount
294         ::EndDeferWindowPos(m_hdwp);
295     }
296 
297     // Send final message to release all DCs associated with this component
298     SendMessage(WM_AWT_RELEASE_ALL_DCS);
299 
300     /* Stop message filtering. */
301     UnsubclassHWND();
302 
303     /* Release global ref to input method */
304     SetInputMethod(NULL, TRUE);
305 
306     if (m_childList != NULL) {
307         delete m_childList;
308         m_childList = NULL;
309     }
310 
311     DestroyDropTarget();
312     ReleaseDragCapture(0);
313 
314     if (m_myControlID != 0) {
315         AwtComponent* parent = GetParent();
316         if (parent != NULL)
317             parent->RemoveChild(m_myControlID);
318     }
319 
320     ::RemoveProp(GetHWnd(), DrawingStateProp);
321 
322     /* Release any allocated resources. */
323     if (m_penForeground != NULL) {
324         m_penForeground->Release();
325         m_penForeground = NULL;
326     }
327     if (m_brushBackground != NULL) {
328         m_brushBackground->Release();
329         m_brushBackground = NULL;
330     }
331 
332     /* Disconnect all links. */
333     UnlinkObjects();
334 
335     if (m_bPauseDestroy) {
336         // AwtComponent::WmNcDestroy could be released now
337         m_bPauseDestroy = FALSE;
338         m_hwnd = NULL;
339     }
340 
341     // The component instance is deleted using AwtObject::Dispose() method
342     AwtObject::Dispose();
343 }
344 
345 /* store component pointer in window extra bytes */
SetComponentInHWND()346 void AwtComponent::SetComponentInHWND() {
347     DASSERT(::GetWindowLongPtr(GetHWnd(), GWLP_USERDATA) == NULL);
348     ::SetWindowLongPtr(GetHWnd(), GWLP_USERDATA, (LONG_PTR)this);
349 }
350 
351 /*
352  * static function to get AwtComponent pointer from hWnd --
353  * you don't want to call this from inside a wndproc to avoid
354  * infinite recursion
355  */
GetComponent(HWND hWnd)356 AwtComponent* AwtComponent::GetComponent(HWND hWnd) {
357     // Requests for Toolkit hwnd resolution happen pretty often. Check first.
358     if (hWnd == AwtToolkit::GetInstance().GetHWnd()) {
359         return NULL;
360     }
361 
362     // check that it's an AWT component from the same toolkit as the caller
363     if (::IsWindow(hWnd) &&
364         AwtToolkit::MainThread() == ::GetWindowThreadProcessId(hWnd, NULL))
365     {
366         DASSERT(WmAwtIsComponent != 0);
367         if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) {
368             return GetComponentImpl(hWnd);
369         }
370     }
371     return NULL;
372 }
373 
374 /*
375  * static function to get AwtComponent pointer from hWnd--
376  * different from GetComponent because caller knows the
377  * hwnd is an AWT component hwnd
378  */
GetComponentImpl(HWND hWnd)379 AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
380     AwtComponent *component =
381         (AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
382     DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
383     DASSERT(!component || component->GetHWnd() == hWnd );
384     return component;
385 }
386 
387 /*
388  * Single window proc for all the components. Delegates real work to
389  * the component's WindowProc() member function.
390  */
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)391 LRESULT CALLBACK AwtComponent::WndProc(HWND hWnd, UINT message,
392                                        WPARAM wParam, LPARAM lParam)
393 {
394     TRY;
395 
396     AwtComponent * self = AwtComponent::GetComponentImpl(hWnd);
397     if (self == NULL || self->GetHWnd() != hWnd ||
398         message == WM_UNDOCUMENTED_CLIENTSHUTDOWN) // handle log-off gracefully
399     {
400         return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam);
401     } else {
402         return self->WindowProc(message, wParam, lParam);
403     }
404 
405     CATCH_BAD_ALLOC_RET(0);
406 }
407 
IsFocusable()408 BOOL AwtComponent::IsFocusable() {
409     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
410     jobject peer = GetPeer(env);
411     jobject target = env->GetObjectField(peer, AwtObject::targetID);
412     BOOL res = env->GetBooleanField(target, focusableID);
413     AwtWindow *pCont = GetContainer();
414     if (pCont) {
415         res &= pCont->IsFocusableWindow();
416     }
417     env->DeleteLocalRef(target);
418     return res;
419 }
420 
421 /************************************************************************
422  * AwtComponent dynamic methods
423  *
424  * Window class registration routines
425  */
426 
427 /*
428  * Fix for 4964237: Win XP: Changing theme changes java dialogs title icon
429  */
FillClassInfo(WNDCLASSEX * lpwc)430 void AwtComponent::FillClassInfo(WNDCLASSEX *lpwc)
431 {
432     lpwc->cbSize        = sizeof(WNDCLASSEX);
433     lpwc->style         = 0L;//CS_OWNDC;
434     lpwc->lpfnWndProc   = (WNDPROC)::DefWindowProc;
435     lpwc->cbClsExtra    = 0;
436     lpwc->cbWndExtra    = 0;
437     lpwc->hInstance     = AwtToolkit::GetInstance().GetModuleHandle(),
438     lpwc->hIcon         = AwtToolkit::GetInstance().GetAwtIcon();
439     lpwc->hCursor       = NULL;
440     lpwc->hbrBackground = NULL;
441     lpwc->lpszMenuName  = NULL;
442     lpwc->lpszClassName = GetClassName();
443     //Fixed 6233560: PIT: Java Cup Logo on the title bar of top-level windows look blurred, Win32
444     lpwc->hIconSm       = AwtToolkit::GetInstance().GetAwtIconSm();
445 }
446 
RegisterClass()447 void AwtComponent::RegisterClass()
448 {
449     WNDCLASSEX wc;
450     if (!::GetClassInfoEx(AwtToolkit::GetInstance().GetModuleHandle(), GetClassName(), &wc)) {
451         FillClassInfo(&wc);
452         ATOM ret = ::RegisterClassEx(&wc);
453         DASSERT(ret != 0);
454     }
455 }
456 
UnregisterClass()457 void AwtComponent::UnregisterClass()
458 {
459     ::UnregisterClass(GetClassName(), AwtToolkit::GetInstance().GetModuleHandle());
460 }
461 
462 /*
463  * Copy the graphicsConfig reference from Component into WComponentPeer
464  */
InitPeerGraphicsConfig(JNIEnv * env,jobject peer)465 void AwtComponent::InitPeerGraphicsConfig(JNIEnv *env, jobject peer)
466 {
467     jobject target = env->GetObjectField(peer, AwtObject::targetID);
468     //Get graphicsConfig object ref from Component
469     jobject compGC = env->GetObjectField(target,
470                       AwtComponent::graphicsConfigID);
471 
472     //Set peer's graphicsConfig to Component's graphicsConfig
473     if (compGC != NULL) {
474         jclass win32GCCls = env->FindClass("sun/awt/Win32GraphicsConfig");
475         DASSERT(win32GCCls != NULL);
476         DASSERT(env->IsInstanceOf(compGC, win32GCCls));
477         if (win32GCCls == NULL) {
478             throw std::bad_alloc();
479         }
480         env->SetObjectField(peer, AwtComponent::peerGCID, compGC);
481     }
482 }
483 
484 void
CreateHWnd(JNIEnv * env,LPCWSTR title,DWORD windowStyle,DWORD windowExStyle,int x,int y,int w,int h,HWND hWndParent,HMENU hMenu,COLORREF colorForeground,COLORREF colorBackground,jobject peer)485 AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title,
486                          DWORD windowStyle,
487                          DWORD windowExStyle,
488                          int x, int y, int w, int h,
489                          HWND hWndParent, HMENU hMenu,
490                          COLORREF colorForeground,
491                          COLORREF colorBackground,
492                          jobject peer)
493 {
494     if (env->EnsureLocalCapacity(2) < 0) {
495         return;
496     }
497 
498     /*
499      * The window class of multifont label must be "BUTTON" because
500      * "STATIC" class can't get WM_DRAWITEM message, and m_peerObject
501      * member is referred in the GetClassName method of AwtLabel class.
502      * So m_peerObject member must be set here.
503      */
504     if (m_peerObject == NULL) {
505         m_peerObject = env->NewGlobalRef(peer);
506     } else {
507         assert(env->IsSameObject(m_peerObject, peer));
508     }
509 
510     RegisterClass();
511 
512     jobject target = env->GetObjectField(peer, AwtObject::targetID);
513     jboolean visible = env->GetBooleanField(target, AwtComponent::visibleID);
514     m_visible = visible;
515 
516     if (visible) {
517         windowStyle |= WS_VISIBLE;
518     } else {
519         windowStyle &= ~WS_VISIBLE;
520     }
521 
522     InitPeerGraphicsConfig(env, peer);
523 
524     SetLastError(0);
525     HWND hwnd = ::CreateWindowEx(windowExStyle,
526                                  GetClassName(),
527                                  title,
528                                  windowStyle,
529                                  x, y, w, h,
530                                  hWndParent,
531                                  hMenu,
532                                  AwtToolkit::GetInstance().GetModuleHandle(),
533                                  NULL);
534 
535     // fix for 5088782
536     // check if CreateWindowsEx() returns not null value and if it does -
537     //   create an InternalError or OutOfMemoryError based on GetLastError().
538     //   This error is set to createError field of WObjectPeer and then
539     //   checked and thrown in WComponentPeer constructor. We can't throw an
540     //   error here because this code is invoked on Toolkit thread
541     if (hwnd == NULL)
542     {
543         DWORD dw = ::GetLastError();
544         jobject createError = NULL;
545         if (dw == ERROR_OUTOFMEMORY)
546         {
547             jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles");
548             if (errorMsg == NULL || env->ExceptionCheck()) {
549                 env->ExceptionClear();
550                 createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "()V");
551             } else {
552                 createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError",
553                                                       "(Ljava/lang/String;)V",
554                                                       errorMsg);
555                 env->DeleteLocalRef(errorMsg);
556             }
557         }
558         else
559         {
560             TCHAR *buf;
561             FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
562                 NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
563                 (LPTSTR)&buf, 0, NULL);
564             jstring s = JNU_NewStringPlatform(env, buf);
565             if (s == NULL || env->ExceptionCheck()) {
566                 env->ExceptionClear();
567                 createError = JNU_NewObjectByName(env, "java/lang/InternalError", "()V");
568             } else {
569                 createError = JNU_NewObjectByName(env, "java/lang/InternalError",
570                                                                   "(Ljava/lang/String;)V", s);
571                 env->DeleteLocalRef(s);
572             }
573             LocalFree(buf);
574         }
575         if (createError != NULL) {
576             env->SetObjectField(peer, AwtObject::createErrorID, createError);
577             env->DeleteLocalRef(createError);
578         }
579         env->DeleteLocalRef(target);
580         return;
581     }
582 
583     m_hwnd = hwnd;
584 
585     ::ImmAssociateContext(m_hwnd, NULL);
586 
587     SetDrawState((jint)JAWT_LOCK_SURFACE_CHANGED |
588         (jint)JAWT_LOCK_BOUNDS_CHANGED |
589         (jint)JAWT_LOCK_CLIP_CHANGED);
590 
591     LinkObjects(env, peer);
592 
593     /* Subclass the window now so that we can snoop on its messages */
594     SubclassHWND();
595 
596     AwtToolkit& tk = AwtToolkit::GetInstance();
597     if (tk.IsWin8OrLater() && tk.IsTouchKeyboardAutoShowEnabled()) {
598         tk.TIRegisterTouchWindow(GetHWnd(), TWF_WANTPALM);
599     }
600 
601     /*
602       * Fix for 4046446.
603       */
604     SetWindowPos(GetHWnd(), 0, x, y, w, h, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE);
605 
606     /* Set default colors. */
607     m_colorForeground = colorForeground;
608     m_colorBackground = colorBackground;
609 
610     /*
611      * Only set background color if the color is actually set on the
612      * target -- this avoids inheriting a parent's color unnecessarily,
613      * and has to be done here because there isn't an API to get the
614      * real background color from outside the AWT package.
615      */
616     jobject bkgrd = env->GetObjectField(target, AwtComponent::backgroundID) ;
617     if (bkgrd != NULL) {
618         JNU_CallMethodByName(env, NULL, peer, "setBackground",
619                              "(Ljava/awt/Color;)V", bkgrd);
620         DASSERT(!safe_ExceptionOccurred(env));
621     }
622     env->DeleteLocalRef(target);
623     env->DeleteLocalRef(bkgrd);
624 }
625 
626 /*
627  * Destroy this window's HWND
628  */
DestroyHWnd()629 void AwtComponent::DestroyHWnd() {
630     if (m_hwnd != NULL) {
631         AwtToolkit::DestroyComponentHWND(m_hwnd);
632         //AwtToolkit::DestroyComponent(this);
633         m_hwnd = NULL;
634     }
635 }
636 
637 /*
638  * Returns hwnd for target on non Toolkit thread
639  */
640 HWND
GetHWnd(JNIEnv * env,jobject target)641 AwtComponent::GetHWnd(JNIEnv* env, jobject target) {
642     if (JNU_IsNull(env, target)) {
643         return 0;
644     }
645     jobject peer = env->GetObjectField(target, AwtComponent::peerID);
646     if (JNU_IsNull(env, peer)) {
647         return 0;
648     }
649     HWND hwnd = reinterpret_cast<HWND>(static_cast<LONG_PTR> (
650         env->GetLongField(peer, AwtComponent::hwndID)));
651     env->DeleteLocalRef(peer);
652     return hwnd;
653 }
654 //
655 // Propagate the background color to synchronize Java field and peer's field.
656 // This is needed to fix 4148334
657 //
UpdateBackground(JNIEnv * env,jobject target)658 void AwtComponent::UpdateBackground(JNIEnv *env, jobject target)
659 {
660     if (env->EnsureLocalCapacity(1) < 0) {
661         return;
662     }
663 
664     jobject bkgrnd = env->GetObjectField(target, AwtComponent::backgroundID);
665 
666     if (bkgrnd == NULL) {
667         bkgrnd = JNU_NewObjectByName(env, "java/awt/Color", "(III)V",
668                                      GetRValue(m_colorBackground),
669                                      GetGValue(m_colorBackground),
670                                      GetBValue(m_colorBackground));
671         if (bkgrnd != NULL) {
672             env->SetObjectField(target, AwtComponent::backgroundID, bkgrnd);
673         }
674     }
675     env->DeleteLocalRef(bkgrnd);
676 }
677 
678 /*
679  * Install our window proc as the proc for our HWND, and save off the
680  * previous proc as the default
681  */
SubclassHWND()682 void AwtComponent::SubclassHWND()
683 {
684     if (m_bSubclassed) {
685         return;
686     }
687     const WNDPROC wndproc = WndProc; // let compiler type check WndProc
688     m_DefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(GetHWnd(), wndproc);
689     m_bSubclassed = TRUE;
690 }
691 
692 /*
693  * Reinstall the original window proc as the proc for our HWND
694  */
UnsubclassHWND()695 void AwtComponent::UnsubclassHWND()
696 {
697     if (!m_bSubclassed) {
698         return;
699     }
700     ComCtl32Util::GetInstance().UnsubclassHWND(GetHWnd(), WndProc, m_DefWindowProc);
701     m_bSubclassed = FALSE;
702 }
703 
704 /////////////////////////////////////
705 // (static method)
706 // Determines the top-level ancestor for a given window. If the given
707 // window is a top-level window, return itself.
708 //
709 // 'Top-level' includes dialogs as well.
710 //
GetTopLevelParentForWindow(HWND hwndDescendant)711 HWND AwtComponent::GetTopLevelParentForWindow(HWND hwndDescendant) {
712     if (hwndDescendant == NULL) {
713         return NULL;
714     }
715 
716     DASSERT(IsWindow(hwndDescendant));
717     HWND hwnd = hwndDescendant;
718     for(;;) {
719         DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
720         // a) found a non-child window so terminate
721         // b) found real toplevel window (e.g. EmbeddedFrame
722         //    that is child though)
723         if ( (style & WS_CHILD) == 0 ||
724              AwtComponent::IsTopLevelHWnd(hwnd) )
725         {
726             break;
727         }
728         hwnd = ::GetParent(hwnd);
729     }
730 
731     return hwnd;
732 }
733 ////////////////////
734 
FindHeavyweightUnderCursor(BOOL useCache)735 jobject AwtComponent::FindHeavyweightUnderCursor(BOOL useCache) {
736     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
737     if (env->EnsureLocalCapacity(1) < 0) {
738         return NULL;
739     }
740 
741     HWND hit = NULL;
742     POINT p = { 0, 0 };
743     AwtComponent *comp = NULL;
744 
745     if (useCache) {
746         if (sm_cursorOn == NULL) {
747             return NULL;
748         }
749 
750 
751         DASSERT(::IsWindow(sm_cursorOn));
752         VERIFY(::GetCursorPos(&p));
753         /*
754          * Fix for BugTraq ID 4304024.
755          * Allow a non-default cursor only for the client area.
756          */
757         comp = AwtComponent::GetComponent(sm_cursorOn);
758         if (comp != NULL &&
759             ::SendMessage(sm_cursorOn, WM_NCHITTEST, 0,
760                           MAKELPARAM(p.x, p.y)) == HTCLIENT) {
761             goto found;
762         }
763     }
764 
765     ::GetCursorPos(&p);
766     hit = ::WindowFromPoint(p);
767     while (hit != NULL) {
768         comp = AwtComponent::GetComponent(hit);
769 
770         if (comp != NULL) {
771             INT nHittest = (INT)::SendMessage(hit, WM_NCHITTEST,
772                                           0, MAKELPARAM(p.x, p.y));
773             /*
774              * Fix for BugTraq ID 4304024.
775              * Allow a non-default cursor only for the client area.
776              */
777             if (nHittest != HTCLIENT) {
778                 /*
779                  * When over the non-client area, send WM_SETCURSOR
780                  * to revert the cursor to an arrow.
781                  */
782                 ::SendMessage(hit, WM_SETCURSOR, (WPARAM)hit,
783                               MAKELPARAM(nHittest, WM_MOUSEMOVE));
784                 return NULL;
785             } else {
786               sm_cursorOn = hit;
787               goto found;
788             }
789         }
790 
791         if ((::GetWindowLong(hit, GWL_STYLE) & WS_CHILD) == 0) {
792             return NULL;
793         }
794         hit = ::GetParent(hit);
795     }
796 
797     return NULL;
798 
799 found:
800     jobject localRef = comp->GetTarget(env);
801     jobject globalRef = env->NewGlobalRef(localRef);
802     env->DeleteLocalRef(localRef);
803     return globalRef;
804 }
805 
SetColor(COLORREF c)806 void AwtComponent::SetColor(COLORREF c)
807 {
808     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
809     int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
810     if (grayscale != GS_NOTGRAY) {
811         int g;
812 
813         g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) +
814             .114 * ((c >> 16) & 0xFF) + 0.5);
815         // c = g | (g << 8) | (g << 16);
816         c = PALETTERGB(g, g, g);
817     }
818 
819     if (m_colorForeground == c) {
820         return;
821     }
822 
823     m_colorForeground = c;
824     if (m_penForeground != NULL) {
825         m_penForeground->Release();
826         m_penForeground = NULL;
827     }
828     VERIFY(::InvalidateRect(GetHWnd(), NULL, FALSE));
829 }
830 
SetBackgroundColor(COLORREF c)831 void AwtComponent::SetBackgroundColor(COLORREF c)
832 {
833     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
834     int grayscale = AwtWin32GraphicsDevice::GetGrayness(screen);
835     if (grayscale != GS_NOTGRAY) {
836         int g;
837 
838         g = (int) (.299 * (c & 0xFF) + .587 * ((c >> 8) & 0xFF) +
839             .114 * ((c >> 16) & 0xFF) + 0.5);
840         // c = g | (g << 8) | (g << 16);
841         c = PALETTERGB(g, g, g);
842     }
843 
844     if (m_colorBackground == c) {
845         return;
846     }
847     m_colorBackground = c;
848     m_backgroundColorSet = TRUE;
849     if (m_brushBackground != NULL) {
850         m_brushBackground->Release();
851         m_brushBackground = NULL;
852     }
853     VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
854 }
855 
GetForegroundPen()856 HPEN AwtComponent::GetForegroundPen()
857 {
858     if (m_penForeground == NULL) {
859         m_penForeground = AwtPen::Get(m_colorForeground);
860     }
861     return (HPEN)m_penForeground->GetHandle();
862 }
863 
GetBackgroundColor()864 COLORREF AwtComponent::GetBackgroundColor()
865 {
866     if (m_backgroundColorSet == FALSE) {
867         AwtComponent* c = this;
868         while ((c = c->GetParent()) != NULL) {
869             if (c->IsBackgroundColorSet()) {
870                 return c->GetBackgroundColor();
871             }
872         }
873     }
874     return m_colorBackground;
875 }
876 
GetBackgroundBrush()877 HBRUSH AwtComponent::GetBackgroundBrush()
878 {
879     if (m_backgroundColorSet == FALSE) {
880         if (m_brushBackground != NULL) {
881             m_brushBackground->Release();
882             m_brushBackground = NULL;
883         }
884           AwtComponent* c = this;
885           while ((c = c->GetParent()) != NULL) {
886               if (c->IsBackgroundColorSet()) {
887                   m_brushBackground =
888                       AwtBrush::Get(c->GetBackgroundColor());
889                   break;
890               }
891           }
892     }
893     if (m_brushBackground == NULL) {
894         m_brushBackground = AwtBrush::Get(m_colorBackground);
895     }
896     return (HBRUSH)m_brushBackground->GetHandle();
897 }
898 
SetFont(AwtFont * font)899 void AwtComponent::SetFont(AwtFont* font)
900 {
901     DASSERT(font != NULL);
902     if (font->GetAscent() < 0) {
903         AwtFont::SetupAscent(font);
904     }
905     SendMessage(WM_SETFONT, (WPARAM)font->GetHFont(), MAKELPARAM(FALSE, 0));
906     VERIFY(::InvalidateRect(GetHWnd(), NULL, TRUE));
907 }
908 
GetParent()909 AwtComponent* AwtComponent::GetParent()
910 {
911     HWND hwnd = ::GetParent(GetHWnd());
912     if (hwnd == NULL) {
913         return NULL;
914     }
915     return GetComponent(hwnd);
916 }
917 
GetContainer()918 AwtWindow* AwtComponent::GetContainer()
919 {
920     AwtComponent* comp = this;
921     while (comp != NULL) {
922         if (comp->IsContainer()) {
923             return (AwtWindow*)comp;
924         }
925         comp = comp->GetParent();
926     }
927     return NULL;
928 }
929 
Show()930 void AwtComponent::Show()
931 {
932     m_visible = true;
933     ::ShowWindow(GetHWnd(), SW_SHOWNA);
934 }
935 
Hide()936 void AwtComponent::Hide()
937 {
938     m_visible = false;
939     ::ShowWindow(GetHWnd(), SW_HIDE);
940 }
941 
942 BOOL
SetWindowPos(HWND wnd,HWND after,int x,int y,int w,int h,UINT flags)943 AwtComponent::SetWindowPos(HWND wnd, HWND after,
944                            int x, int y, int w, int h, UINT flags)
945 {
946     // Conditions we shouldn't handle:
947     // z-order changes, correct window dimensions
948     if (after != NULL || (w < 32767 && h < 32767)
949         || ((::GetWindowLong(wnd, GWL_STYLE) & WS_CHILD) == 0))
950     {
951         return ::SetWindowPos(wnd, after, x, y, w, h, flags);
952     }
953     WINDOWPLACEMENT wp;
954     ::ZeroMemory(&wp, sizeof(wp));
955 
956     wp.length = sizeof(wp);
957     ::GetWindowPlacement(wnd, &wp);
958     wp.rcNormalPosition.left = x;
959     wp.rcNormalPosition.top = y;
960     wp.rcNormalPosition.right = x + w;
961     wp.rcNormalPosition.bottom = y + h;
962     if ( flags & SWP_NOACTIVATE ) {
963         wp.showCmd = SW_SHOWNOACTIVATE;
964     }
965     ::SetWindowPlacement(wnd, &wp);
966     return 1;
967 }
968 
969 
Reshape(int x,int y,int w,int h)970 void AwtComponent::Reshape(int x, int y, int w, int h)
971 {
972 #if defined(DEBUG)
973     RECT        rc;
974     ::GetWindowRect(GetHWnd(), &rc);
975     ::MapWindowPoints(HWND_DESKTOP, ::GetParent(GetHWnd()), (LPPOINT)&rc, 2);
976     DTRACE_PRINTLN4("AwtComponent::Reshape from %d, %d, %d, %d", rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
977 #endif
978     AwtWindow* container = GetContainer();
979     AwtComponent* parent = GetParent();
980     if (container != NULL && container == parent) {
981         container->SubtractInsetPoint(x, y);
982     }
983     DTRACE_PRINTLN4("AwtComponent::Reshape to %d, %d, %d, %d", x, y, w, h);
984     UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
985 
986     RECT        r;
987 
988     ::GetWindowRect(GetHWnd(), &r);
989     // if the component size is changing , don't copy window bits
990     if (r.right - r.left != w || r.bottom - r.top != h) {
991         flags |= SWP_NOCOPYBITS;
992     }
993 
994     if (parent && _tcscmp(parent->GetClassName(), TEXT("SunAwtScrollPane")) == 0) {
995         if (x > 0) {
996             x = 0;
997         }
998         if (y > 0) {
999             y = 0;
1000         }
1001     }
1002     if (m_hdwp != NULL) {
1003         m_hdwp = ::DeferWindowPos(m_hdwp, GetHWnd(), 0, x, y, w, h, flags);
1004         DASSERT(m_hdwp != NULL);
1005     } else {
1006         /*
1007          * Fox for 4046446
1008          * If window has dimensions above the short int limit, ::SetWindowPos doesn't work.
1009          * We should use SetWindowPlacement instead.
1010          */
1011         SetWindowPos(GetHWnd(), 0, x, y, w, h, flags);
1012     }
1013 }
1014 
SetScrollValues(UINT bar,int min,int value,int max)1015 void AwtComponent::SetScrollValues(UINT bar, int min, int value, int max)
1016 {
1017     int minTmp, maxTmp;
1018 
1019     ::GetScrollRange(GetHWnd(), bar, &minTmp, &maxTmp);
1020     if (min == INT_MAX) {
1021         min = minTmp;
1022     }
1023     if (value == INT_MAX) {
1024         value = ::GetScrollPos(GetHWnd(), bar);
1025     }
1026     if (max == INT_MAX) {
1027         max = maxTmp;
1028     }
1029     if (min == max) {
1030         max++;
1031     }
1032     ::SetScrollRange(GetHWnd(), bar, min, max, FALSE);
1033     ::SetScrollPos(GetHWnd(), bar, value, TRUE);
1034 }
1035 
1036 /*
1037  * Save Global Reference of sun.awt.windows.WInputMethod object
1038  */
SetInputMethod(jobject im,BOOL useNativeCompWindow)1039 void AwtComponent::SetInputMethod(jobject im, BOOL useNativeCompWindow)
1040 {
1041     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1042 
1043     if (m_InputMethod!=NULL)
1044         env->DeleteGlobalRef(m_InputMethod);
1045 
1046     if (im!=NULL){
1047         m_InputMethod = env->NewGlobalRef(im);
1048         m_useNativeCompWindow = useNativeCompWindow;
1049     } else {
1050         m_InputMethod = NULL;
1051         m_useNativeCompWindow = TRUE;
1052     }
1053 
1054 }
1055 
1056 /*
1057  * Opportunity to process and/or eat a message before it is dispatched
1058  */
PreProcessMsg(MSG & msg)1059 MsgRouting AwtComponent::PreProcessMsg(MSG& msg)
1060 {
1061     return mrPassAlong;
1062 }
1063 
1064 static UINT lastMessage = WM_NULL;
1065 
1066 #ifndef SPY_MESSAGES
1067 #define SpyWinMessage(hwin,msg,str)
1068 #else
1069 
1070 #define FMT_MSG(x,y) case x: _stprintf(szBuf, \
1071     "0x%8.8x(%s):%s\n", hwnd, szComment, y); break;
1072 #define WIN_MSG(x) FMT_MSG(x,#x)
1073 
SpyWinMessage(HWND hwnd,UINT message,LPCTSTR szComment)1074 void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) {
1075 
1076     TCHAR szBuf[256];
1077 
1078     switch (message) {
1079         WIN_MSG(WM_NULL)
1080         WIN_MSG(WM_CREATE)
1081         WIN_MSG(WM_DESTROY)
1082         WIN_MSG(WM_MOVE)
1083         WIN_MSG(WM_SIZE)
1084         WIN_MSG(WM_ACTIVATE)
1085         WIN_MSG(WM_SETFOCUS)
1086         WIN_MSG(WM_KILLFOCUS)
1087         WIN_MSG(WM_ENABLE)
1088         WIN_MSG(WM_SETREDRAW)
1089         WIN_MSG(WM_SETTEXT)
1090         WIN_MSG(WM_GETTEXT)
1091         WIN_MSG(WM_GETTEXTLENGTH)
1092         WIN_MSG(WM_PAINT)
1093         WIN_MSG(WM_CLOSE)
1094         WIN_MSG(WM_QUERYENDSESSION)
1095         WIN_MSG(WM_QUIT)
1096         WIN_MSG(WM_QUERYOPEN)
1097         WIN_MSG(WM_ERASEBKGND)
1098         WIN_MSG(WM_SYSCOLORCHANGE)
1099         WIN_MSG(WM_ENDSESSION)
1100         WIN_MSG(WM_SHOWWINDOW)
1101         FMT_MSG(WM_WININICHANGE,"WM_WININICHANGE/WM_SETTINGCHANGE")
1102         WIN_MSG(WM_DEVMODECHANGE)
1103         WIN_MSG(WM_ACTIVATEAPP)
1104         WIN_MSG(WM_FONTCHANGE)
1105         WIN_MSG(WM_TIMECHANGE)
1106         WIN_MSG(WM_CANCELMODE)
1107         WIN_MSG(WM_SETCURSOR)
1108         WIN_MSG(WM_MOUSEACTIVATE)
1109         WIN_MSG(WM_CHILDACTIVATE)
1110         WIN_MSG(WM_QUEUESYNC)
1111         WIN_MSG(WM_GETMINMAXINFO)
1112         WIN_MSG(WM_PAINTICON)
1113         WIN_MSG(WM_ICONERASEBKGND)
1114         WIN_MSG(WM_NEXTDLGCTL)
1115         WIN_MSG(WM_SPOOLERSTATUS)
1116         WIN_MSG(WM_DRAWITEM)
1117         WIN_MSG(WM_MEASUREITEM)
1118         WIN_MSG(WM_DELETEITEM)
1119         WIN_MSG(WM_VKEYTOITEM)
1120         WIN_MSG(WM_CHARTOITEM)
1121         WIN_MSG(WM_SETFONT)
1122         WIN_MSG(WM_GETFONT)
1123         WIN_MSG(WM_SETHOTKEY)
1124         WIN_MSG(WM_GETHOTKEY)
1125         WIN_MSG(WM_QUERYDRAGICON)
1126         WIN_MSG(WM_COMPAREITEM)
1127         FMT_MSG(0x003D, "WM_GETOBJECT")
1128         WIN_MSG(WM_COMPACTING)
1129         WIN_MSG(WM_COMMNOTIFY)
1130         WIN_MSG(WM_WINDOWPOSCHANGING)
1131         WIN_MSG(WM_WINDOWPOSCHANGED)
1132         WIN_MSG(WM_POWER)
1133         WIN_MSG(WM_COPYDATA)
1134         WIN_MSG(WM_CANCELJOURNAL)
1135         WIN_MSG(WM_NOTIFY)
1136         WIN_MSG(WM_INPUTLANGCHANGEREQUEST)
1137         WIN_MSG(WM_INPUTLANGCHANGE)
1138         WIN_MSG(WM_TCARD)
1139         WIN_MSG(WM_HELP)
1140         WIN_MSG(WM_USERCHANGED)
1141         WIN_MSG(WM_NOTIFYFORMAT)
1142         WIN_MSG(WM_CONTEXTMENU)
1143         WIN_MSG(WM_STYLECHANGING)
1144         WIN_MSG(WM_STYLECHANGED)
1145         WIN_MSG(WM_DISPLAYCHANGE)
1146         WIN_MSG(WM_GETICON)
1147         WIN_MSG(WM_SETICON)
1148         WIN_MSG(WM_NCCREATE)
1149         WIN_MSG(WM_NCDESTROY)
1150         WIN_MSG(WM_NCCALCSIZE)
1151         WIN_MSG(WM_NCHITTEST)
1152         WIN_MSG(WM_NCPAINT)
1153         WIN_MSG(WM_NCACTIVATE)
1154         WIN_MSG(WM_GETDLGCODE)
1155         WIN_MSG(WM_SYNCPAINT)
1156         WIN_MSG(WM_NCMOUSEMOVE)
1157         WIN_MSG(WM_NCLBUTTONDOWN)
1158         WIN_MSG(WM_NCLBUTTONUP)
1159         WIN_MSG(WM_NCLBUTTONDBLCLK)
1160         WIN_MSG(WM_NCRBUTTONDOWN)
1161         WIN_MSG(WM_NCRBUTTONUP)
1162         WIN_MSG(WM_NCRBUTTONDBLCLK)
1163         WIN_MSG(WM_NCMBUTTONDOWN)
1164         WIN_MSG(WM_NCMBUTTONUP)
1165         WIN_MSG(WM_NCMBUTTONDBLCLK)
1166         WIN_MSG(WM_KEYDOWN)
1167         WIN_MSG(WM_KEYUP)
1168         WIN_MSG(WM_CHAR)
1169         WIN_MSG(WM_DEADCHAR)
1170         WIN_MSG(WM_SYSKEYDOWN)
1171         WIN_MSG(WM_SYSKEYUP)
1172         WIN_MSG(WM_SYSCHAR)
1173         WIN_MSG(WM_SYSDEADCHAR)
1174         WIN_MSG(WM_IME_STARTCOMPOSITION)
1175         WIN_MSG(WM_IME_ENDCOMPOSITION)
1176         WIN_MSG(WM_IME_COMPOSITION)
1177         WIN_MSG(WM_INITDIALOG)
1178         WIN_MSG(WM_COMMAND)
1179         WIN_MSG(WM_SYSCOMMAND)
1180         WIN_MSG(WM_TIMER)
1181         WIN_MSG(WM_HSCROLL)
1182         WIN_MSG(WM_VSCROLL)
1183         WIN_MSG(WM_INITMENU)
1184         WIN_MSG(WM_INITMENUPOPUP)
1185         WIN_MSG(WM_MENUSELECT)
1186         WIN_MSG(WM_MENUCHAR)
1187         WIN_MSG(WM_ENTERIDLE)
1188         FMT_MSG(0x0122, "WM_MENURBUTTONUP")
1189         FMT_MSG(0x0123, "WM_MENUDRAG")
1190         FMT_MSG(0x0124, "WM_MENUGETOBJECT")
1191         FMT_MSG(0x0125, "WM_UNINITMENUPOPUP")
1192         FMT_MSG(0x0126, "WM_MENUCOMMAND")
1193         WIN_MSG(WM_CTLCOLORMSGBOX)
1194         WIN_MSG(WM_CTLCOLOREDIT)
1195         WIN_MSG(WM_CTLCOLORLISTBOX)
1196         WIN_MSG(WM_CTLCOLORBTN)
1197         WIN_MSG(WM_CTLCOLORDLG)
1198         WIN_MSG(WM_CTLCOLORSCROLLBAR)
1199         WIN_MSG(WM_CTLCOLORSTATIC)
1200         WIN_MSG(WM_MOUSEMOVE)
1201         WIN_MSG(WM_LBUTTONDOWN)
1202         WIN_MSG(WM_LBUTTONUP)
1203         WIN_MSG(WM_LBUTTONDBLCLK)
1204         WIN_MSG(WM_RBUTTONDOWN)
1205         WIN_MSG(WM_RBUTTONUP)
1206         WIN_MSG(WM_RBUTTONDBLCLK)
1207         WIN_MSG(WM_MBUTTONDOWN)
1208         WIN_MSG(WM_MBUTTONUP)
1209         WIN_MSG(WM_MBUTTONDBLCLK)
1210         WIN_MSG(WM_XBUTTONDBLCLK)
1211         WIN_MSG(WM_XBUTTONDOWN)
1212         WIN_MSG(WM_XBUTTONUP)
1213         WIN_MSG(WM_MOUSEWHEEL)
1214         WIN_MSG(WM_PARENTNOTIFY)
1215         WIN_MSG(WM_ENTERMENULOOP)
1216         WIN_MSG(WM_EXITMENULOOP)
1217         WIN_MSG(WM_NEXTMENU)
1218         WIN_MSG(WM_SIZING)
1219         WIN_MSG(WM_CAPTURECHANGED)
1220         WIN_MSG(WM_MOVING)
1221         WIN_MSG(WM_POWERBROADCAST)
1222         WIN_MSG(WM_DEVICECHANGE)
1223         WIN_MSG(WM_MDICREATE)
1224         WIN_MSG(WM_MDIDESTROY)
1225         WIN_MSG(WM_MDIACTIVATE)
1226         WIN_MSG(WM_MDIRESTORE)
1227         WIN_MSG(WM_MDINEXT)
1228         WIN_MSG(WM_MDIMAXIMIZE)
1229         WIN_MSG(WM_MDITILE)
1230         WIN_MSG(WM_MDICASCADE)
1231         WIN_MSG(WM_MDIICONARRANGE)
1232         WIN_MSG(WM_MDIGETACTIVE)
1233         WIN_MSG(WM_MDISETMENU)
1234         WIN_MSG(WM_ENTERSIZEMOVE)
1235         WIN_MSG(WM_EXITSIZEMOVE)
1236         WIN_MSG(WM_DROPFILES)
1237         WIN_MSG(WM_MDIREFRESHMENU)
1238         WIN_MSG(WM_IME_SETCONTEXT)
1239         WIN_MSG(WM_IME_NOTIFY)
1240         WIN_MSG(WM_IME_CONTROL)
1241         WIN_MSG(WM_IME_COMPOSITIONFULL)
1242         WIN_MSG(WM_IME_SELECT)
1243         WIN_MSG(WM_IME_CHAR)
1244         FMT_MSG(WM_IME_REQUEST)
1245         WIN_MSG(WM_IME_KEYDOWN)
1246         WIN_MSG(WM_IME_KEYUP)
1247         FMT_MSG(0x02A1, "WM_MOUSEHOVER")
1248         FMT_MSG(0x02A3, "WM_MOUSELEAVE")
1249         WIN_MSG(WM_CUT)
1250         WIN_MSG(WM_COPY)
1251         WIN_MSG(WM_PASTE)
1252         WIN_MSG(WM_CLEAR)
1253         WIN_MSG(WM_UNDO)
1254         WIN_MSG(WM_RENDERFORMAT)
1255         WIN_MSG(WM_RENDERALLFORMATS)
1256         WIN_MSG(WM_DESTROYCLIPBOARD)
1257         WIN_MSG(WM_DRAWCLIPBOARD)
1258         WIN_MSG(WM_PAINTCLIPBOARD)
1259         WIN_MSG(WM_VSCROLLCLIPBOARD)
1260         WIN_MSG(WM_SIZECLIPBOARD)
1261         WIN_MSG(WM_ASKCBFORMATNAME)
1262         WIN_MSG(WM_CHANGECBCHAIN)
1263         WIN_MSG(WM_HSCROLLCLIPBOARD)
1264         WIN_MSG(WM_QUERYNEWPALETTE)
1265         WIN_MSG(WM_PALETTEISCHANGING)
1266         WIN_MSG(WM_PALETTECHANGED)
1267         WIN_MSG(WM_HOTKEY)
1268         WIN_MSG(WM_PRINT)
1269         WIN_MSG(WM_PRINTCLIENT)
1270         WIN_MSG(WM_HANDHELDFIRST)
1271         WIN_MSG(WM_HANDHELDLAST)
1272         WIN_MSG(WM_AFXFIRST)
1273         WIN_MSG(WM_AFXLAST)
1274         WIN_MSG(WM_PENWINFIRST)
1275         WIN_MSG(WM_PENWINLAST)
1276         WIN_MSG(WM_AWT_COMPONENT_CREATE)
1277         WIN_MSG(WM_AWT_DESTROY_WINDOW)
1278         WIN_MSG(WM_AWT_MOUSEENTER)
1279         WIN_MSG(WM_AWT_MOUSEEXIT)
1280         WIN_MSG(WM_AWT_COMPONENT_SHOW)
1281         WIN_MSG(WM_AWT_COMPONENT_HIDE)
1282         WIN_MSG(WM_AWT_COMPONENT_SETFOCUS)
1283         WIN_MSG(WM_AWT_WINDOW_SETACTIVE)
1284         WIN_MSG(WM_AWT_LIST_SETMULTISELECT)
1285         WIN_MSG(WM_AWT_HANDLE_EVENT)
1286         WIN_MSG(WM_AWT_PRINT_COMPONENT)
1287         WIN_MSG(WM_AWT_RESHAPE_COMPONENT)
1288         WIN_MSG(WM_AWT_SETALWAYSONTOP)
1289         WIN_MSG(WM_AWT_BEGIN_VALIDATE)
1290         WIN_MSG(WM_AWT_END_VALIDATE)
1291         WIN_MSG(WM_AWT_FORWARD_CHAR)
1292         WIN_MSG(WM_AWT_FORWARD_BYTE)
1293         WIN_MSG(WM_AWT_SET_SCROLL_INFO)
1294         WIN_MSG(WM_AWT_CREATECONTEXT)
1295         WIN_MSG(WM_AWT_DESTROYCONTEXT)
1296         WIN_MSG(WM_AWT_ASSOCIATECONTEXT)
1297         WIN_MSG(WM_AWT_GET_DEFAULT_IME_HANDLER)
1298         WIN_MSG(WM_AWT_HANDLE_NATIVE_IME_EVENT)
1299         WIN_MSG(WM_AWT_PRE_KEYDOWN)
1300         WIN_MSG(WM_AWT_PRE_KEYUP)
1301         WIN_MSG(WM_AWT_PRE_SYSKEYDOWN)
1302         WIN_MSG(WM_AWT_PRE_SYSKEYUP)
1303         WIN_MSG(WM_AWT_ENDCOMPOSITION,)
1304         WIN_MSG(WM_AWT_DISPOSE,)
1305         WIN_MSG(WM_AWT_DELETEOBJECT,)
1306         WIN_MSG(WM_AWT_SETCONVERSIONSTATUS,)
1307         WIN_MSG(WM_AWT_GETCONVERSIONSTATUS,)
1308         WIN_MSG(WM_AWT_SETOPENSTATUS,)
1309         WIN_MSG(WM_AWT_GETOPENSTATUS)
1310         WIN_MSG(WM_AWT_ACTIVATEKEYBOARDLAYOUT)
1311         WIN_MSG(WM_AWT_OPENCANDIDATEWINDOW)
1312         WIN_MSG(WM_AWT_DLG_SHOWMODAL,)
1313         WIN_MSG(WM_AWT_DLG_ENDMODAL,)
1314         WIN_MSG(WM_AWT_SETCURSOR,)
1315         WIN_MSG(WM_AWT_WAIT_FOR_SINGLE_OBJECT,)
1316         WIN_MSG(WM_AWT_INVOKE_METHOD,)
1317         WIN_MSG(WM_AWT_INVOKE_VOID_METHOD,)
1318         WIN_MSG(WM_AWT_EXECUTE_SYNC,)
1319         WIN_MSG(WM_AWT_CURSOR_SYNC)
1320         WIN_MSG(WM_AWT_GETDC)
1321         WIN_MSG(WM_AWT_RELEASEDC)
1322         WIN_MSG(WM_AWT_RELEASE_ALL_DCS)
1323         WIN_MSG(WM_AWT_SHOWCURSOR)
1324         WIN_MSG(WM_AWT_HIDECURSOR)
1325         WIN_MSG(WM_AWT_CREATE_PRINTED_PIXELS)
1326         WIN_MSG(WM_AWT_OBJECTLISTCLEANUP)
1327         default:
1328             sprintf(szBuf, "0x%8.8x(%s):Unknown message 0x%8.8x\n",
1329                 hwnd, szComment, message);
1330             break;
1331     }
1332     printf(szBuf);
1333 }
1334 
1335 #endif /* SPY_MESSAGES */
1336 
1337 /*
1338  * Dispatch messages for this window class--general component
1339  */
WindowProc(UINT message,WPARAM wParam,LPARAM lParam)1340 LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
1341 {
1342     CounterHelper ch(&m_MessagesProcessing);
1343 
1344     JNILocalFrame lframe(AwtToolkit::GetEnv(), 10);
1345     SpyWinMessage(GetHWnd(), message,
1346         (message == WM_AWT_RELEASE_ALL_DCS) ? TEXT("Disposed Component") : GetClassName());
1347 
1348     LRESULT retValue = 0;
1349     MsgRouting mr = mrDoDefault;
1350     AwtToolkit::GetInstance().eventNumber++;
1351 
1352     static BOOL ignoreNextLBTNUP = FALSE; //Ignore next LBUTTONUP msg?
1353 
1354     lastMessage = message;
1355 
1356     if (message == WmAwtIsComponent) {
1357     // special message to identify AWT HWND's without using
1358     // resource hogging ::SetProp
1359         return (LRESULT)TRUE;
1360     }
1361 
1362     DWORD curPos = 0;
1363 
1364     UINT switchMessage = message;
1365     switch (switchMessage) {
1366       case WM_AWT_GETDC:
1367       {
1368             HDC hDC;
1369             // First, release the DCs scheduled for deletion
1370             ReleaseDCList(GetHWnd(), passiveDCList);
1371 
1372             GetDCReturnStruct *returnStruct = new GetDCReturnStruct;
1373             returnStruct->gdiLimitReached = FALSE;
1374             if (AwtGDIObject::IncrementIfAvailable()) {
1375                 hDC = ::GetDCEx(GetHWnd(), NULL,
1376                                 DCX_CACHE | DCX_CLIPCHILDREN |
1377                                 DCX_CLIPSIBLINGS);
1378                 if (hDC != NULL) {
1379                     // Add new DC to list of DC's associated with this Component
1380                     activeDCList.AddDC(hDC, GetHWnd());
1381                 } else {
1382                     // Creation failed; decrement counter in AwtGDIObject
1383                     AwtGDIObject::Decrement();
1384                 }
1385             } else {
1386                 hDC = NULL;
1387                 returnStruct->gdiLimitReached = TRUE;
1388             }
1389             returnStruct->hDC = hDC;
1390             retValue = (LRESULT)returnStruct;
1391             mr = mrConsume;
1392             break;
1393       }
1394       case WM_AWT_RELEASEDC:
1395       {
1396             HDC hDC = (HDC)wParam;
1397             MoveDCToPassiveList(hDC, GetHWnd());
1398             ReleaseDCList(GetHWnd(), passiveDCList);
1399             mr = mrConsume;
1400             break;
1401       }
1402       case WM_AWT_RELEASE_ALL_DCS:
1403       {
1404             // Called during Component destruction.  Gets current list of
1405             // DC's associated with Component and releases each DC.
1406             ReleaseDCList(GetHWnd(), activeDCList);
1407             ReleaseDCList(GetHWnd(), passiveDCList);
1408             mr = mrConsume;
1409             break;
1410       }
1411       case WM_AWT_SHOWCURSOR:
1412           ::ShowCursor(TRUE);
1413           break;
1414       case WM_AWT_HIDECURSOR:
1415           ::ShowCursor(FALSE);
1416           break;
1417       case WM_CREATE: mr = WmCreate(); break;
1418       case WM_CLOSE:      mr = WmClose(); break;
1419       case WM_DESTROY:    mr = WmDestroy(); break;
1420       case WM_NCDESTROY:  mr = WmNcDestroy(); break;
1421 
1422       case WM_ERASEBKGND:
1423           mr = WmEraseBkgnd((HDC)wParam, *(BOOL*)&retValue); break;
1424       case WM_PAINT:
1425           CheckFontSmoothingSettings(GetHWnd());
1426           /* Set draw state */
1427           SetDrawState(GetDrawState() | JAWT_LOCK_CLIP_CHANGED);
1428           mr = WmPaint((HDC)wParam);
1429           break;
1430 
1431       case WM_GETMINMAXINFO:
1432           mr = WmGetMinMaxInfo((LPMINMAXINFO)lParam);
1433           break;
1434 
1435       case WM_WINDOWPOSCHANGING:
1436       {
1437           // We process this message so that we can synchronize access to
1438           // a moving window.  The Scale/Blt functions in Win32BlitLoops
1439           // take the same windowMoveLock to ensure that a window is not
1440           // moving while we are trying to copy pixels into it.
1441           WINDOWPOS *lpPosInfo = (WINDOWPOS *)lParam;
1442           if ((lpPosInfo->flags & (SWP_NOMOVE | SWP_NOSIZE)) !=
1443               (SWP_NOMOVE | SWP_NOSIZE))
1444           {
1445               // Move or Size command.
1446               // Windows tends to send erroneous events that the window
1447               // is about to move when the coordinates are exactly the
1448               // same as the last time.  This can cause problems with
1449               // our windowMoveLock CriticalSection because we enter it
1450               // here and never get to WM_WINDOWPOSCHANGED to release it.
1451               // So make sure this is a real move/size event before bothering
1452               // to grab the critical section.
1453               BOOL takeLock = FALSE;
1454               if (!(lpPosInfo->flags & SWP_NOMOVE) &&
1455                   ((windowMoveLockPosX != lpPosInfo->x) ||
1456                    (windowMoveLockPosY != lpPosInfo->y)))
1457               {
1458                   // Real move event
1459                   takeLock = TRUE;
1460                   windowMoveLockPosX = lpPosInfo->x;
1461                   windowMoveLockPosY = lpPosInfo->y;
1462               }
1463               if (!(lpPosInfo->flags & SWP_NOSIZE) &&
1464                   ((windowMoveLockPosCX != lpPosInfo->cx) ||
1465                    (windowMoveLockPosCY != lpPosInfo->cy)))
1466               {
1467                   // Real size event
1468                   takeLock = TRUE;
1469                   windowMoveLockPosCX = lpPosInfo->cx;
1470                   windowMoveLockPosCY = lpPosInfo->cy;
1471               }
1472               if (takeLock) {
1473                   if (!windowMoveLockHeld) {
1474                       windowMoveLock.Enter();
1475                       windowMoveLockHeld = TRUE;
1476                   }
1477               }
1478           }
1479           mr = WmWindowPosChanging(lParam);
1480           break;
1481       }
1482       case WM_WINDOWPOSCHANGED:
1483       {
1484           // Release lock grabbed in the POSCHANGING message
1485           if (windowMoveLockHeld) {
1486               windowMoveLockHeld = FALSE;
1487               windowMoveLock.Leave();
1488           }
1489           mr = WmWindowPosChanged(lParam);
1490           break;
1491       }
1492       case WM_MOVE: {
1493           RECT r;
1494           ::GetWindowRect(GetHWnd(), &r);
1495           mr = WmMove(r.left, r.top);
1496           break;
1497       }
1498       case WM_SIZE:
1499       {
1500           RECT r;
1501           // fix 4128317 : use GetClientRect for full 32-bit int precision and
1502           // to avoid negative client area dimensions overflowing 16-bit params - robi
1503           ::GetClientRect( GetHWnd(), &r );
1504           mr = WmSize(static_cast<UINT>(wParam), r.right - r.left, r.bottom - r.top);
1505           //mr = WmSize(wParam, LOWORD(lParam), HIWORD(lParam));
1506           SetCompositionWindow(r);
1507           break;
1508       }
1509       case WM_SIZING:
1510           mr = WmSizing();
1511           break;
1512       case WM_SHOWWINDOW:
1513           mr = WmShowWindow(static_cast<BOOL>(wParam),
1514                             static_cast<UINT>(lParam)); break;
1515       case WM_SYSCOMMAND:
1516           mr = WmSysCommand(static_cast<UINT>(wParam & 0xFFF0),
1517                             GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1518           break;
1519       case WM_EXITSIZEMOVE:
1520           mr = WmExitSizeMove();
1521           break;
1522       // Bug #4039858 (Selecting menu item causes bogus mouse click event)
1523       case WM_ENTERMENULOOP:
1524           mr = WmEnterMenuLoop((BOOL)wParam);
1525           sm_bMenuLoop = TRUE;
1526           // we need to release grab if menu is shown
1527           if (AwtWindow::GetGrabbedWindow() != NULL) {
1528               AwtWindow::GetGrabbedWindow()->Ungrab();
1529           }
1530           break;
1531       case WM_EXITMENULOOP:
1532           mr = WmExitMenuLoop((BOOL)wParam);
1533           sm_bMenuLoop = FALSE;
1534           break;
1535 
1536       // We don't expect any focus messages on non-proxy component,
1537       // except those that came from Java.
1538       case WM_SETFOCUS:
1539           if (sm_inSynthesizeFocus) {
1540               mr = WmSetFocus((HWND)wParam);
1541           } else {
1542               mr = mrConsume;
1543           }
1544           break;
1545       case WM_KILLFOCUS:
1546           if (sm_inSynthesizeFocus) {
1547               mr = WmKillFocus((HWND)wParam);
1548           } else {
1549               mr = mrConsume;
1550           }
1551           break;
1552       case WM_ACTIVATE: {
1553           UINT nState = LOWORD(wParam);
1554           BOOL fMinimized = (BOOL)HIWORD(wParam);
1555           mr = mrConsume;
1556 
1557           if (!sm_suppressFocusAndActivation &&
1558               (!fMinimized || (nState == WA_INACTIVE)))
1559           {
1560               mr = WmActivate(nState, fMinimized, (HWND)lParam);
1561 
1562               // When the window is deactivated, send WM_IME_ENDCOMPOSITION
1563               // message to deactivate the composition window so that
1564               // it won't receive keyboard input focus.
1565               HIMC hIMC;
1566               HWND hwnd = ImmGetHWnd();
1567               if ((hIMC = ImmGetContext(hwnd)) != NULL) {
1568                   ImmReleaseContext(hwnd, hIMC);
1569                   DefWindowProc(WM_IME_ENDCOMPOSITION, 0, 0);
1570               }
1571           }
1572           break;
1573       }
1574       case WM_MOUSEACTIVATE: {
1575           AwtWindow *window = GetContainer();
1576           if (window && window->IsFocusableWindow()) {
1577               // AWT/Swing will later request focus to a proper component
1578               // on handling the Java mouse event. Anyway, we have to
1579               // activate the window here as it works both for AWT & Swing.
1580               // Do it in our own fassion,
1581               window->AwtSetActiveWindow(TRUE, LOWORD(lParam)/*hittest*/);
1582           }
1583           mr = mrConsume;
1584           retValue = MA_NOACTIVATE;
1585           break;
1586       }
1587       case WM_CTLCOLORMSGBOX:
1588       case WM_CTLCOLOREDIT:
1589       case WM_CTLCOLORLISTBOX:
1590       case WM_CTLCOLORBTN:
1591       case WM_CTLCOLORDLG:
1592       case WM_CTLCOLORSCROLLBAR:
1593       case WM_CTLCOLORSTATIC:
1594           mr = WmCtlColor((HDC)wParam, (HWND)lParam,
1595                           message-WM_CTLCOLORMSGBOX+CTLCOLOR_MSGBOX,
1596                           *(HBRUSH*)&retValue);
1597           break;
1598       case WM_HSCROLL:
1599           mr = WmHScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
1600           break;
1601       case WM_VSCROLL:
1602           mr = WmVScroll(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
1603           break;
1604       // 4664415: We're seeing a WM_LBUTTONUP when the user releases the
1605       // mouse button after a WM_NCLBUTTONDBLCLK.  We want to ignore this
1606       // WM_LBUTTONUP, so we set a flag in WM_NCLBUTTONDBLCLK and look for the
1607       // flag on a WM_LBUTTONUP.  -bchristi
1608       case WM_NCLBUTTONDBLCLK:
1609           mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON | DBL_CLICK);
1610           if (mr == mrDoDefault) {
1611               ignoreNextLBTNUP = TRUE;
1612           }
1613           break;
1614       case WM_NCLBUTTONDOWN:
1615           mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON);
1616           ignoreNextLBTNUP = FALSE;
1617           break;
1618       case WM_NCLBUTTONUP:
1619           mr = WmNcMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), LEFT_BUTTON);
1620           break;
1621       case WM_NCRBUTTONDOWN:
1622            mr = WmNcMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RIGHT_BUTTON);
1623            break;
1624       case WM_LBUTTONUP:
1625           if (ignoreNextLBTNUP) {
1626               ignoreNextLBTNUP = FALSE;
1627               return mrDoDefault;
1628           }
1629           //fall-through
1630       case WM_LBUTTONDOWN:
1631           ignoreNextLBTNUP = FALSE;
1632           //fall-through
1633       case WM_LBUTTONDBLCLK:
1634       case WM_RBUTTONDOWN:
1635       case WM_RBUTTONDBLCLK:
1636       case WM_RBUTTONUP:
1637       case WM_MBUTTONDOWN:
1638       case WM_MBUTTONDBLCLK:
1639       case WM_MBUTTONUP:
1640       case WM_XBUTTONDBLCLK:
1641       case WM_XBUTTONDOWN:
1642       case WM_XBUTTONUP:
1643       case WM_MOUSEMOVE:
1644       case WM_MOUSEWHEEL:
1645       case WM_AWT_MOUSEENTER:
1646       case WM_AWT_MOUSEEXIT:
1647           curPos = ::GetMessagePos();
1648           POINT myPos;
1649           myPos.x = GET_X_LPARAM(curPos);
1650           myPos.y = GET_Y_LPARAM(curPos);
1651           ::ScreenToClient(GetHWnd(), &myPos);
1652           switch(switchMessage) {
1653           case WM_AWT_MOUSEENTER:
1654               mr = WmMouseEnter(static_cast<UINT>(wParam), myPos.x, myPos.y);
1655               break;
1656           case WM_LBUTTONDOWN:
1657           case WM_LBUTTONDBLCLK:
1658               mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1659                                LEFT_BUTTON);
1660               break;
1661           case WM_LBUTTONUP:
1662               mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1663                              LEFT_BUTTON);
1664               break;
1665           case WM_MOUSEMOVE:
1666               mr = WmMouseMove(static_cast<UINT>(wParam), myPos.x, myPos.y);
1667               break;
1668           case WM_MBUTTONDOWN:
1669           case WM_MBUTTONDBLCLK:
1670               mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1671                                MIDDLE_BUTTON);
1672               break;
1673           case WM_XBUTTONDOWN:
1674           case WM_XBUTTONDBLCLK:
1675               if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) {
1676                   if (HIWORD(wParam) == 1) {
1677                       mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1678                                        X1_BUTTON);
1679                   }
1680                   if (HIWORD(wParam) == 2) {
1681                       mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1682                                        X2_BUTTON);
1683                   }
1684               }
1685               break;
1686           case WM_XBUTTONUP:
1687               if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) {
1688                   if (HIWORD(wParam) == 1) {
1689                       mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1690                                      X1_BUTTON);
1691                   }
1692                   if (HIWORD(wParam) == 2) {
1693                       mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1694                                      X2_BUTTON);
1695                   }
1696               }
1697               break;
1698           case WM_RBUTTONDOWN:
1699           case WM_RBUTTONDBLCLK:
1700               mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y,
1701                                RIGHT_BUTTON);
1702               break;
1703           case WM_RBUTTONUP:
1704               mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1705                              RIGHT_BUTTON);
1706               break;
1707           case WM_MBUTTONUP:
1708               mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y,
1709                              MIDDLE_BUTTON);
1710               break;
1711           case WM_AWT_MOUSEEXIT:
1712               mr = WmMouseExit(static_cast<UINT>(wParam), myPos.x, myPos.y);
1713               break;
1714           case  WM_MOUSEWHEEL:
1715               mr = WmMouseWheel(GET_KEYSTATE_WPARAM(wParam),
1716                                 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
1717                                 GET_WHEEL_DELTA_WPARAM(wParam));
1718               break;
1719           }
1720           break;
1721       case WM_TOUCH:
1722           WmTouch(wParam, lParam);
1723           break;
1724       case WM_SETCURSOR:
1725           mr = mrDoDefault;
1726           if (LOWORD(lParam) == HTCLIENT) {
1727               if (AwtComponent* comp =
1728                                     AwtComponent::GetComponent((HWND)wParam)) {
1729                   AwtCursor::UpdateCursor(comp);
1730                   mr = mrConsume;
1731               }
1732           }
1733           break;
1734 
1735       case WM_KEYDOWN:
1736           mr = WmKeyDown(static_cast<UINT>(wParam),
1737                          LOWORD(lParam), HIWORD(lParam), FALSE);
1738           break;
1739       case WM_KEYUP:
1740           mr = WmKeyUp(static_cast<UINT>(wParam),
1741                        LOWORD(lParam), HIWORD(lParam), FALSE);
1742           break;
1743       case WM_SYSKEYDOWN:
1744           mr = WmKeyDown(static_cast<UINT>(wParam),
1745                          LOWORD(lParam), HIWORD(lParam), TRUE);
1746           break;
1747       case WM_SYSKEYUP:
1748           mr = WmKeyUp(static_cast<UINT>(wParam),
1749                        LOWORD(lParam), HIWORD(lParam), TRUE);
1750           break;
1751       case WM_IME_SETCONTEXT:
1752           // lParam is passed as pointer and it can be modified.
1753           mr = WmImeSetContext(static_cast<BOOL>(wParam), &lParam);
1754           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1755           break;
1756       case WM_IME_NOTIFY:
1757           mr = WmImeNotify(wParam, lParam);
1758           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1759           break;
1760       case WM_IME_STARTCOMPOSITION:
1761           mr = WmImeStartComposition();
1762           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1763           break;
1764       case WM_IME_ENDCOMPOSITION:
1765           mr = WmImeEndComposition();
1766           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1767           break;
1768       case WM_IME_COMPOSITION: {
1769           WORD dbcschar = static_cast<WORD>(wParam);
1770           mr = WmImeComposition(dbcschar, lParam);
1771           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1772           break;
1773       }
1774       case WM_IME_CONTROL:
1775       case WM_IME_COMPOSITIONFULL:
1776       case WM_IME_SELECT:
1777       case WM_IME_KEYUP:
1778       case WM_IME_KEYDOWN:
1779       case WM_IME_REQUEST:
1780           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1781           break;
1782       case WM_CHAR:
1783           mr = WmChar(static_cast<UINT>(wParam),
1784                       LOWORD(lParam), HIWORD(lParam), FALSE);
1785           break;
1786       case WM_SYSCHAR:
1787           mr = WmChar(static_cast<UINT>(wParam),
1788                       LOWORD(lParam), HIWORD(lParam), TRUE);
1789           break;
1790       case WM_IME_CHAR:
1791           mr = WmIMEChar(static_cast<UINT>(wParam),
1792                          LOWORD(lParam), HIWORD(lParam), FALSE);
1793           break;
1794 
1795       case WM_INPUTLANGCHANGEREQUEST: {
1796           DTRACE_PRINTLN4("WM_INPUTLANGCHANGEREQUEST: hwnd = 0x%X (%s);"//
1797                           "0x%08X -> 0x%08X",
1798                           GetHWnd(), GetClassName(),
1799                           (UINT_PTR)GetKeyboardLayout(), (UINT_PTR)lParam);
1800           // 4267428: make sure keyboard layout is turned undead.
1801           static BYTE keyboardState[AwtToolkit::KB_STATE_SIZE];
1802           AwtToolkit::GetKeyboardState(keyboardState);
1803           WORD ignored;
1804           ::ToAsciiEx(VK_SPACE, ::MapVirtualKey(VK_SPACE, 0),
1805                       keyboardState, &ignored, 0, GetKeyboardLayout());
1806 
1807           // Set this flag to block ActivateKeyboardLayout from
1808           // WInputMethod.activate()
1809           g_bUserHasChangedInputLang = TRUE;
1810           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1811           break;
1812       }
1813       case WM_INPUTLANGCHANGE:
1814           DTRACE_PRINTLN3("WM_INPUTLANGCHANGE: hwnd = 0x%X (%s);"//
1815                           "new = 0x%08X",
1816                           GetHWnd(), GetClassName(), (UINT)lParam);
1817           mr = WmInputLangChange(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam));
1818           g_bUserHasChangedInputLang = TRUE;
1819           CallProxyDefWindowProc(message, wParam, lParam, retValue, mr);
1820           // should return non-zero if we process this message
1821           retValue = 1;
1822           break;
1823 
1824       case WM_AWT_FORWARD_CHAR:
1825           mr = WmForwardChar(LOWORD(wParam), lParam, HIWORD(wParam));
1826           break;
1827 
1828       case WM_AWT_FORWARD_BYTE:
1829           mr = HandleEvent( (MSG *) lParam, (BOOL) wParam);
1830           break;
1831 
1832       case WM_PASTE:
1833           mr = WmPaste();
1834           break;
1835       case WM_TIMER:
1836           mr = WmTimer(wParam);
1837           break;
1838 
1839       case WM_COMMAND:
1840           mr = WmCommand(LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
1841           break;
1842       case WM_COMPAREITEM:
1843           mr = WmCompareItem(static_cast<UINT>(wParam),
1844                              *(COMPAREITEMSTRUCT*)lParam, retValue);
1845           break;
1846       case WM_DELETEITEM:
1847           mr = WmDeleteItem(static_cast<UINT>(wParam),
1848                             *(DELETEITEMSTRUCT*)lParam);
1849           break;
1850       case WM_DRAWITEM:
1851           mr = WmDrawItem(static_cast<UINT>(wParam),
1852                           *(DRAWITEMSTRUCT*)lParam);
1853           break;
1854       case WM_MEASUREITEM:
1855           mr = WmMeasureItem(static_cast<UINT>(wParam),
1856                              *(MEASUREITEMSTRUCT*)lParam);
1857           break;
1858 
1859       case WM_AWT_HANDLE_EVENT:
1860           mr = HandleEvent( (MSG *) lParam, (BOOL) wParam);
1861           break;
1862 
1863       case WM_PRINT:
1864           mr = WmPrint((HDC)wParam, lParam);
1865           break;
1866       case WM_PRINTCLIENT:
1867           mr = WmPrintClient((HDC)wParam, lParam);
1868           break;
1869 
1870       case WM_NCCALCSIZE:
1871           mr = WmNcCalcSize((BOOL)wParam, (LPNCCALCSIZE_PARAMS)lParam,
1872                             retValue);
1873           break;
1874       case WM_NCPAINT:
1875           mr = WmNcPaint((HRGN)wParam);
1876           break;
1877       case WM_NCHITTEST:
1878           mr = WmNcHitTest(LOWORD(lParam), HIWORD(lParam), retValue);
1879           break;
1880 
1881       case WM_AWT_RESHAPE_COMPONENT: {
1882           RECT* r = (RECT*)lParam;
1883           WPARAM checkEmbedded = wParam;
1884           if (checkEmbedded == CHECK_EMBEDDED && IsEmbeddedFrame()) {
1885               ::OffsetRect(r, -r->left, -r->top);
1886           }
1887           Reshape(r->left, r->top, r->right - r->left, r->bottom - r->top);
1888           delete r;
1889           mr = mrConsume;
1890           break;
1891       }
1892 
1893       case WM_AWT_SETALWAYSONTOP: {
1894         AwtWindow* w = (AwtWindow*)lParam;
1895         BOOL value = (BOOL)wParam;
1896         UINT flags = SWP_NOMOVE | SWP_NOSIZE;
1897         // transient windows shouldn't change the owner window's position in the z-order
1898         if (w->IsRetainingHierarchyZOrder()) {
1899             flags |= SWP_NOOWNERZORDER;
1900         }
1901         ::SetWindowPos(w->GetHWnd(), (value != 0 ? HWND_TOPMOST : HWND_NOTOPMOST),
1902                        0,0,0,0, flags);
1903         break;
1904       }
1905 
1906       case WM_AWT_BEGIN_VALIDATE:
1907           BeginValidate();
1908           mr = mrConsume;
1909           break;
1910       case WM_AWT_END_VALIDATE:
1911           EndValidate();
1912           mr = mrConsume;
1913           break;
1914 
1915       case WM_PALETTEISCHANGING:
1916           mr = WmPaletteIsChanging((HWND)wParam);
1917           mr = mrDoDefault;
1918           break;
1919       case WM_QUERYNEWPALETTE:
1920           mr = WmQueryNewPalette(retValue);
1921           break;
1922       case WM_PALETTECHANGED:
1923           mr = WmPaletteChanged((HWND)wParam);
1924           break;
1925       case WM_STYLECHANGED:
1926           mr = WmStyleChanged(static_cast<int>(wParam), (LPSTYLESTRUCT)lParam);
1927           break;
1928       case WM_SETTINGCHANGE:
1929           CheckFontSmoothingSettings(NULL);
1930           mr = WmSettingChange(static_cast<UINT>(wParam), (LPCTSTR)lParam);
1931           break;
1932       case WM_CONTEXTMENU:
1933           mr = WmContextMenu((HWND)wParam,
1934                              GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
1935           break;
1936 
1937           /*
1938            * These messages are used to route Win32 calls to the
1939            * creating thread, since these calls fail unless executed
1940            * there.
1941            */
1942       case WM_AWT_COMPONENT_SHOW:
1943           Show();
1944           mr = mrConsume;
1945           break;
1946       case WM_AWT_COMPONENT_HIDE:
1947           Hide();
1948           mr = mrConsume;
1949           break;
1950 
1951       case WM_AWT_COMPONENT_SETFOCUS:
1952           if ((BOOL)wParam) {
1953               retValue = SynthesizeWmSetFocus(GetHWnd(), NULL);
1954           } else {
1955               retValue = SynthesizeWmKillFocus(GetHWnd(), NULL);
1956           }
1957           mr = mrConsume;
1958           break;
1959       case WM_AWT_WINDOW_SETACTIVE:
1960           retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam);
1961           mr = mrConsume;
1962           break;
1963 
1964       case WM_AWT_SET_SCROLL_INFO: {
1965           SCROLLINFO *si = (SCROLLINFO *) lParam;
1966           ::SetScrollInfo(GetHWnd(), (int) wParam, si, TRUE);
1967           delete si;
1968           mr = mrConsume;
1969           break;
1970       }
1971       case WM_AWT_CREATE_PRINTED_PIXELS: {
1972           CreatePrintedPixelsStruct* cpps = (CreatePrintedPixelsStruct*)wParam;
1973           SIZE loc = { cpps->srcx, cpps->srcy };
1974           SIZE size = { cpps->srcw, cpps->srch };
1975           retValue = (LRESULT)CreatePrintedPixels(loc, size, cpps->alpha);
1976           mr = mrConsume;
1977           break;
1978       }
1979       case WM_UNDOCUMENTED_CLICKMENUBAR:
1980       {
1981           if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
1982               mr = mrConsume;
1983           }
1984       }
1985     }
1986 
1987     /*
1988      * If not a specific Consume, it was a specific DoDefault, or a
1989      * PassAlong (since the default is the next in chain), then call the
1990      * default proc.
1991      */
1992     if (mr != mrConsume) {
1993         retValue = DefWindowProc(message, wParam, lParam);
1994     }
1995 
1996     return retValue;
1997 }
1998 /*
1999  * Call this instance's default window proc, or if none set, call the stock
2000  * Window's one.
2001  */
DefWindowProc(UINT msg,WPARAM wParam,LPARAM lParam)2002 LRESULT AwtComponent::DefWindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
2003 {
2004     return ComCtl32Util::GetInstance().DefWindowProc(m_DefWindowProc, GetHWnd(), msg, wParam, lParam);
2005 }
2006 
2007 /*
2008  * This message should only be received when a window is destroyed by
2009  * Windows, and not Java.  Window termination has been reworked so
2010  * this method should never be called during termination.
2011  */
WmDestroy()2012 MsgRouting AwtComponent::WmDestroy()
2013 {
2014     return mrConsume;
2015 }
2016 
2017 /*
2018  * This message should only be received when a window is destroyed by
2019  * Windows, and not Java. It is sent only after child windows were destroyed.
2020  */
WmNcDestroy()2021 MsgRouting AwtComponent::WmNcDestroy()
2022 {
2023     if (m_peerObject != NULL) { // is not being terminating
2024         // Stay in this handler until AwtComponent::Dispose is called.
2025         m_bPauseDestroy = TRUE;
2026 
2027         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2028         // Post invocation event for WObjectPeer.dispose to EDT
2029         env->CallVoidMethod(m_peerObject, AwtComponent::disposeLaterMID);
2030         // Wait until AwtComponent::Dispose is called
2031         AwtToolkit::GetInstance().PumpToDestroy(this);
2032     }
2033 
2034     return mrConsume;
2035 }
2036 
WmGetMinMaxInfo(LPMINMAXINFO lpmmi)2037 MsgRouting AwtComponent::WmGetMinMaxInfo(LPMINMAXINFO lpmmi)
2038 {
2039     return mrDoDefault;
2040 }
2041 
WmMove(int x,int y)2042 MsgRouting AwtComponent::WmMove(int x, int y)
2043 {
2044     SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED)
2045         | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED));
2046     return mrDoDefault;
2047 }
2048 
WmSize(UINT type,int w,int h)2049 MsgRouting AwtComponent::WmSize(UINT type, int w, int h)
2050 {
2051     SetDrawState(GetDrawState() | static_cast<jint>(JAWT_LOCK_BOUNDS_CHANGED)
2052         | static_cast<jint>(JAWT_LOCK_CLIP_CHANGED));
2053     return mrDoDefault;
2054 }
2055 
WmSizing()2056 MsgRouting AwtComponent::WmSizing()
2057 {
2058     return mrDoDefault;
2059 }
2060 
WmSysCommand(UINT uCmdType,int xPos,int yPos)2061 MsgRouting AwtComponent::WmSysCommand(UINT uCmdType, int xPos, int yPos)
2062 {
2063     return mrDoDefault;
2064 }
2065 
WmExitSizeMove()2066 MsgRouting AwtComponent::WmExitSizeMove()
2067 {
2068     return mrDoDefault;
2069 }
2070 
WmEnterMenuLoop(BOOL isTrackPopupMenu)2071 MsgRouting AwtComponent::WmEnterMenuLoop(BOOL isTrackPopupMenu)
2072 {
2073     return mrDoDefault;
2074 }
2075 
WmExitMenuLoop(BOOL isTrackPopupMenu)2076 MsgRouting AwtComponent::WmExitMenuLoop(BOOL isTrackPopupMenu)
2077 {
2078     return mrDoDefault;
2079 }
2080 
WmShowWindow(BOOL show,UINT status)2081 MsgRouting AwtComponent::WmShowWindow(BOOL show, UINT status)
2082 {
2083     return mrDoDefault;
2084 }
2085 
WmSetFocus(HWND hWndLostFocus)2086 MsgRouting AwtComponent::WmSetFocus(HWND hWndLostFocus)
2087 {
2088     m_wheelRotationAmount = 0;
2089     return mrDoDefault;
2090 }
2091 
WmKillFocus(HWND hWndGotFocus)2092 MsgRouting AwtComponent::WmKillFocus(HWND hWndGotFocus)
2093 {
2094     m_wheelRotationAmount = 0;
2095     return mrDoDefault;
2096 }
2097 
WmCtlColor(HDC hDC,HWND hCtrl,UINT ctlColor,HBRUSH & retBrush)2098 MsgRouting AwtComponent::WmCtlColor(HDC hDC, HWND hCtrl,
2099                                     UINT ctlColor, HBRUSH& retBrush)
2100 {
2101     AwtComponent* child = AwtComponent::GetComponent(hCtrl);
2102     if (child) {
2103         ::SetBkColor(hDC, child->GetBackgroundColor());
2104         ::SetTextColor(hDC, child->GetColor());
2105         retBrush = child->GetBackgroundBrush();
2106         return mrConsume;
2107     }
2108     return mrDoDefault;
2109 /*
2110     switch (ctlColor) {
2111         case CTLCOLOR_MSGBOX:
2112         case CTLCOLOR_EDIT:
2113         case CTLCOLOR_LISTBOX:
2114         case CTLCOLOR_BTN:
2115         case CTLCOLOR_DLG:
2116         case CTLCOLOR_SCROLLBAR:
2117         case CTLCOLOR_STATIC:
2118     }
2119 */
2120 }
2121 
WmHScroll(UINT scrollCode,UINT pos,HWND hScrollbar)2122 MsgRouting AwtComponent::WmHScroll(UINT scrollCode, UINT pos,
2123                                    HWND hScrollbar) {
2124     if (hScrollbar && hScrollbar != GetHWnd()) {
2125         /* the last test should never happen */
2126         AwtComponent* sb = GetComponent(hScrollbar);
2127         if (sb) {
2128             sb->WmHScroll(scrollCode, pos, hScrollbar);
2129         }
2130     }
2131     return mrDoDefault;
2132 }
2133 
WmVScroll(UINT scrollCode,UINT pos,HWND hScrollbar)2134 MsgRouting AwtComponent::WmVScroll(UINT scrollCode, UINT pos, HWND hScrollbar)
2135 {
2136     if (hScrollbar && hScrollbar != GetHWnd()) {
2137         /* the last test should never happen */
2138         AwtComponent* sb = GetComponent(hScrollbar);
2139         if (sb) {
2140             sb->WmVScroll(scrollCode, pos, hScrollbar);
2141         }
2142     }
2143     return mrDoDefault;
2144 }
2145 
2146 namespace TimeHelper {
2147     // Sometimes the message belongs to another event queue and
2148     // GetMessageTime() may return wrong non-zero value (the case is
2149     // the TrayIcon peer). Using TimeHelper::windowsToUTC(::GetTickCount())
2150     // could help there.
getMessageTimeWindows()2151     static DWORD getMessageTimeWindows(){
2152         DWORD time = ::GetMessageTime();
2153         // The following 'if' seems to be a unneeded hack.
2154         // Consider removing it.
2155         if (time == 0) {
2156             time = ::GetTickCount();
2157         }
2158         return time;
2159     }
2160 
getMessageTimeUTC()2161     jlong getMessageTimeUTC() {
2162         return ::JVM_CurrentTimeMillis(NULL, 0);
2163     }
2164 } //TimeHelper
2165 
WmPaint(HDC)2166 MsgRouting AwtComponent::WmPaint(HDC)
2167 {
2168     /* Get the rectangle that covers all update regions, if any exist. */
2169     RECT r;
2170     if (::GetUpdateRect(GetHWnd(), &r, FALSE)) {
2171         if ((r.right-r.left) > 0 && (r.bottom-r.top) > 0 &&
2172             m_peerObject != NULL && m_callbacksEnabled) {
2173             /*
2174              * Always call handlePaint, because the underlying control
2175              * will have painted itself (the "background") before any
2176              * paint method is called.
2177              */
2178             DoCallback("handlePaint", "(IIII)V",
2179                        r.left, r.top, r.right-r.left, r.bottom-r.top);
2180         }
2181     }
2182     return mrDoDefault;
2183 }
2184 
PaintUpdateRgn(const RECT * insets)2185 void AwtComponent::PaintUpdateRgn(const RECT *insets)
2186 {
2187     // Fix 4530093: Don't Validate if can't actually paint
2188     if (m_peerObject == NULL || !m_callbacksEnabled) {
2189 
2190         // Fix 4745222: If we don't ValidateRgn,  windows will keep sending
2191         // WM_PAINT messages until we do. This causes java to go into
2192         // a tight loop that increases CPU to 100% and starves main
2193         // thread which needs to complete initialization, but cant.
2194         ::ValidateRgn(GetHWnd(), NULL);
2195 
2196         return;
2197     }
2198 
2199     HRGN rgn = ::CreateRectRgn(0,0,1,1);
2200     int updated = ::GetUpdateRgn(GetHWnd(), rgn, FALSE);
2201     /*
2202      * Now remove all update regions from this window -- do it
2203      * here instead of after the Java upcall, in case any new
2204      * updating is requested.
2205      */
2206     ::ValidateRgn(GetHWnd(), NULL);
2207 
2208     if (updated == COMPLEXREGION || updated == SIMPLEREGION) {
2209         if (insets != NULL) {
2210             ::OffsetRgn(rgn, insets->left, insets->top);
2211         }
2212         DWORD size = ::GetRegionData(rgn, 0, NULL);
2213         if (size == 0) {
2214             ::DeleteObject((HGDIOBJ)rgn);
2215             return;
2216         }
2217         char* buffer = new char[size]; // safe because sizeof(char)==1
2218         memset(buffer, 0, size);
2219         LPRGNDATA rgndata = (LPRGNDATA)buffer;
2220         rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
2221         rgndata->rdh.iType = RDH_RECTANGLES;
2222         int retCode = ::GetRegionData(rgn, size, rgndata);
2223         VERIFY(retCode);
2224         if (retCode == 0) {
2225             delete [] buffer;
2226             ::DeleteObject((HGDIOBJ)rgn);
2227             return;
2228         }
2229         /*
2230          * Updating rects are divided into mostly vertical and mostly horizontal
2231          * Each group is united together and if not empty painted separately
2232          */
2233         RECT* r = (RECT*)(buffer + rgndata->rdh.dwSize);
2234         RECT* un[2] = {0, 0};
2235     DWORD i;
2236     for (i = 0; i < rgndata->rdh.nCount; i++, r++) {
2237             int width = r->right-r->left;
2238             int height = r->bottom-r->top;
2239             if (width > 0 && height > 0) {
2240                 int toAdd = (width > height) ? 0: 1;
2241                 if (un[toAdd] != 0) {
2242                     ::UnionRect(un[toAdd], un[toAdd], r);
2243                 } else {
2244                     un[toAdd] = r;
2245                 }
2246             }
2247         }
2248         for(i = 0; i < 2; i++) {
2249             if (un[i] != 0) {
2250                 DoCallback("handleExpose", "(IIII)V", un[i]->left, un[i]->top,
2251                     un[i]->right-un[i]->left, un[i]->bottom-un[i]->top);
2252             }
2253         }
2254         delete [] buffer;
2255     }
2256     ::DeleteObject((HGDIOBJ)rgn);
2257 }
2258 
WmMouseEnter(UINT flags,int x,int y)2259 MsgRouting AwtComponent::WmMouseEnter(UINT flags, int x, int y)
2260 {
2261     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_ENTERED,
2262                    TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(), 0, JNI_FALSE);
2263     if ((flags & ALL_MK_BUTTONS) == 0) {
2264         AwtCursor::UpdateCursor(this);
2265     }
2266     sm_cursorOn = GetHWnd();
2267     return mrConsume;   /* Don't pass our synthetic event on! */
2268 }
2269 
2270 MSG*
CreateMessage(UINT message,WPARAM wParam,LPARAM lParam,int x=0,int y=0)2271 AwtComponent::CreateMessage(UINT message, WPARAM wParam, LPARAM lParam,
2272                             int x = 0, int y = 0)
2273 {
2274     MSG* pMsg = new MSG;
2275     InitMessage(pMsg, message, wParam, lParam, x, y);
2276     return pMsg;
2277 }
2278 
2279 
2280 jint
GetDrawState(HWND hwnd)2281 AwtComponent::GetDrawState(HWND hwnd) {
2282     return (jint)(INT_PTR)(::GetProp(hwnd, DrawingStateProp));
2283 }
2284 
2285 void
SetDrawState(HWND hwnd,jint state)2286 AwtComponent::SetDrawState(HWND hwnd, jint state) {
2287     ::SetProp(hwnd, DrawingStateProp, (HANDLE)(INT_PTR)state);
2288 }
2289 
2290 void
InitMessage(MSG * msg,UINT message,WPARAM wParam,LPARAM lParam,int x=0,int y=0)2291 AwtComponent::InitMessage(MSG* msg, UINT message, WPARAM wParam, LPARAM lParam,
2292                             int x = 0, int y = 0)
2293 {
2294     msg->message = message;
2295     msg->wParam = wParam;
2296     msg->lParam = lParam;
2297     msg->time = TimeHelper::getMessageTimeWindows();
2298     msg->pt.x = x;
2299     msg->pt.y = y;
2300 }
2301 
WmNcMouseDown(WPARAM hitTest,int x,int y,int button)2302 MsgRouting AwtComponent::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
2303     return mrDoDefault;
2304 }
WmNcMouseUp(WPARAM hitTest,int x,int y,int button)2305 MsgRouting AwtComponent::WmNcMouseUp(WPARAM hitTest, int x, int y, int button) {
2306     return mrDoDefault;
2307 }
2308 
WmWindowPosChanging(LPARAM windowPos)2309 MsgRouting AwtComponent::WmWindowPosChanging(LPARAM windowPos) {
2310     return mrDoDefault;
2311 }
WmWindowPosChanged(LPARAM windowPos)2312 MsgRouting AwtComponent::WmWindowPosChanged(LPARAM windowPos) {
2313     return mrDoDefault;
2314 }
2315 
WmTouch(WPARAM wParam,LPARAM lParam)2316 void AwtComponent::WmTouch(WPARAM wParam, LPARAM lParam) {
2317     AwtToolkit& tk = AwtToolkit::GetInstance();
2318     if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) {
2319         return;
2320     }
2321 
2322     UINT inputsCount = LOWORD(wParam);
2323     TOUCHINPUT* pInputs = new TOUCHINPUT[inputsCount];
2324     if (pInputs != NULL) {
2325         if (tk.TIGetTouchInputInfo((HTOUCHINPUT)lParam, inputsCount, pInputs,
2326                 sizeof(TOUCHINPUT)) != 0) {
2327             for (UINT i = 0; i < inputsCount; i++) {
2328                 TOUCHINPUT ti = pInputs[i];
2329                 if (ti.dwFlags & TOUCHEVENTF_PRIMARY) {
2330                     if (ti.dwFlags & TOUCHEVENTF_DOWN) {
2331                         m_touchDownPoint.x = ti.x / 100;
2332                         m_touchDownPoint.y = ti.y / 100;
2333                         ::ScreenToClient(GetHWnd(), &m_touchDownPoint);
2334                         m_touchDownOccurred = TRUE;
2335                     } else if (ti.dwFlags & TOUCHEVENTF_UP) {
2336                         m_touchUpPoint.x = ti.x / 100;
2337                         m_touchUpPoint.y = ti.y / 100;
2338                         ::ScreenToClient(GetHWnd(), &m_touchUpPoint);
2339                         m_touchUpOccurred = TRUE;
2340                     }
2341                 }
2342             }
2343         }
2344         delete[] pInputs;
2345     }
2346 }
2347 
2348 /* Double-click variables. */
2349 static jlong multiClickTime = ::GetDoubleClickTime();
2350 static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK);
2351 static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK);
2352 static AwtComponent* lastClickWnd = NULL;
2353 static jlong lastTime = 0;
2354 static int lastClickX = 0;
2355 static int lastClickY = 0;
2356 static int lastButton = 0;
2357 static int clickCount = 0;
2358 
2359 // A static method that makes the clickCount available in the derived classes
2360 // overriding WmMouseDown().
GetClickCount()2361 int AwtComponent::GetClickCount()
2362 {
2363     return clickCount;
2364 }
2365 
WmMouseDown(UINT flags,int x,int y,int button)2366 MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
2367 {
2368     jlong now = TimeHelper::getMessageTimeUTC();
2369 
2370     if (lastClickWnd == this &&
2371         lastButton == button &&
2372         (now - lastTime) <= multiClickTime &&
2373         abs(x - lastClickX) <= multiClickMaxX &&
2374         abs(y - lastClickY) <= multiClickMaxY)
2375     {
2376         clickCount++;
2377     } else {
2378         clickCount = 1;
2379         lastClickWnd = this;
2380         lastButton = button;
2381         lastClickX = x;
2382         lastClickY = y;
2383     }
2384     /*
2385      *Set appropriate bit of the mask on WM_MOUSE_DOWN message.
2386      */
2387     m_mouseButtonClickAllowed |= GetButtonMK(button);
2388     lastTime = now;
2389 
2390     BOOL causedByTouchEvent = FALSE;
2391     if (m_touchDownOccurred &&
2392         (abs(m_touchDownPoint.x - x) <= TOUCH_MOUSE_COORDS_DELTA) &&
2393         (abs(m_touchDownPoint.y - y) <= TOUCH_MOUSE_COORDS_DELTA)) {
2394         causedByTouchEvent = TRUE;
2395         m_touchDownOccurred = FALSE;
2396     }
2397 
2398     MSG msg;
2399     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2400 
2401     AwtWindow *toplevel = GetContainer();
2402     if (toplevel && !toplevel->IsSimpleWindow()) {
2403         /*
2404          * The frame should be focused by click in case it is
2405          * the active window but not the focused window. See 6886678.
2406          */
2407         if (toplevel->GetHWnd() == ::GetActiveWindow() &&
2408             toplevel->GetHWnd() != AwtComponent::GetFocusedWindow())
2409         {
2410             toplevel->AwtSetActiveWindow();
2411         }
2412     }
2413 
2414     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
2415                    GetJavaModifiers(), clickCount, JNI_FALSE,
2416                    GetButton(button), &msg, causedByTouchEvent);
2417     /*
2418      * NOTE: this call is intentionally placed after all other code,
2419      * since AwtComponent::WmMouseDown() assumes that the cached id of the
2420      * latest retrieved message (see lastMessage in awt_Component.cpp)
2421      * matches the mouse message being processed.
2422      * SetCapture() sends WM_CAPTURECHANGED and breaks that
2423      * assumption.
2424      */
2425     SetDragCapture(flags);
2426 
2427     AwtWindow * owner = (AwtWindow*)GetComponent(GetTopLevelParentForWindow(GetHWnd()));
2428     if (AwtWindow::GetGrabbedWindow() != NULL && owner != NULL) {
2429         if (!AwtWindow::GetGrabbedWindow()->IsOneOfOwnersOf(owner)) {
2430             AwtWindow::GetGrabbedWindow()->Ungrab();
2431         }
2432     }
2433     return mrConsume;
2434 }
2435 
WmMouseUp(UINT flags,int x,int y,int button)2436 MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button)
2437 {
2438     BOOL causedByTouchEvent = FALSE;
2439     if (m_touchUpOccurred &&
2440         (abs(m_touchUpPoint.x - x) <= TOUCH_MOUSE_COORDS_DELTA) &&
2441         (abs(m_touchUpPoint.y - y) <= TOUCH_MOUSE_COORDS_DELTA)) {
2442         causedByTouchEvent = TRUE;
2443         m_touchUpOccurred = FALSE;
2444     }
2445 
2446     MSG msg;
2447     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2448 
2449     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::getMessageTimeUTC(),
2450                    x, y, GetJavaModifiers(), clickCount,
2451                    (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
2452                     TRUE : FALSE), GetButton(button), &msg, causedByTouchEvent);
2453     /*
2454      * If no movement, then report a click following the button release.
2455      * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN,
2456      * spurous MOUSE_CLICK is about to happen. See 6430553.
2457      */
2458     if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed
2459         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
2460                        TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(),
2461                        clickCount, JNI_FALSE, GetButton(button));
2462     }
2463     // Exclude button from allowed to generate CLICK messages
2464     m_mouseButtonClickAllowed &= ~GetButtonMK(button);
2465 
2466     if ((flags & ALL_MK_BUTTONS) == 0) {
2467         // only update if all buttons have been released
2468         AwtCursor::UpdateCursor(this);
2469     }
2470     /*
2471      * NOTE: this call is intentionally placed after all other code,
2472      * since AwtComponent::WmMouseUp() assumes that the cached id of the
2473      * latest retrieved message (see lastMessage in awt_Component.cpp)
2474      * matches the mouse message being processed.
2475      * ReleaseCapture() sends WM_CAPTURECHANGED and breaks that
2476      * assumption.
2477      */
2478     ReleaseDragCapture(flags);
2479 
2480     return mrConsume;
2481 }
2482 
WmMouseMove(UINT flags,int x,int y)2483 MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y)
2484 {
2485     static AwtComponent* lastComp = NULL;
2486     static int lastX = 0;
2487     static int lastY = 0;
2488 
2489     /*
2490      * Only report mouse move and drag events if a move or drag
2491      * actually happened -- Windows sends a WM_MOUSEMOVE in case the
2492      * app wants to modify the cursor.
2493      */
2494     if (lastComp != this || x != lastX || y != lastY) {
2495         lastComp = this;
2496         lastX = x;
2497         lastY = y;
2498         BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled();
2499         if (((flags & (ALL_MK_BUTTONS)) != 0) ||
2500             (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0))
2501 //        if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) ||
2502 //            ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) ))
2503         {
2504             // 6404008 : if Dragged event fired we shouldn't fire
2505             // Clicked event: m_firstDragSent set to TRUE.
2506             // This is a partial backout of 5039416 fix.
2507             MSG msg;
2508             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2509             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, TimeHelper::getMessageTimeUTC(), x, y,
2510                            GetJavaModifiers(), 0, JNI_FALSE,
2511                            java_awt_event_MouseEvent_NOBUTTON, &msg);
2512             //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence
2513             m_mouseButtonClickAllowed = 0;
2514         } else {
2515             MSG msg;
2516             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
2517             SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::getMessageTimeUTC(), x, y,
2518                            GetJavaModifiers(), 0, JNI_FALSE,
2519                            java_awt_event_MouseEvent_NOBUTTON, &msg);
2520         }
2521     }
2522 
2523     return mrConsume;
2524 }
2525 
WmMouseExit(UINT flags,int x,int y)2526 MsgRouting AwtComponent::WmMouseExit(UINT flags, int x, int y)
2527 {
2528     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, TimeHelper::getMessageTimeUTC(), x,
2529                    y, GetJavaModifiers(), 0, JNI_FALSE);
2530     sm_cursorOn = NULL;
2531     return mrConsume;   /* Don't pass our synthetic event on! */
2532 }
2533 
WmMouseWheel(UINT flags,int x,int y,int wheelRotation)2534 MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y,
2535                                       int wheelRotation)
2536 {
2537     // convert coordinates to be Component-relative, not screen relative
2538     // for wheeling when outside the window, this works similar to
2539     // coordinates during a drag
2540     POINT eventPt;
2541     eventPt.x = x;
2542     eventPt.y = y;
2543     DTRACE_PRINT2("  original coords: %i,%i\n", x, y);
2544     ::ScreenToClient(GetHWnd(), &eventPt);
2545     DTRACE_PRINT2("  new coords: %i,%i\n\n", eventPt.x, eventPt.y);
2546 
2547     // set some defaults
2548     jint scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
2549     jint scrollLines = 3;
2550 
2551     BOOL result;
2552     UINT platformLines;
2553 
2554     m_wheelRotationAmount += wheelRotation;
2555 
2556     // AWT interprets wheel rotation differently than win32, so we need to
2557     // decode wheel amount.
2558     jint roundedWheelRotation = m_wheelRotationAmount / (-1 * WHEEL_DELTA);
2559     jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA);
2560 
2561     MSG msg;
2562     result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
2563                                     &platformLines, 0);
2564     InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation),
2565                 MAKELPARAM(x, y));
2566 
2567     if (result) {
2568         if (platformLines == WHEEL_PAGESCROLL) {
2569             scrollType = java_awt_event_MouseWheelEvent_WHEEL_BLOCK_SCROLL;
2570             scrollLines = 1;
2571         }
2572         else {
2573             scrollType = java_awt_event_MouseWheelEvent_WHEEL_UNIT_SCROLL;
2574             scrollLines = platformLines;
2575         }
2576     }
2577 
2578     DTRACE_PRINTLN("calling SendMouseWheelEvent");
2579 
2580     SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, TimeHelper::getMessageTimeUTC(),
2581                         eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType,
2582                         scrollLines, roundedWheelRotation, preciseWheelRotation, &msg);
2583 
2584     m_wheelRotationAmount %= WHEEL_DELTA;
2585     // this message could be propagated up to the parent chain
2586     // by the mouse message post processors
2587     return mrConsume;
2588 }
2589 
GetKeyLocation(UINT wkey,UINT flags)2590 jint AwtComponent::GetKeyLocation(UINT wkey, UINT flags) {
2591     // Rector+Newcomer page 413
2592     // The extended keys are the Alt and Control on the right of
2593     // the space bar, the non-Numpad arrow keys, the non-Numpad
2594     // Insert, PageUp, etc. keys, and the Numpad Divide and Enter keys.
2595     // Note that neither Shift key is extended.
2596     // Although not listed in Rector+Newcomer, both Windows keys
2597     // (91 and 92) are extended keys, the Context Menu key
2598     // (property key or application key - 93) is extended,
2599     // and so is the NumLock key.
2600 
2601     // wkey is the wParam, flags is the HIWORD of the lParam
2602 
2603     // "Extended" bit is 24th in lParam, so it's 8th in flags = HIWORD(lParam)
2604     BOOL extended = ((1<<8) & flags);
2605 
2606     if (IsNumPadKey(wkey, extended)) {
2607         return java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD;
2608     }
2609 
2610     switch (wkey) {
2611       case VK_SHIFT:
2612         return AwtComponent::GetShiftKeyLocation(wkey, flags);
2613       case VK_CONTROL: // fall through
2614       case VK_MENU:
2615         if (extended) {
2616             return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2617         } else {
2618             return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2619         }
2620       case VK_LWIN:
2621         return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2622       case VK_RWIN:
2623         return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2624       default:
2625         break;
2626     }
2627 
2628     // REMIND: if we add keycodes for the windows keys, we'll have to
2629     // include left/right discrimination code for them.
2630 
2631     return java_awt_event_KeyEvent_KEY_LOCATION_STANDARD;
2632 }
2633 
GetShiftKeyLocation(UINT vkey,UINT flags)2634 jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags)
2635 {
2636     // init scancodes to safe values
2637     UINT leftShiftScancode = 0;
2638     UINT rightShiftScancode = 0;
2639 
2640     // First 8 bits of flags is the scancode
2641     UINT keyScanCode = flags & 0xFF;
2642 
2643     DTRACE_PRINTLN3(
2644       "AwtComponent::GetShiftKeyLocation  vkey = %d = 0x%x  scan = %d",
2645       vkey, vkey, keyScanCode);
2646 
2647     leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0);
2648     rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0);
2649 
2650     if (keyScanCode == leftShiftScancode) {
2651         return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2652     }
2653     if (keyScanCode == rightShiftScancode) {
2654         return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT;
2655     }
2656 
2657     DASSERT(false);
2658     // Note: the above should not fail on NT (or 2000)
2659 
2660     // default value
2661     return java_awt_event_KeyEvent_KEY_LOCATION_LEFT;
2662 }
2663 
2664 /* Returns Java extended InputEvent modifieres.
2665  * Since ::GetKeyState returns current state and Java modifiers represent
2666  * state before event, modifier on changed key are inverted.
2667  */
2668 jint
GetJavaModifiers()2669 AwtComponent::GetJavaModifiers()
2670 {
2671     jint modifiers = 0;
2672 
2673     if (HIBYTE(::GetKeyState(VK_CONTROL)) != 0) {
2674         modifiers |= java_awt_event_InputEvent_CTRL_DOWN_MASK;
2675     }
2676     if (HIBYTE(::GetKeyState(VK_SHIFT)) != 0) {
2677         modifiers |= java_awt_event_InputEvent_SHIFT_DOWN_MASK;
2678     }
2679     if (HIBYTE(::GetKeyState(VK_MENU)) != 0) {
2680         modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK;
2681     }
2682     if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) {
2683        modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK;
2684     }
2685     if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) {
2686         modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK;
2687     }
2688     if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) {
2689         modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK;
2690     }
2691 
2692     if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) {
2693         modifiers |= masks[3];
2694     }
2695     if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) {
2696         modifiers |= masks[4];
2697     }
2698     return modifiers;
2699 }
2700 
2701 jint
GetButton(int mouseButton)2702 AwtComponent::GetButton(int mouseButton)
2703 {
2704     /* Mouse buttons are already set correctly for left/right handedness */
2705     switch(mouseButton) {
2706     case LEFT_BUTTON:
2707         return java_awt_event_MouseEvent_BUTTON1;
2708     case MIDDLE_BUTTON:
2709         return java_awt_event_MouseEvent_BUTTON2;
2710     case RIGHT_BUTTON:
2711         return java_awt_event_MouseEvent_BUTTON3;
2712     case X1_BUTTON: //16 :
2713         //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now
2714         return 4;
2715     case X2_BUTTON: //32
2716         return 5;
2717     }
2718     return java_awt_event_MouseEvent_NOBUTTON;
2719 }
2720 
2721 UINT
GetButtonMK(int mouseButton)2722 AwtComponent::GetButtonMK(int mouseButton)
2723 {
2724     switch(mouseButton) {
2725     case LEFT_BUTTON:
2726         return MK_LBUTTON;
2727     case MIDDLE_BUTTON:
2728         return MK_MBUTTON;
2729     case RIGHT_BUTTON:
2730         return MK_RBUTTON;
2731     case X1_BUTTON:
2732         return MK_XBUTTON1;
2733     case X2_BUTTON:
2734         return MK_XBUTTON2;
2735     }
2736     return 0;
2737 }
2738 
2739 // FIXME: Keyboard related stuff has grown so big and hairy that we
2740 // really need to move it into a class of its own.  And, since
2741 // keyboard is a shared resource, AwtComponent is a bad place for it.
2742 
2743 // These constants are defined in the Japanese version of VC++5.0,
2744 // but not the US version
2745 #ifndef VK_CONVERT
2746 #define VK_KANA           0x15
2747 #define VK_KANJI          0x19
2748 #define VK_CONVERT        0x1C
2749 #define VK_NONCONVERT     0x1D
2750 #endif
2751 
2752 #ifndef VK_XBUTTON1
2753 #define VK_XBUTTON1      0x05
2754 #endif
2755 
2756 #ifndef VK_XBUTTON2
2757 #define VK_XBUTTON2      0x06
2758 #endif
2759 
2760 typedef struct {
2761     UINT javaKey;
2762     UINT windowsKey;
2763 } KeyMapEntry;
2764 
2765 // Static table, arranged more or less spatially.
2766 KeyMapEntry keyMapTable[] = {
2767     // Modifier keys
2768     {java_awt_event_KeyEvent_VK_CAPS_LOCK,        VK_CAPITAL},
2769     {java_awt_event_KeyEvent_VK_SHIFT,            VK_SHIFT},
2770     {java_awt_event_KeyEvent_VK_CONTROL,          VK_CONTROL},
2771     {java_awt_event_KeyEvent_VK_ALT,              VK_MENU},
2772     {java_awt_event_KeyEvent_VK_NUM_LOCK,         VK_NUMLOCK},
2773 
2774     // Miscellaneous Windows keys
2775     {java_awt_event_KeyEvent_VK_WINDOWS,          VK_LWIN},
2776     {java_awt_event_KeyEvent_VK_WINDOWS,          VK_RWIN},
2777     {java_awt_event_KeyEvent_VK_CONTEXT_MENU,     VK_APPS},
2778 
2779     // Alphabet
2780     {java_awt_event_KeyEvent_VK_A,                'A'},
2781     {java_awt_event_KeyEvent_VK_B,                'B'},
2782     {java_awt_event_KeyEvent_VK_C,                'C'},
2783     {java_awt_event_KeyEvent_VK_D,                'D'},
2784     {java_awt_event_KeyEvent_VK_E,                'E'},
2785     {java_awt_event_KeyEvent_VK_F,                'F'},
2786     {java_awt_event_KeyEvent_VK_G,                'G'},
2787     {java_awt_event_KeyEvent_VK_H,                'H'},
2788     {java_awt_event_KeyEvent_VK_I,                'I'},
2789     {java_awt_event_KeyEvent_VK_J,                'J'},
2790     {java_awt_event_KeyEvent_VK_K,                'K'},
2791     {java_awt_event_KeyEvent_VK_L,                'L'},
2792     {java_awt_event_KeyEvent_VK_M,                'M'},
2793     {java_awt_event_KeyEvent_VK_N,                'N'},
2794     {java_awt_event_KeyEvent_VK_O,                'O'},
2795     {java_awt_event_KeyEvent_VK_P,                'P'},
2796     {java_awt_event_KeyEvent_VK_Q,                'Q'},
2797     {java_awt_event_KeyEvent_VK_R,                'R'},
2798     {java_awt_event_KeyEvent_VK_S,                'S'},
2799     {java_awt_event_KeyEvent_VK_T,                'T'},
2800     {java_awt_event_KeyEvent_VK_U,                'U'},
2801     {java_awt_event_KeyEvent_VK_V,                'V'},
2802     {java_awt_event_KeyEvent_VK_W,                'W'},
2803     {java_awt_event_KeyEvent_VK_X,                'X'},
2804     {java_awt_event_KeyEvent_VK_Y,                'Y'},
2805     {java_awt_event_KeyEvent_VK_Z,                'Z'},
2806 
2807     // Standard numeric row
2808     {java_awt_event_KeyEvent_VK_0,                '0'},
2809     {java_awt_event_KeyEvent_VK_1,                '1'},
2810     {java_awt_event_KeyEvent_VK_2,                '2'},
2811     {java_awt_event_KeyEvent_VK_3,                '3'},
2812     {java_awt_event_KeyEvent_VK_4,                '4'},
2813     {java_awt_event_KeyEvent_VK_5,                '5'},
2814     {java_awt_event_KeyEvent_VK_6,                '6'},
2815     {java_awt_event_KeyEvent_VK_7,                '7'},
2816     {java_awt_event_KeyEvent_VK_8,                '8'},
2817     {java_awt_event_KeyEvent_VK_9,                '9'},
2818 
2819     // Misc key from main block
2820     {java_awt_event_KeyEvent_VK_ENTER,            VK_RETURN},
2821     {java_awt_event_KeyEvent_VK_SPACE,            VK_SPACE},
2822     {java_awt_event_KeyEvent_VK_BACK_SPACE,       VK_BACK},
2823     {java_awt_event_KeyEvent_VK_TAB,              VK_TAB},
2824     {java_awt_event_KeyEvent_VK_ESCAPE,           VK_ESCAPE},
2825 
2826     // NumPad with NumLock off & extended block (rectangular)
2827     {java_awt_event_KeyEvent_VK_INSERT,           VK_INSERT},
2828     {java_awt_event_KeyEvent_VK_DELETE,           VK_DELETE},
2829     {java_awt_event_KeyEvent_VK_HOME,             VK_HOME},
2830     {java_awt_event_KeyEvent_VK_END,              VK_END},
2831     {java_awt_event_KeyEvent_VK_PAGE_UP,          VK_PRIOR},
2832     {java_awt_event_KeyEvent_VK_PAGE_DOWN,        VK_NEXT},
2833     {java_awt_event_KeyEvent_VK_CLEAR,            VK_CLEAR}, // NumPad 5
2834 
2835     // NumPad with NumLock off & extended arrows block (triangular)
2836     {java_awt_event_KeyEvent_VK_LEFT,             VK_LEFT},
2837     {java_awt_event_KeyEvent_VK_RIGHT,            VK_RIGHT},
2838     {java_awt_event_KeyEvent_VK_UP,               VK_UP},
2839     {java_awt_event_KeyEvent_VK_DOWN,             VK_DOWN},
2840 
2841     // NumPad with NumLock on: numbers
2842     {java_awt_event_KeyEvent_VK_NUMPAD0,          VK_NUMPAD0},
2843     {java_awt_event_KeyEvent_VK_NUMPAD1,          VK_NUMPAD1},
2844     {java_awt_event_KeyEvent_VK_NUMPAD2,          VK_NUMPAD2},
2845     {java_awt_event_KeyEvent_VK_NUMPAD3,          VK_NUMPAD3},
2846     {java_awt_event_KeyEvent_VK_NUMPAD4,          VK_NUMPAD4},
2847     {java_awt_event_KeyEvent_VK_NUMPAD5,          VK_NUMPAD5},
2848     {java_awt_event_KeyEvent_VK_NUMPAD6,          VK_NUMPAD6},
2849     {java_awt_event_KeyEvent_VK_NUMPAD7,          VK_NUMPAD7},
2850     {java_awt_event_KeyEvent_VK_NUMPAD8,          VK_NUMPAD8},
2851     {java_awt_event_KeyEvent_VK_NUMPAD9,          VK_NUMPAD9},
2852 
2853     // NumPad with NumLock on
2854     {java_awt_event_KeyEvent_VK_MULTIPLY,         VK_MULTIPLY},
2855     {java_awt_event_KeyEvent_VK_ADD,              VK_ADD},
2856     {java_awt_event_KeyEvent_VK_SEPARATOR,        VK_SEPARATOR},
2857     {java_awt_event_KeyEvent_VK_SUBTRACT,         VK_SUBTRACT},
2858     {java_awt_event_KeyEvent_VK_DECIMAL,          VK_DECIMAL},
2859     {java_awt_event_KeyEvent_VK_DIVIDE,           VK_DIVIDE},
2860 
2861     // Functional keys
2862     {java_awt_event_KeyEvent_VK_F1,               VK_F1},
2863     {java_awt_event_KeyEvent_VK_F2,               VK_F2},
2864     {java_awt_event_KeyEvent_VK_F3,               VK_F3},
2865     {java_awt_event_KeyEvent_VK_F4,               VK_F4},
2866     {java_awt_event_KeyEvent_VK_F5,               VK_F5},
2867     {java_awt_event_KeyEvent_VK_F6,               VK_F6},
2868     {java_awt_event_KeyEvent_VK_F7,               VK_F7},
2869     {java_awt_event_KeyEvent_VK_F8,               VK_F8},
2870     {java_awt_event_KeyEvent_VK_F9,               VK_F9},
2871     {java_awt_event_KeyEvent_VK_F10,              VK_F10},
2872     {java_awt_event_KeyEvent_VK_F11,              VK_F11},
2873     {java_awt_event_KeyEvent_VK_F12,              VK_F12},
2874     {java_awt_event_KeyEvent_VK_F13,              VK_F13},
2875     {java_awt_event_KeyEvent_VK_F14,              VK_F14},
2876     {java_awt_event_KeyEvent_VK_F15,              VK_F15},
2877     {java_awt_event_KeyEvent_VK_F16,              VK_F16},
2878     {java_awt_event_KeyEvent_VK_F17,              VK_F17},
2879     {java_awt_event_KeyEvent_VK_F18,              VK_F18},
2880     {java_awt_event_KeyEvent_VK_F19,              VK_F19},
2881     {java_awt_event_KeyEvent_VK_F20,              VK_F20},
2882     {java_awt_event_KeyEvent_VK_F21,              VK_F21},
2883     {java_awt_event_KeyEvent_VK_F22,              VK_F22},
2884     {java_awt_event_KeyEvent_VK_F23,              VK_F23},
2885     {java_awt_event_KeyEvent_VK_F24,              VK_F24},
2886 
2887     {java_awt_event_KeyEvent_VK_PRINTSCREEN,      VK_SNAPSHOT},
2888     {java_awt_event_KeyEvent_VK_SCROLL_LOCK,      VK_SCROLL},
2889     {java_awt_event_KeyEvent_VK_PAUSE,            VK_PAUSE},
2890     {java_awt_event_KeyEvent_VK_CANCEL,           VK_CANCEL},
2891     {java_awt_event_KeyEvent_VK_HELP,             VK_HELP},
2892 
2893     // Japanese
2894     {java_awt_event_KeyEvent_VK_CONVERT,          VK_CONVERT},
2895     {java_awt_event_KeyEvent_VK_NONCONVERT,       VK_NONCONVERT},
2896     {java_awt_event_KeyEvent_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
2897     {java_awt_event_KeyEvent_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC},
2898     {java_awt_event_KeyEvent_VK_KATAKANA,         VK_DBE_KATAKANA},
2899     {java_awt_event_KeyEvent_VK_HIRAGANA,         VK_DBE_HIRAGANA},
2900     {java_awt_event_KeyEvent_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR},
2901     {java_awt_event_KeyEvent_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR},
2902     {java_awt_event_KeyEvent_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
2903 
2904     {java_awt_event_KeyEvent_VK_UNDEFINED,        0}
2905 };
2906 
2907 
2908 // Dynamic mapping table for OEM VK codes.  This table is refilled
2909 // by BuildDynamicKeyMapTable when keyboard layout is switched.
2910 // (see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
2911 struct DynamicKeyMapEntry {
2912     UINT windowsKey;            // OEM VK codes known in advance
2913     UINT javaKey;               // depends on input langauge (kbd layout)
2914 };
2915 
2916 static DynamicKeyMapEntry dynamicKeyMapTable[] = {
2917     {0x00BA,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_1
2918     {0x00BB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PLUS
2919     {0x00BC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_COMMA
2920     {0x00BD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_MINUS
2921     {0x00BE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_PERIOD
2922     {0x00BF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_2
2923     {0x00C0,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_3
2924     {0x00DB,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_4
2925     {0x00DC,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_5
2926     {0x00DD,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_6
2927     {0x00DE,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_7
2928     {0x00DF,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_8
2929     {0x00E2,  java_awt_event_KeyEvent_VK_UNDEFINED}, // VK_OEM_102
2930     {0, 0}
2931 };
2932 
2933 
2934 
2935 // Auxiliary tables used to fill the above dynamic table.  We first
2936 // find the character for the OEM VK code using ::MapVirtualKey and
2937 // then go through these auxiliary tables to map it to Java VK code.
2938 
2939 struct CharToVKEntry {
2940     WCHAR c;
2941     UINT  javaKey;
2942 };
2943 
2944 static const CharToVKEntry charToVKTable[] = {
2945     {L'!',   java_awt_event_KeyEvent_VK_EXCLAMATION_MARK},
2946     {L'"',   java_awt_event_KeyEvent_VK_QUOTEDBL},
2947     {L'#',   java_awt_event_KeyEvent_VK_NUMBER_SIGN},
2948     {L'$',   java_awt_event_KeyEvent_VK_DOLLAR},
2949     {L'&',   java_awt_event_KeyEvent_VK_AMPERSAND},
2950     {L'\'',  java_awt_event_KeyEvent_VK_QUOTE},
2951     {L'(',   java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS},
2952     {L')',   java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS},
2953     {L'*',   java_awt_event_KeyEvent_VK_ASTERISK},
2954     {L'+',   java_awt_event_KeyEvent_VK_PLUS},
2955     {L',',   java_awt_event_KeyEvent_VK_COMMA},
2956     {L'-',   java_awt_event_KeyEvent_VK_MINUS},
2957     {L'.',   java_awt_event_KeyEvent_VK_PERIOD},
2958     {L'/',   java_awt_event_KeyEvent_VK_SLASH},
2959     {L':',   java_awt_event_KeyEvent_VK_COLON},
2960     {L';',   java_awt_event_KeyEvent_VK_SEMICOLON},
2961     {L'<',   java_awt_event_KeyEvent_VK_LESS},
2962     {L'=',   java_awt_event_KeyEvent_VK_EQUALS},
2963     {L'>',   java_awt_event_KeyEvent_VK_GREATER},
2964     {L'@',   java_awt_event_KeyEvent_VK_AT},
2965     {L'[',   java_awt_event_KeyEvent_VK_OPEN_BRACKET},
2966     {L'\\',  java_awt_event_KeyEvent_VK_BACK_SLASH},
2967     {L']',   java_awt_event_KeyEvent_VK_CLOSE_BRACKET},
2968     {L'^',   java_awt_event_KeyEvent_VK_CIRCUMFLEX},
2969     {L'_',   java_awt_event_KeyEvent_VK_UNDERSCORE},
2970     {L'`',   java_awt_event_KeyEvent_VK_BACK_QUOTE},
2971     {L'{',   java_awt_event_KeyEvent_VK_BRACELEFT},
2972     {L'}',   java_awt_event_KeyEvent_VK_BRACERIGHT},
2973     {0x00A1, java_awt_event_KeyEvent_VK_INVERTED_EXCLAMATION_MARK},
2974     {0x20A0, java_awt_event_KeyEvent_VK_EURO_SIGN}, // ????
2975     {0,0}
2976 };
2977 
2978 // For dead accents some layouts return ASCII punctuation, while some
2979 // return spacing accent chars, so both should be listed.  NB: MS docs
2980 // say that conversion routings return spacing accent character, not
2981 // combining.
2982 static const CharToVKEntry charToDeadVKTable[] = {
2983     {L'`',   java_awt_event_KeyEvent_VK_DEAD_GRAVE},
2984     {L'\'',  java_awt_event_KeyEvent_VK_DEAD_ACUTE},
2985     {0x00B4, java_awt_event_KeyEvent_VK_DEAD_ACUTE},
2986     {L'^',   java_awt_event_KeyEvent_VK_DEAD_CIRCUMFLEX},
2987     {L'~',   java_awt_event_KeyEvent_VK_DEAD_TILDE},
2988     {0x02DC, java_awt_event_KeyEvent_VK_DEAD_TILDE},
2989     {0x00AF, java_awt_event_KeyEvent_VK_DEAD_MACRON},
2990     {0x02D8, java_awt_event_KeyEvent_VK_DEAD_BREVE},
2991     {0x02D9, java_awt_event_KeyEvent_VK_DEAD_ABOVEDOT},
2992     {L'"',   java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
2993     {0x00A8, java_awt_event_KeyEvent_VK_DEAD_DIAERESIS},
2994     {0x02DA, java_awt_event_KeyEvent_VK_DEAD_ABOVERING},
2995     {0x02DD, java_awt_event_KeyEvent_VK_DEAD_DOUBLEACUTE},
2996     {0x02C7, java_awt_event_KeyEvent_VK_DEAD_CARON},            // aka hacek
2997     {L',',   java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
2998     {0x00B8, java_awt_event_KeyEvent_VK_DEAD_CEDILLA},
2999     {0x02DB, java_awt_event_KeyEvent_VK_DEAD_OGONEK},
3000     {0x037A, java_awt_event_KeyEvent_VK_DEAD_IOTA},             // ASCII ???
3001     {0x309B, java_awt_event_KeyEvent_VK_DEAD_VOICED_SOUND},
3002     {0x309C, java_awt_event_KeyEvent_VK_DEAD_SEMIVOICED_SOUND},
3003     {0x0004, java_awt_event_KeyEvent_VK_COMPOSE},
3004     {0,0}
3005 };
3006 
3007 // The full map of the current keyboard state including
3008 // windows virtual key, scancode, java virtual key, and unicode
3009 // for this key sans modifiers.
3010 // All but first element may be 0.
3011 // XXX in the update releases this is an addition to the unchanged existing code
3012 struct DynPrimaryKeymapEntry {
3013     UINT wkey;
3014     UINT scancode;
3015     UINT jkey;
3016     WCHAR unicode;
3017 };
3018 
3019 static DynPrimaryKeymapEntry dynPrimaryKeymap[256];
3020 
3021 void
InitDynamicKeyMapTable()3022 AwtComponent::InitDynamicKeyMapTable()
3023 {
3024     static BOOL kbdinited = FALSE;
3025 
3026     if (!kbdinited) {
3027         AwtComponent::BuildDynamicKeyMapTable();
3028         // We cannot build it here since JNI is not available yet:
3029         //AwtComponent::BuildPrimaryDynamicTable();
3030         kbdinited = TRUE;
3031     }
3032 }
3033 
3034 void
BuildDynamicKeyMapTable()3035 AwtComponent::BuildDynamicKeyMapTable()
3036 {
3037     HKL hkl = GetKeyboardLayout();
3038 
3039     DTRACE_PRINTLN2("Building dynamic VK mapping tables: HKL = %08X (CP%d)",
3040                     hkl, AwtComponent::GetCodePage());
3041 
3042     // Will need this to reset layout after dead keys.
3043     UINT spaceScanCode = ::MapVirtualKeyEx(VK_SPACE, 0, hkl);
3044 
3045     // Entries in dynamic table that maps between Java VK and Windows
3046     // VK are built in three steps:
3047     //   1. Map windows VK to ANSI character (cannot map to unicode
3048     //      directly, since ::ToUnicode is not implemented on win9x)
3049     //   2. Convert ANSI char to Unicode char
3050     //   3. Map Unicode char to Java VK via two auxilary tables.
3051 
3052     for (DynamicKeyMapEntry *dynamic = dynamicKeyMapTable;
3053          dynamic->windowsKey != 0;
3054          ++dynamic)
3055     {
3056         // Defaults to VK_UNDEFINED
3057         dynamic->javaKey = java_awt_event_KeyEvent_VK_UNDEFINED;
3058 
3059         BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
3060         AwtToolkit::GetKeyboardState(kbdState);
3061 
3062         kbdState[dynamic->windowsKey] |=  0x80; // Press the key.
3063 
3064         // Unpress modifiers, since they are most likely pressed as
3065         // part of the keyboard switching shortcut.
3066         kbdState[VK_CONTROL] &= ~0x80;
3067         kbdState[VK_SHIFT]   &= ~0x80;
3068         kbdState[VK_MENU]    &= ~0x80;
3069 
3070         char cbuf[2] = { '\0', '\0'};
3071         UINT scancode = ::MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
3072         int nchars = ::ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
3073                                  (WORD*)cbuf, 0, hkl);
3074 
3075         // Auxiliary table used to map Unicode character to Java VK.
3076         // Will assign a different table for dead keys (below).
3077         const CharToVKEntry *charMap = charToVKTable;
3078 
3079         if (nchars < 0) { // Dead key
3080             // Use a different table for dead chars since different layouts
3081             // return different characters for the same dead key.
3082             charMap = charToDeadVKTable;
3083 
3084             // We also need to reset layout so that next translation
3085             // is unaffected by the dead status.  We do this by
3086             // translating <SPACE> key.
3087             kbdState[dynamic->windowsKey] &= ~0x80;
3088             kbdState[VK_SPACE] |= 0x80;
3089 
3090             char junkbuf[2] = { '\0', '\0'};
3091             ::ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
3092                         (WORD*)junkbuf, 0, hkl);
3093         }
3094 
3095 #ifdef DEBUG
3096         if (nchars == 0) {
3097             DTRACE_PRINTLN1("VK 0x%02X -> cannot convert to ANSI char",
3098                             dynamic->windowsKey);
3099             continue;
3100         }
3101         else if (nchars > 1) {  // can't happen, see reset code below
3102             DTRACE_PRINTLN3("VK 0x%02X -> converted to <0x%02X,0x%02X>",
3103                             dynamic->windowsKey,
3104                             (UCHAR)cbuf[0], (UCHAR)cbuf[1]);
3105             continue;
3106         }
3107 #endif
3108 
3109         WCHAR ucbuf[2] = { L'\0', L'\0' };
3110         int nconverted = ::MultiByteToWideChar(AwtComponent::GetCodePage(), 0,
3111                                                cbuf, 1, ucbuf, 2);
3112 #ifdef DEBUG
3113         if (nconverted < 0) {
3114             DTRACE_PRINTLN3("VK 0x%02X -> ANSI 0x%02X -> MultiByteToWideChar failed (0x%X)",
3115                             dynamic->windowsKey, (UCHAR)cbuf[0],
3116                             ::GetLastError());
3117             continue;
3118         }
3119 #endif
3120 
3121         WCHAR uc = ucbuf[0];
3122         for (const CharToVKEntry *map = charMap;  map->c != 0;  ++map) {
3123             if (uc == map->c) {
3124                 dynamic->javaKey = map->javaKey;
3125                 break;
3126             }
3127         }
3128 
3129         DTRACE_PRINTLN4("VK 0x%02X -> ANSI 0x%02X -> U+%04X -> Java VK 0x%X",
3130                         dynamic->windowsKey, (UCHAR)cbuf[0], (UINT)ucbuf[0],
3131                         dynamic->javaKey);
3132     } // for each VK_OEM_*
3133 }
3134 
3135 
isKanaLockAvailable()3136 static BOOL isKanaLockAvailable()
3137 {
3138     // This method is to determine whether the Kana Lock feature is
3139     // available on the attached keyboard.  Kana Lock feature does not
3140     // necessarily require that the real KANA keytop is available on
3141     // keyboard, so using MapVirtualKey(VK_KANA) is not sufficient for testing.
3142     // Instead of that we regard it as Japanese keyboard (w/ Kana Lock) if :-
3143     //
3144     // - the keyboard layout is Japanese (VK_KANA has the same value as VK_HANGUL)
3145     // - the keyboard is Japanese keyboard (keyboard type == 7).
3146     return (LOWORD(GetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
3147         && (GetKeyboardType(0) == 7);
3148 }
3149 
JavaKeyToWindowsKey(UINT javaKey,UINT * windowsKey,UINT * modifiers,UINT originalWindowsKey)3150 void AwtComponent::JavaKeyToWindowsKey(UINT javaKey,
3151                                        UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey)
3152 {
3153     // Handle the few cases where a Java VK code corresponds to a Windows
3154     // key/modifier combination or applies only to specific keyboard layouts
3155     switch (javaKey) {
3156         case java_awt_event_KeyEvent_VK_ALL_CANDIDATES:
3157             *windowsKey = VK_CONVERT;
3158             *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
3159             return;
3160         case java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE:
3161             *windowsKey = VK_CONVERT;
3162             *modifiers = java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3163             return;
3164         case java_awt_event_KeyEvent_VK_CODE_INPUT:
3165             *windowsKey = VK_DBE_ALPHANUMERIC;
3166             *modifiers = java_awt_event_InputEvent_ALT_DOWN_MASK;
3167             return;
3168         case java_awt_event_KeyEvent_VK_KANA_LOCK:
3169             if (isKanaLockAvailable()) {
3170                 *windowsKey = VK_KANA;
3171                 *modifiers = java_awt_event_InputEvent_CTRL_DOWN_MASK;
3172                 return;
3173             }
3174     }
3175 
3176     // for the general case, use a bi-directional table
3177     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3178         if (keyMapTable[i].javaKey == javaKey) {
3179             *windowsKey = keyMapTable[i].windowsKey;
3180             *modifiers = 0;
3181             return;
3182         }
3183     }
3184 
3185     // Bug 4766655
3186     // Two Windows keys could map to the same Java key, so
3187     // give preference to the originalWindowsKey if it is
3188     // specified (not IGNORE_KEY).
3189     if (originalWindowsKey == IGNORE_KEY) {
3190         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3191             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3192                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3193                 *modifiers = 0;
3194                 return;
3195             }
3196         }
3197     } else {
3198         BOOL found = false;
3199         for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3200             if (dynamicKeyMapTable[j].javaKey == javaKey) {
3201                 *windowsKey = dynamicKeyMapTable[j].windowsKey;
3202                 *modifiers = 0;
3203                 found = true;
3204                 if (*windowsKey == originalWindowsKey) {
3205                     return;   /* if ideal case found return, else keep looking */
3206                 }
3207             }
3208         }
3209         if (found) {
3210             return;
3211         }
3212     }
3213 
3214     *windowsKey = 0;
3215     *modifiers = 0;
3216     return;
3217 }
3218 
WindowsKeyToJavaKey(UINT windowsKey,UINT modifiers,UINT character,BOOL isDeadKey)3219 UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey)
3220 
3221 {
3222     // Handle the few cases where we need to take the modifier into
3223     // consideration for the Java VK code or where we have to take the keyboard
3224     // layout into consideration so that function keys can get
3225     // recognized in a platform-independent way.
3226     switch (windowsKey) {
3227         case VK_CONVERT:
3228             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3229                 return java_awt_event_KeyEvent_VK_ALL_CANDIDATES;
3230             }
3231             if ((modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) != 0) {
3232                 return java_awt_event_KeyEvent_VK_PREVIOUS_CANDIDATE;
3233             }
3234             break;
3235         case VK_DBE_ALPHANUMERIC:
3236             if ((modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) != 0) {
3237                 return java_awt_event_KeyEvent_VK_CODE_INPUT;
3238             }
3239             break;
3240         case VK_KANA:
3241             if (isKanaLockAvailable()) {
3242                 return java_awt_event_KeyEvent_VK_KANA_LOCK;
3243             }
3244             break;
3245     };
3246 
3247     // check dead key
3248     if (isDeadKey) {
3249       for (int i = 0; charToDeadVKTable[i].c != 0; i++) {
3250         if (charToDeadVKTable[i].c == character) {
3251             return charToDeadVKTable[i].javaKey;
3252         }
3253       }
3254     }
3255 
3256     // for the general case, use a bi-directional table
3257     for (int i = 0; keyMapTable[i].windowsKey != 0; i++) {
3258         if (keyMapTable[i].windowsKey == windowsKey) {
3259             return keyMapTable[i].javaKey;
3260         }
3261     }
3262 
3263     for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
3264         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
3265             if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
3266                 return dynamicKeyMapTable[j].javaKey;
3267             }else{
3268                 break;
3269             }
3270         }
3271     }
3272 
3273     return java_awt_event_KeyEvent_VK_UNDEFINED;
3274 }
3275 
IsNavigationKey(UINT wkey)3276 BOOL AwtComponent::IsNavigationKey(UINT wkey) {
3277     switch (wkey) {
3278       case VK_END:
3279       case VK_PRIOR:  // PageUp
3280       case VK_NEXT:  // PageDown
3281       case VK_HOME:
3282       case VK_LEFT:
3283       case VK_UP:
3284       case VK_RIGHT:
3285       case VK_DOWN:
3286           return TRUE;
3287     }
3288     return FALSE;
3289 }
3290 
3291 // determine if a key is a numpad key (distinguishes the numpad
3292 // arrow keys from the non-numpad arrow keys, for example).
IsNumPadKey(UINT vkey,BOOL extended)3293 BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended)
3294 {
3295     // Note: scancodes are the same for the numpad arrow keys and
3296     // the non-numpad arrow keys (also for PageUp, etc.).
3297     // The scancodes for the numpad divide and the non-numpad slash
3298     // are the same, but the wparams are different
3299 
3300     DTRACE_PRINTLN3("AwtComponent::IsNumPadKey  vkey = %d = 0x%x  extended = %d",
3301       vkey, vkey, extended);
3302 
3303     switch (vkey) {
3304       case VK_CLEAR:  // numpad 5 with numlock off
3305       case VK_NUMPAD0:
3306       case VK_NUMPAD1:
3307       case VK_NUMPAD2:
3308       case VK_NUMPAD3:
3309       case VK_NUMPAD4:
3310       case VK_NUMPAD5:
3311       case VK_NUMPAD6:
3312       case VK_NUMPAD7:
3313       case VK_NUMPAD8:
3314       case VK_NUMPAD9:
3315       case VK_MULTIPLY:
3316       case VK_ADD:
3317       case VK_SEPARATOR:  // numpad ,  not on US kbds
3318       case VK_SUBTRACT:
3319       case VK_DECIMAL:
3320       case VK_DIVIDE:
3321       case VK_NUMLOCK:
3322         return TRUE;
3323         break;
3324       case VK_END:
3325       case VK_PRIOR:  // PageUp
3326       case VK_NEXT:  // PageDown
3327       case VK_HOME:
3328       case VK_LEFT:
3329       case VK_UP:
3330       case VK_RIGHT:
3331       case VK_DOWN:
3332       case VK_INSERT:
3333       case VK_DELETE:
3334         // extended if non-numpad
3335         return (!extended);
3336         break;
3337       case VK_RETURN:  // extended if on numpad
3338         return (extended);
3339         break;
3340       default:
3341         break;
3342     }
3343 
3344     return FALSE;
3345 }
3346 static void
resetKbdState(BYTE kstate[256])3347 resetKbdState( BYTE kstate[256]) {
3348     BYTE tmpState[256];
3349     WCHAR wc[2];
3350     memmove(tmpState, kstate, sizeof(kstate));
3351     tmpState[VK_SHIFT] = 0;
3352     tmpState[VK_CONTROL] = 0;
3353     tmpState[VK_MENU] = 0;
3354 
3355     ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0,  GetKeyboardLayout(0));
3356 }
3357 
3358 // XXX in the update releases this is an addition to the unchanged existing code
3359 // After the call, a table will have a unicode associated with a windows virtual keycode
3360 // sans modifiers. With some further simplification, one can
3361 // derive java keycode from it, and anyway we will pass this unicode value
3362 // all the way up in a comment to a KeyEvent.
3363 void
BuildPrimaryDynamicTable()3364 AwtComponent::BuildPrimaryDynamicTable() {
3365     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
3366     // XXX: how about that?
3367     //CriticalSection::Lock l(GetLock());
3368     //if (GetPeer(env) == NULL) {
3369     //    /* event received during termination. */
3370     //    return;
3371     //}
3372 
3373     HKL hkl = GetKeyboardLayout();
3374     UINT sc = 0;
3375     BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
3376     memset(kbdState, 0, sizeof (kbdState));
3377 
3378     // Use JNI call to obtain java key code. We should keep a list
3379     // of currently available keycodes in a single place.
3380     static jclass extKeyCodesCls;
3381     if( extKeyCodesCls == NULL) {
3382         jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes");
3383         DASSERT(extKeyCodesClsLocal);
3384         CHECK_NULL(extKeyCodesClsLocal);
3385         extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal);
3386         env->DeleteLocalRef(extKeyCodesClsLocal);
3387     }
3388     static jmethodID getExtendedKeyCodeForChar;
3389     if (getExtendedKeyCodeForChar == NULL) {
3390         getExtendedKeyCodeForChar =
3391                   env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I");
3392         DASSERT(getExtendedKeyCodeForChar);
3393         CHECK_NULL(getExtendedKeyCodeForChar);
3394     }
3395     jint extJKC; //extended Java key code
3396 
3397     for (UINT i = 0; i < 256; i++) {
3398         dynPrimaryKeymap[i].wkey = i;
3399         dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED;
3400         dynPrimaryKeymap[i].unicode = 0;
3401 
3402         if ((sc = MapVirtualKey (i, 0)) == 0) {
3403             dynPrimaryKeymap[i].scancode = 0;
3404             continue;
3405         }
3406         dynPrimaryKeymap[i].scancode = sc;
3407 
3408         // XXX process cases like VK_SHIFT etc.
3409         kbdState[i] = 0x80; // "key pressed".
3410         WCHAR wc[16];
3411         int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl);
3412         if (k == 1) {
3413             // unicode
3414             dynPrimaryKeymap[i].unicode = wc[0];
3415             if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) {
3416             // Convert unicode to java keycode.
3417                 //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000);
3418                 //
3419                 //XXX If this key in on the keypad, we should force a special value equal to
3420                 //XXX an old java keycode: but how to say if it is a keypad key?
3421                 //XXX We'll do it in WmKeyUp/Down.
3422                 extJKC = env->CallStaticIntMethod(extKeyCodesCls,
3423                                                   getExtendedKeyCodeForChar, (jint)(wc[0]));
3424                 dynPrimaryKeymap[i].jkey = extJKC;
3425             }
3426         }else if (k == -1) {
3427             // dead key: use charToDeadVKTable
3428             dynPrimaryKeymap[i].unicode = wc[0];
3429             resetKbdState( kbdState );
3430             for (const CharToVKEntry *map = charToDeadVKTable;  map->c != 0;  ++map) {
3431                 if (wc[0] == map->c) {
3432                     dynPrimaryKeymap[i].jkey = map->javaKey;
3433                     break;
3434                 }
3435             }
3436         } else if (k == 0) {
3437             // reset
3438             resetKbdState( kbdState );
3439         }else {
3440             // k > 1: this key does generate multiple characters. Ignore it.
3441             // An example: Arabic Lam and Alef ligature.
3442             // There will be no extended keycode and thus shortcuts for this  key.
3443             // XXX shouldn't we reset the kbd state?
3444 #ifdef DEBUG
3445             DTRACE_PRINTLN2("wkey 0x%02X (%d)", i,i);
3446 #endif
3447         }
3448         kbdState[i] = 0; // "key unpressed"
3449     }
3450 }
3451 void
UpdateDynPrimaryKeymap(UINT wkey,UINT jkeyLegacy,jint keyLocation,UINT modifiers)3452 AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
3453 {
3454     if( wkey && wkey < 256 ) {
3455         if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
3456             // At the creation time,
3457             // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
3458             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3459         }
3460         if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
3461             // E.g. it is non-unicode key
3462             dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
3463         }
3464     }
3465 }
3466 
WindowsKeyToJavaChar(UINT wkey,UINT modifiers,TransOps ops,BOOL & isDeadKey)3467 UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops, BOOL &isDeadKey)
3468 {
3469     static Hashtable transTable("VKEY translations");
3470     static Hashtable deadKeyFlagTable("Dead Key Flags");
3471     isDeadKey = FALSE;
3472 
3473     // Try to translate using last saved translation
3474     if (ops == LOAD) {
3475        void* deadKeyFlag = deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3476        void* value = transTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3477        if (value != NULL) {
3478            isDeadKey = static_cast<BOOL>(reinterpret_cast<INT_PTR>(deadKeyFlag));
3479            return static_cast<UINT>(reinterpret_cast<INT_PTR>(value));
3480        }
3481     }
3482 
3483     // If the windows key is a return, wkey will equal 13 ('\r')
3484     // In this case, we want to return 10 ('\n')
3485     // Since ToAscii would convert VK_RETURN to '\r', we need
3486     // to have a special case here.
3487     if (wkey == VK_RETURN)
3488         return '\n';
3489 
3490     // high order bit in keyboardState indicates whether the key is down
3491     static const BYTE KEY_STATE_DOWN = 0x80;
3492     BYTE    keyboardState[AwtToolkit::KB_STATE_SIZE];
3493     AwtToolkit::GetKeyboardState(keyboardState);
3494 
3495     // apply modifiers to keyboard state if necessary
3496     BOOL shiftIsDown = FALSE;
3497     if (modifiers) {
3498         shiftIsDown = modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK;
3499         BOOL altIsDown = modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK;
3500         BOOL ctrlIsDown = modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK;
3501 
3502         // Windows treats AltGr as Ctrl+Alt
3503         if (modifiers & java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK) {
3504             altIsDown = TRUE;
3505             ctrlIsDown = TRUE;
3506         }
3507 
3508         if (shiftIsDown) {
3509             keyboardState[VK_SHIFT] |= KEY_STATE_DOWN;
3510         }
3511 
3512         // fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715)
3513         // Here we try to resolve a conflict with ::ToAsciiEx's translating
3514         // ALT+number key combinations. kdm@sarc.spb.su
3515         // yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail.
3516         if( IsNavigationKey(wkey) ) {
3517             keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
3518         }
3519 
3520         if (ctrlIsDown)
3521         {
3522             if (altIsDown) {
3523                 // bugid 4215009: don't mess with AltGr == Ctrl + Alt
3524                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3525             }
3526             else {
3527                 // bugid 4098210: old event model doesn't have KEY_TYPED
3528                 // events, so try to provide a meaningful character for
3529                 // Ctrl+<key>.  Take Ctrl into account only when we know
3530                 // that Ctrl+<key> will be an ASCII control.  Ignore by
3531                 // default.
3532                 keyboardState[VK_CONTROL] &= ~KEY_STATE_DOWN;
3533 
3534                 // Letters have Ctrl+<letter> counterparts.  According to
3535                 // <winuser.h> VK_A through VK_Z are the same as ASCII
3536                 // 'A' through 'Z'.
3537                 if (wkey >= 'A' && wkey <= 'Z') {
3538                     keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3539                 }
3540                 else {
3541                     // Non-letter controls 033 to 037 are:
3542                     // ^[ (ESC), ^\ (FS), ^] (GS), ^^ (RS), and ^_ (US)
3543 
3544                     // Shift state bits returned by ::VkKeyScan in HIBYTE
3545                     static const UINT _VKS_SHIFT_MASK = 0x01;
3546                     static const UINT _VKS_CTRL_MASK = 0x02;
3547                     static const UINT _VKS_ALT_MASK = 0x04;
3548 
3549                     // Check to see whether there is a meaningful translation
3550                     TCHAR ch;
3551                     short vk;
3552                     for (ch = _T('\033'); ch < _T('\040'); ch++) {
3553                         vk = ::VkKeyScan(ch);
3554                         if (wkey == LOBYTE(vk)) {
3555                             UINT shiftState = HIBYTE(vk);
3556                             if ((shiftState & _VKS_CTRL_MASK) ||
3557                                 (!(shiftState & _VKS_SHIFT_MASK)
3558                                 == !shiftIsDown))
3559                             {
3560                                 keyboardState[VK_CONTROL] |= KEY_STATE_DOWN;
3561                             }
3562                             break;
3563                         }
3564                     }
3565                 }
3566             } // ctrlIsDown && altIsDown
3567         } // ctrlIsDown
3568     } // modifiers
3569 
3570     WORD wChar[2];
3571     int converted = 1;
3572     UINT ch = ::MapVirtualKeyEx(wkey, 2, GetKeyboardLayout());
3573     if (ch & 0x80000000) {
3574         // Dead key which is handled as a normal key
3575         isDeadKey = deadKeyActive = TRUE;
3576     } else if (deadKeyActive) {
3577         // We cannot use ::ToUnicodeEx if dead key is active because this will
3578         // break dead key function
3579         wChar[0] = shiftIsDown ? ch : tolower(ch);
3580     } else {
3581         UINT scancode = ::MapVirtualKey(wkey, 0);
3582         converted = ::ToUnicodeEx(wkey, scancode, keyboardState,
3583                                               wChar, 2, 0, GetKeyboardLayout());
3584     }
3585 
3586     UINT translation;
3587     BOOL deadKeyFlag = (converted == 2);
3588 
3589     // Dead Key
3590     if (converted < 0 || isDeadKey) {
3591         translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3592     } else
3593     // No translation available -- try known conversions or else punt.
3594     if (converted == 0) {
3595         if (wkey == VK_DELETE) {
3596             translation = '\177';
3597         } else
3598         if (wkey >= VK_NUMPAD0 && wkey <= VK_NUMPAD9) {
3599             translation = '0' + wkey - VK_NUMPAD0;
3600         } else {
3601             translation = java_awt_event_KeyEvent_CHAR_UNDEFINED;
3602         }
3603     } else
3604     // the caller expects a Unicode character.
3605     if (converted > 0) {
3606         translation = wChar[0];
3607     }
3608     if (ops == SAVE) {
3609         transTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3610                        reinterpret_cast<void*>(static_cast<INT_PTR>(translation)));
3611         if (deadKeyFlag) {
3612             deadKeyFlagTable.put(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)),
3613                          reinterpret_cast<void*>(static_cast<INT_PTR>(deadKeyFlag)));
3614         } else {
3615             deadKeyFlagTable.remove(reinterpret_cast<void*>(static_cast<INT_PTR>(wkey)));
3616         }
3617     }
3618 
3619     isDeadKey = deadKeyFlag;
3620     return translation;
3621 }
3622 
WmKeyDown(UINT wkey,UINT repCnt,UINT flags,BOOL system)3623 MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt,
3624                                    UINT flags, BOOL system)
3625 {
3626     // VK_PROCESSKEY is a special value which means
3627     //          "Current IME wants to consume this KeyEvent"
3628     // Real key code is saved by IMM32.DLL and can be retrieved by
3629     // calling ImmGetVirtualKey();
3630     if (wkey == VK_PROCESSKEY) {
3631         return mrDoDefault;
3632     }
3633     MSG msg;
3634     InitMessage(&msg, (system ? WM_SYSKEYDOWN : WM_KEYDOWN),
3635                              wkey, MAKELPARAM(repCnt, flags));
3636 
3637     UINT modifiers = GetJavaModifiers();
3638     jint keyLocation = GetKeyLocation(wkey, flags);
3639     BOOL isDeadKey = FALSE;
3640     UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE, isDeadKey);
3641     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3642     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3643 
3644 
3645     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
3646                              TimeHelper::getMessageTimeUTC(), jkey, character,
3647                              modifiers, keyLocation, (jlong)wkey, &msg);
3648 
3649     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
3650     // for some reason, so we need to create the KEY_TYPED event on the
3651     // WM_KEYDOWN.  Use null msg so the character doesn't get sent back
3652     // to the native window for processing (this event is synthesized
3653     // for Java - we don't want Windows trying to process it).
3654     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
3655         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3656                                  TimeHelper::getMessageTimeUTC(),
3657                                  java_awt_event_KeyEvent_VK_UNDEFINED,
3658                                  character, modifiers,
3659                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
3660     }
3661 
3662     return mrConsume;
3663 }
3664 
WmKeyUp(UINT wkey,UINT repCnt,UINT flags,BOOL system)3665 MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt,
3666                                  UINT flags, BOOL system)
3667 {
3668 
3669     // VK_PROCESSKEY is a special value which means
3670     //          "Current IME wants to consume this KeyEvent"
3671     // Real key code is saved by IMM32.DLL and can be retrieved by
3672     // calling ImmGetVirtualKey();
3673     if (wkey == VK_PROCESSKEY) {
3674         return mrDoDefault;
3675     }
3676     MSG msg;
3677     InitMessage(&msg, (system ? WM_SYSKEYUP : WM_KEYUP),
3678                              wkey, MAKELPARAM(repCnt, flags));
3679 
3680     UINT modifiers = GetJavaModifiers();
3681     jint keyLocation = GetKeyLocation(wkey, flags);
3682     BOOL isDeadKey = FALSE;
3683     UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD, isDeadKey);
3684     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers, character, isDeadKey);
3685     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
3686 
3687     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
3688                              TimeHelper::getMessageTimeUTC(), jkey, character,
3689                              modifiers, keyLocation, (jlong)wkey, &msg);
3690     return mrConsume;
3691 }
3692 
WmInputLangChange(UINT charset,HKL hKeyboardLayout)3693 MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout)
3694 {
3695     // Normally we would be able to use charset and TranslateCharSetInfo
3696     // to get a code page that should be associated with this keyboard
3697     // layout change. However, there seems to be an NT 4.0 bug associated
3698     // with the WM_INPUTLANGCHANGE message, which makes the charset parameter
3699     // unreliable, especially on Asian systems. Our workaround uses the
3700     // keyboard layout handle instead.
3701     m_hkl = hKeyboardLayout;
3702     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
3703     m_CodePage = LangToCodePage(m_idLang);
3704     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM
3705     BuildPrimaryDynamicTable();
3706     return mrConsume;           // do not propagate to children
3707 }
3708 
3709 // Convert Language ID to CodePage
LangToCodePage(LANGID idLang)3710 UINT AwtComponent::LangToCodePage(LANGID idLang)
3711 {
3712     TCHAR strCodePage[MAX_ACP_STR_LEN];
3713     // use the LANGID to create a LCID
3714     LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
3715     // get the ANSI code page associated with this locale
3716     if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
3717         return _ttoi(strCodePage);
3718     else
3719         return GetACP();
3720 }
3721 
3722 
WmIMEChar(UINT character,UINT repCnt,UINT flags,BOOL system)3723 MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL system)
3724 {
3725     // We will simply create Java events here.
3726     WCHAR unicodeChar = character;
3727     MSG msg;
3728     InitMessage(&msg, WM_IME_CHAR, character,
3729                               MAKELPARAM(repCnt, flags));
3730 
3731     jint modifiers = GetJavaModifiers();
3732     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3733                              TimeHelper::getMessageTimeUTC(),
3734                              java_awt_event_KeyEvent_VK_UNDEFINED,
3735                              unicodeChar, modifiers,
3736                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3737                              &msg);
3738     return mrConsume;
3739 }
3740 
WmChar(UINT character,UINT repCnt,UINT flags,BOOL system)3741 MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags,
3742                                 BOOL system)
3743 {
3744     deadKeyActive = FALSE;
3745 
3746     // Will only get WmChar messages with DBCS if we create them for
3747     // an Edit class in the WmForwardChar method. These synthesized
3748     // DBCS chars are ok to pass on directly to the default window
3749     // procedure. They've already been filtered through the Java key
3750     // event queue. We will never get the trail byte since the edit
3751     // class will PeekMessage(&msg, hwnd, WM_CHAR, WM_CHAR,
3752     // PM_REMOVE).  I would like to be able to pass this character off
3753     // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to
3754     // like that.
3755 
3756     // We will simply create Java events here.
3757     UINT message = system ? WM_SYSCHAR : WM_CHAR;
3758 
3759     // The Alt modifier is reported in the 29th bit of the lParam,
3760     // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
3761     bool alt_is_down = (flags & (1<<13)) != 0;
3762 
3763     // Fix for bug 4141621, corrected by fix for bug 6223726: Alt+space doesn't invoke system menu
3764     // We should not pass this particular combination to Java.
3765 
3766     if (system && alt_is_down) {
3767         if (character == VK_SPACE) {
3768             return mrDoDefault;
3769         }
3770     }
3771 
3772     // If this is a WM_CHAR (non-system) message, then the Alt flag
3773     // indicates that the character was typed using an AltGr key
3774     // (which Windows treats as Ctrl+Alt), so in this case we do NOT
3775     // pass the Ctrl and Alt modifiers to Java, but instead we
3776     // replace them with Java's AltGraph modifier.  Note: the AltGraph
3777     // modifier does not exist in 1.1.x releases.
3778     jint modifiers = GetJavaModifiers();
3779     if (!system && alt_is_down) {
3780         // character typed with AltGraph
3781         modifiers &= ~(java_awt_event_InputEvent_ALT_DOWN_MASK
3782                        | java_awt_event_InputEvent_CTRL_DOWN_MASK);
3783         modifiers |= java_awt_event_InputEvent_ALT_GRAPH_DOWN_MASK;
3784     }
3785 
3786     WCHAR unicodeChar = character;
3787 
3788     // Kludge: Combine pending single byte with this char for some Chinese IMEs
3789     if (m_PendingLeadByte != 0) {
3790         character = (m_PendingLeadByte & 0x00ff) | (character << 8);
3791         m_PendingLeadByte = 0;
3792         ::MultiByteToWideChar(GetCodePage(), 0, (CHAR*)&character, 2,
3793                           &unicodeChar, 1);
3794     }
3795 
3796     if (unicodeChar == VK_RETURN) {
3797         // Enter key generates \r in windows, but \n is required in java
3798         unicodeChar = java_awt_event_KeyEvent_VK_ENTER;
3799     }
3800     MSG msg;
3801     InitMessage(&msg, message, character,
3802                               MAKELPARAM(repCnt, flags));
3803     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
3804                              TimeHelper::getMessageTimeUTC(),
3805                              java_awt_event_KeyEvent_VK_UNDEFINED,
3806                              unicodeChar, modifiers,
3807                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
3808                              &msg);
3809     return mrConsume;
3810 }
3811 
WmForwardChar(WCHAR character,LPARAM lParam,BOOL synthetic)3812 MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam,
3813                                        BOOL synthetic)
3814 {
3815     deadKeyActive = FALSE;
3816 
3817     // just post WM_CHAR with unicode key value
3818     DefWindowProc(WM_CHAR, (WPARAM)character, lParam);
3819     return mrConsume;
3820 }
3821 
WmPaste()3822 MsgRouting AwtComponent::WmPaste()
3823 {
3824     return mrDoDefault;
3825 }
3826 
3827 // support IME Composition messages
SetCompositionWindow(RECT & r)3828 void AwtComponent::SetCompositionWindow(RECT& r)
3829 {
3830     HWND hwnd = ImmGetHWnd();
3831     HIMC hIMC = ImmGetContext(hwnd);
3832     if (hIMC == NULL) {
3833         return;
3834     }
3835     COMPOSITIONFORM cf = {CFS_DEFAULT, {0, 0}, {0, 0, 0, 0}};
3836     ImmSetCompositionWindow(hIMC, &cf);
3837     ImmReleaseContext(hwnd, hIMC);
3838 }
3839 
OpenCandidateWindow(int x,int y)3840 void AwtComponent::OpenCandidateWindow(int x, int y)
3841 {
3842     UINT bits = 1;
3843     POINT p = {0, 0}; // upper left corner of the client area
3844     HWND hWnd = GetHWnd();
3845     if (!::IsWindowVisible(hWnd)) {
3846         return;
3847     }
3848     HWND hTop = GetTopLevelParentForWindow(hWnd);
3849     ::ClientToScreen(hTop, &p);
3850     if (!m_bitsCandType) {
3851         SetCandidateWindow(m_bitsCandType, x - p.x, y - p.y);
3852         return;
3853     }
3854     for (int iCandType=0; iCandType<32; iCandType++, bits<<=1) {
3855         if ( m_bitsCandType & bits )
3856             SetCandidateWindow(iCandType, x - p.x, y - p.y);
3857     }
3858 }
3859 
SetCandidateWindow(int iCandType,int x,int y)3860 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
3861 {
3862     HWND hwnd = ImmGetHWnd();
3863     HIMC hIMC = ImmGetContext(hwnd);
3864     if (hIMC) {
3865         CANDIDATEFORM cf;
3866         cf.dwStyle = CFS_POINT;
3867         ImmGetCandidateWindow(hIMC, 0, &cf);
3868         if (x != cf.ptCurrentPos.x || y != cf.ptCurrentPos.y) {
3869             cf.dwIndex = iCandType;
3870             cf.dwStyle = CFS_POINT;
3871             cf.ptCurrentPos.x = x;
3872             cf.ptCurrentPos.y = y;
3873             cf.rcArea.left = cf.rcArea.top = cf.rcArea.right = cf.rcArea.bottom = 0;
3874             ImmSetCandidateWindow(hIMC, &cf);
3875         }
3876         COMPOSITIONFORM cfr;
3877         cfr.dwStyle = CFS_POINT;
3878         ImmGetCompositionWindow(hIMC, &cfr);
3879         if (x != cfr.ptCurrentPos.x || y != cfr.ptCurrentPos.y) {
3880             cfr.dwStyle = CFS_POINT;
3881             cfr.ptCurrentPos.x = x;
3882             cfr.ptCurrentPos.y = y;
3883             cfr.rcArea.left = cfr.rcArea.top = cfr.rcArea.right = cfr.rcArea.bottom = 0;
3884             ImmSetCompositionWindow(hIMC, &cfr);
3885         }
3886         ImmReleaseContext(hwnd, hIMC);
3887     }
3888 }
3889 
WmImeSetContext(BOOL fSet,LPARAM * lplParam)3890 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
3891 {
3892     // If the Windows input context is disabled, do not let Windows
3893     // display any UIs.
3894     HWND hwnd = ImmGetHWnd();
3895     HIMC hIMC = ImmGetContext(hwnd);
3896     if (hIMC == NULL) {
3897         *lplParam = 0;
3898         return mrDoDefault;
3899     }
3900     ImmReleaseContext(hwnd, hIMC);
3901 
3902     if (fSet) {
3903         LPARAM lParam = *lplParam;
3904         if (!m_useNativeCompWindow) {
3905             // stop to draw native composing window.
3906             *lplParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
3907         }
3908     }
3909     return mrDoDefault;
3910 }
3911 
WmImeNotify(WPARAM subMsg,LPARAM bitsCandType)3912 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
3913 {
3914     if (!m_useNativeCompWindow) {
3915         if (subMsg == IMN_OPENCANDIDATE || subMsg == IMN_CHANGECANDIDATE) {
3916             m_bitsCandType = bitsCandType;
3917             InquireCandidatePosition();
3918         } else if (subMsg == IMN_OPENSTATUSWINDOW ||
3919                    subMsg == WM_IME_STARTCOMPOSITION ||
3920                    subMsg == IMN_SETCANDIDATEPOS) {
3921             InquireCandidatePosition();
3922         }
3923     }
3924     return mrDoDefault;
3925 }
3926 
WmImeStartComposition()3927 MsgRouting AwtComponent::WmImeStartComposition()
3928 {
3929     if (m_useNativeCompWindow) {
3930         RECT rc;
3931         ::GetClientRect(GetHWnd(), &rc);
3932         SetCompositionWindow(rc);
3933         return mrDoDefault;
3934     } else
3935         return mrConsume;
3936 }
3937 
WmImeEndComposition()3938 MsgRouting AwtComponent::WmImeEndComposition()
3939 {
3940     if (m_useNativeCompWindow)   return mrDoDefault;
3941 
3942     SendInputMethodEvent(
3943         java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3944         NULL, 0, NULL, NULL, 0, NULL, NULL, 0, 0, 0 );
3945     return mrConsume;
3946 }
3947 
WmImeComposition(WORD wChar,LPARAM flags)3948 MsgRouting AwtComponent::WmImeComposition(WORD wChar, LPARAM flags)
3949 {
3950     if (m_useNativeCompWindow)   return mrDoDefault;
3951 
3952     int*      bndClauseW = NULL;
3953     jstring*  readingClauseW = NULL;
3954     int*      bndAttrW = NULL;
3955     BYTE*     valAttrW = NULL;
3956     int       cClauseW = 0;
3957     AwtInputTextInfor* textInfor = NULL;
3958 
3959     try {
3960         HWND hwnd = ImmGetHWnd();
3961         HIMC hIMC = ImmGetContext(hwnd);
3962         DASSERT(hIMC!=0);
3963 
3964         textInfor = new AwtInputTextInfor;
3965         textInfor->GetContextData(hIMC, flags);
3966         ImmReleaseContext(hwnd, hIMC);
3967 
3968         jstring jtextString = textInfor->GetText();
3969         /* The conditions to send the input method event to AWT EDT are:
3970            1. Whenever there is a composition message sent regarding whether
3971            the composition text is NULL or not. See details at bug 6222692.
3972            2. When there is a committed message sent, in which case, we have to
3973            check whether the committed string is NULL or not. If the committed string
3974            is NULL, there is no need to send any input method event.
3975            (Minor note: 'jtextString' returned is the merged string in the case of
3976            partial commit.)
3977         */
3978         if ((flags & GCS_RESULTSTR && jtextString != NULL) ||
3979             (flags & GCS_COMPSTR)) {
3980             int       cursorPosW = textInfor->GetCursorPosition();
3981             // In order not to delete the readingClauseW in the catch clause,
3982             // calling GetAttributeInfor before GetClauseInfor.
3983             int       cAttrW = textInfor->GetAttributeInfor(bndAttrW, valAttrW);
3984             cClauseW = textInfor->GetClauseInfor(bndClauseW, readingClauseW);
3985 
3986             /* Send INPUT_METHOD_TEXT_CHANGED event to the WInputMethod which in turn sends
3987                the event to AWT EDT.
3988 
3989                The last two paremeters are set to equal since we don't have recommendations for
3990                the visible position within the current composed text. See details at
3991                java.awt.event.InputMethodEvent.
3992             */
3993             SendInputMethodEvent(java_awt_event_InputMethodEvent_INPUT_METHOD_TEXT_CHANGED,
3994                                  jtextString,
3995                                  cClauseW, bndClauseW, readingClauseW,
3996                                  cAttrW, bndAttrW, valAttrW,
3997                                  textInfor->GetCommittedTextLength(),
3998                                  cursorPosW, cursorPosW);
3999         }
4000     } catch (...) {
4001         // since GetClauseInfor and GetAttributeInfor could throw exception, we have to release
4002         // the pointer here.
4003         delete [] bndClauseW;
4004         delete [] readingClauseW;
4005         delete [] bndAttrW;
4006         delete [] valAttrW;
4007         throw;
4008     }
4009 
4010     /* Free the storage allocated. Since jtextString won't be passed from threads
4011      *  to threads, we just use the local ref and it will be deleted within the destructor
4012      *  of AwtInputTextInfor object.
4013      */
4014     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4015     if (cClauseW && readingClauseW) {
4016         for (int i = 0; i < cClauseW; i ++) {
4017             if (readingClauseW[i]) {
4018                 env->DeleteLocalRef(readingClauseW[i]);
4019             }
4020         }
4021     }
4022     delete [] bndClauseW;
4023     delete [] readingClauseW;
4024     delete [] bndAttrW;
4025     delete [] valAttrW;
4026     delete textInfor;
4027 
4028     return mrConsume;
4029 }
4030 
4031 //
4032 // generate and post InputMethodEvent
4033 //
SendInputMethodEvent(jint id,jstring text,int cClause,int * rgClauseBoundary,jstring * rgClauseReading,int cAttrBlock,int * rgAttrBoundary,BYTE * rgAttrValue,int commitedTextLength,int caretPos,int visiblePos)4034 void AwtComponent::SendInputMethodEvent(jint id, jstring text,
4035                                         int cClause, int* rgClauseBoundary, jstring* rgClauseReading,
4036                                         int cAttrBlock, int* rgAttrBoundary, BYTE *rgAttrValue,
4037                                         int commitedTextLength, int caretPos, int visiblePos)
4038 {
4039     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4040 
4041     // assumption for array type casting
4042     DASSERT(sizeof(int)==sizeof(jint));
4043     DASSERT(sizeof(BYTE)==sizeof(jbyte));
4044 
4045     // caluse information
4046     jintArray clauseBoundary = NULL;
4047     jobjectArray clauseReading = NULL;
4048     if (cClause && rgClauseBoundary && rgClauseReading) {
4049         // convert clause boundary offset array to java array
4050         clauseBoundary = env->NewIntArray(cClause+1);
4051         DASSERT(clauseBoundary);
4052         CHECK_NULL(clauseBoundary);
4053         env->SetIntArrayRegion(clauseBoundary, 0, cClause+1, (jint *)rgClauseBoundary);
4054         DASSERT(!safe_ExceptionOccurred(env));
4055 
4056         // convert clause reading string array to java array
4057         jclass stringCls = JNU_ClassString(env);
4058         DASSERT(stringCls);
4059         CHECK_NULL(stringCls);
4060         clauseReading = env->NewObjectArray(cClause, stringCls, NULL);
4061         DASSERT(clauseReading);
4062         CHECK_NULL(clauseReading);
4063         for (int i=0; i<cClause; i++)   env->SetObjectArrayElement(clauseReading, i, rgClauseReading[i]);
4064         DASSERT(!safe_ExceptionOccurred(env));
4065     }
4066 
4067 
4068     // attrubute value definition in WInputMethod.java must be equal to that in IMM.H
4069     DASSERT(ATTR_INPUT==sun_awt_windows_WInputMethod_ATTR_INPUT);
4070     DASSERT(ATTR_TARGET_CONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_CONVERTED);
4071     DASSERT(ATTR_CONVERTED==sun_awt_windows_WInputMethod_ATTR_CONVERTED);
4072     DASSERT(ATTR_TARGET_NOTCONVERTED==sun_awt_windows_WInputMethod_ATTR_TARGET_NOTCONVERTED);
4073     DASSERT(ATTR_INPUT_ERROR==sun_awt_windows_WInputMethod_ATTR_INPUT_ERROR);
4074 
4075     // attribute information
4076     jintArray attrBoundary = NULL;
4077     jbyteArray attrValue = NULL;
4078     if (cAttrBlock && rgAttrBoundary && rgAttrValue) {
4079         // convert attribute boundary offset array to java array
4080         attrBoundary = env->NewIntArray(cAttrBlock+1);
4081         DASSERT(attrBoundary);
4082         CHECK_NULL(attrBoundary);
4083         env->SetIntArrayRegion(attrBoundary, 0, cAttrBlock+1, (jint *)rgAttrBoundary);
4084         DASSERT(!safe_ExceptionOccurred(env));
4085 
4086         // convert attribute value byte array to java array
4087         attrValue = env->NewByteArray(cAttrBlock);
4088         DASSERT(attrValue);
4089         CHECK_NULL(attrValue);
4090         env->SetByteArrayRegion(attrValue, 0, cAttrBlock, (jbyte *)rgAttrValue);
4091         DASSERT(!safe_ExceptionOccurred(env));
4092     }
4093 
4094 
4095     // get global reference of WInputMethod class (run only once)
4096     static jclass wInputMethodCls = NULL;
4097     if (wInputMethodCls == NULL) {
4098         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4099         DASSERT(wInputMethodClsLocal);
4100         CHECK_NULL(wInputMethodClsLocal);
4101         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4102         env->DeleteLocalRef(wInputMethodClsLocal);
4103     }
4104 
4105     // get method ID of sendInputMethodEvent() (run only once)
4106     static jmethodID sendIMEventMid = 0;
4107     if (sendIMEventMid == 0) {
4108         sendIMEventMid =  env->GetMethodID(wInputMethodCls, "sendInputMethodEvent",
4109                                            "(IJLjava/lang/String;[I[Ljava/lang/String;[I[BIII)V");
4110         DASSERT(sendIMEventMid);
4111         CHECK_NULL(sendIMEventMid);
4112     }
4113 
4114     // call m_InputMethod.sendInputMethod()
4115     env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, TimeHelper::getMessageTimeUTC(),
4116                         text, clauseBoundary, clauseReading, attrBoundary,
4117                         attrValue, commitedTextLength, caretPos, visiblePos);
4118     if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
4119     DASSERT(!safe_ExceptionOccurred(env));
4120 
4121 }
4122 
4123 
4124 
4125 //
4126 // Inquires candidate position according to the composed text
4127 //
InquireCandidatePosition()4128 void AwtComponent::InquireCandidatePosition()
4129 {
4130     if (!::IsWindowVisible(GetHWnd())) {
4131         return;
4132     }
4133     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4134 
4135     // get global reference of WInputMethod class (run only once)
4136     static jclass wInputMethodCls = NULL;
4137     if (wInputMethodCls == NULL) {
4138         jclass wInputMethodClsLocal = env->FindClass("sun/awt/windows/WInputMethod");
4139         DASSERT(wInputMethodClsLocal);
4140         CHECK_NULL(wInputMethodClsLocal);
4141         wInputMethodCls = (jclass)env->NewGlobalRef(wInputMethodClsLocal);
4142         env->DeleteLocalRef(wInputMethodClsLocal);
4143     }
4144 
4145     // get method ID of sendInputMethodEvent() (run only once)
4146     static jmethodID inqCandPosMid = 0;
4147     if (inqCandPosMid == 0) {
4148         inqCandPosMid =  env->GetMethodID(wInputMethodCls, "inquireCandidatePosition", "()V");
4149         DASSERT(!safe_ExceptionOccurred(env));
4150         DASSERT(inqCandPosMid);
4151         CHECK_NULL(inqCandPosMid);
4152     }
4153 
4154     // call m_InputMethod.sendInputMethod()
4155     jobject candPos = env->CallObjectMethod(m_InputMethod, inqCandPosMid);
4156     DASSERT(!safe_ExceptionOccurred(env));
4157 }
4158 
ImmGetHWnd()4159 HWND AwtComponent::ImmGetHWnd()
4160 {
4161     HWND proxy = GetProxyFocusOwner();
4162     return (proxy != NULL) ? proxy : GetHWnd();
4163 }
4164 
ImmAssociateContext(HIMC himc)4165 HIMC AwtComponent::ImmAssociateContext(HIMC himc)
4166 {
4167     return ::ImmAssociateContext(ImmGetHWnd(), himc);
4168 }
4169 
GetProxyFocusOwner()4170 HWND AwtComponent::GetProxyFocusOwner()
4171 {
4172     AwtWindow *window = GetContainer();
4173     if (window != 0) {
4174         AwtFrame *owner = window->GetOwningFrameOrDialog();
4175         if (owner != 0) {
4176             return owner->GetProxyFocusOwner();
4177         } else if (!window->IsSimpleWindow()) { // isn't an owned simple window
4178             return ((AwtFrame*)window)->GetProxyFocusOwner();
4179         }
4180     }
4181     return (HWND)NULL;
4182 }
4183 
4184 /* Redirects message to the focus proxy, if any */
CallProxyDefWindowProc(UINT message,WPARAM wParam,LPARAM lParam,LRESULT & retVal,MsgRouting & mr)4185 void AwtComponent::CallProxyDefWindowProc(UINT message, WPARAM wParam,
4186     LPARAM lParam, LRESULT &retVal, MsgRouting &mr)
4187 {
4188     if (mr != mrConsume)  {
4189         HWND proxy = GetProxyFocusOwner();
4190         if (proxy != NULL && ::IsWindowEnabled(proxy)) {
4191             retVal = ::DefWindowProc(proxy, message, wParam, lParam);
4192             mr = mrConsume;
4193         }
4194     }
4195 }
4196 
WmCommand(UINT id,HWND hWndChild,UINT notifyCode)4197 MsgRouting AwtComponent::WmCommand(UINT id, HWND hWndChild, UINT notifyCode)
4198 {
4199     /* Menu/Accelerator */
4200     if (hWndChild == 0) {
4201         AwtObject* obj = AwtToolkit::GetInstance().LookupCmdID(id);
4202         if (obj == NULL) {
4203             return mrConsume;
4204         }
4205         DASSERT(((AwtMenuItem*)obj)->GetID() == id);
4206         obj->DoCommand();
4207         return mrConsume;
4208     }
4209     /* Child id notification */
4210     else {
4211         AwtComponent* child = AwtComponent::GetComponent(hWndChild);
4212         if (child) {
4213             child->WmNotify(notifyCode);
4214         }
4215     }
4216     return mrDoDefault;
4217 }
4218 
WmNotify(UINT notifyCode)4219 MsgRouting AwtComponent::WmNotify(UINT notifyCode)
4220 {
4221     return mrDoDefault;
4222 }
4223 
WmCompareItem(UINT ctrlId,COMPAREITEMSTRUCT & compareInfo,LRESULT & result)4224 MsgRouting AwtComponent::WmCompareItem(UINT ctrlId,
4225                                        COMPAREITEMSTRUCT &compareInfo,
4226                                        LRESULT &result)
4227 {
4228     AwtComponent* child = AwtComponent::GetComponent(compareInfo.hwndItem);
4229     if (child == this) {
4230         /* DoCallback("handleItemDelete", */
4231     }
4232     else if (child) {
4233         return child->WmCompareItem(ctrlId, compareInfo, result);
4234     }
4235     return mrConsume;
4236 }
4237 
WmDeleteItem(UINT ctrlId,DELETEITEMSTRUCT & deleteInfo)4238 MsgRouting AwtComponent::WmDeleteItem(UINT ctrlId,
4239                                       DELETEITEMSTRUCT &deleteInfo)
4240 {
4241     /*
4242      * Workaround for NT 4.0 bug -- if SetWindowPos is called on a AwtList
4243      * window, a WM_DELETEITEM message is sent to its parent with a window
4244      * handle of one of the list's child windows.  The property lookup
4245      * succeeds, but the HWNDs don't match.
4246      */
4247     if (deleteInfo.hwndItem == NULL) {
4248         return mrConsume;
4249     }
4250     AwtComponent* child = (AwtComponent *)AwtComponent::GetComponent(deleteInfo.hwndItem);
4251 
4252     if (child && child->GetHWnd() != deleteInfo.hwndItem) {
4253         return mrConsume;
4254     }
4255 
4256     if (child == this) {
4257         /*DoCallback("handleItemDelete", */
4258     }
4259     else if (child) {
4260         return child->WmDeleteItem(ctrlId, deleteInfo);
4261     }
4262     return mrConsume;
4263 }
4264 
WmDrawItem(UINT ctrlId,DRAWITEMSTRUCT & drawInfo)4265 MsgRouting AwtComponent::WmDrawItem(UINT ctrlId, DRAWITEMSTRUCT &drawInfo)
4266 {
4267     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4268 
4269     if (drawInfo.CtlType == ODT_MENU) {
4270         if (IsMenu((HMENU)drawInfo.hwndItem) && drawInfo.itemData != 0) {
4271             AwtMenu* menu = (AwtMenu*)(drawInfo.itemData);
4272             menu->DrawItem(drawInfo);
4273         }
4274     } else {
4275         return OwnerDrawItem(ctrlId, drawInfo);
4276     }
4277     return mrConsume;
4278 }
4279 
WmMeasureItem(UINT ctrlId,MEASUREITEMSTRUCT & measureInfo)4280 MsgRouting AwtComponent::WmMeasureItem(UINT ctrlId,
4281                                        MEASUREITEMSTRUCT &measureInfo)
4282 {
4283     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4284 
4285     if (measureInfo.CtlType == ODT_MENU) {
4286         if (measureInfo.itemData != 0) {
4287             AwtMenu* menu = (AwtMenu*)(measureInfo.itemData);
4288             HDC hDC = ::GetDC(GetHWnd());
4289             /* menu->MeasureItem(env, hDC, measureInfo); */
4290             menu->MeasureItem(hDC, measureInfo);
4291             ::ReleaseDC(GetHWnd(), hDC);
4292         }
4293     } else {
4294         return OwnerMeasureItem(ctrlId, measureInfo);
4295     }
4296     return mrConsume;
4297 }
4298 
OwnerDrawItem(UINT ctrlId,DRAWITEMSTRUCT & drawInfo)4299 MsgRouting AwtComponent::OwnerDrawItem(UINT ctrlId,
4300     DRAWITEMSTRUCT &drawInfo)
4301 {
4302     AwtComponent* child = AwtComponent::GetComponent(drawInfo.hwndItem);
4303     if (child == this) {
4304         /* DoCallback("handleItemDelete", */
4305     } else if (child != NULL) {
4306         return child->WmDrawItem(ctrlId, drawInfo);
4307     }
4308     return mrConsume;
4309 }
4310 
OwnerMeasureItem(UINT ctrlId,MEASUREITEMSTRUCT & measureInfo)4311 MsgRouting AwtComponent::OwnerMeasureItem(UINT ctrlId,
4312     MEASUREITEMSTRUCT &measureInfo)
4313 {
4314     HWND  hChild = ::GetDlgItem(GetHWnd(), measureInfo.CtlID);
4315     AwtComponent* child = AwtComponent::GetComponent(hChild);
4316     /*
4317      * If the parent cannot find the child's instance from its handle,
4318      * maybe the child is in its creation.  So the child must be searched
4319      * from the list linked before the child's creation.
4320      */
4321     if (child == NULL) {
4322         child = SearchChild((UINT)ctrlId);
4323     }
4324 
4325     if (child == this) {
4326     /* DoCallback("handleItemDelete",  */
4327     }
4328     else if (child) {
4329         return child->WmMeasureItem(ctrlId, measureInfo);
4330     }
4331     return mrConsume;
4332 }
4333 
4334 /* for WmDrawItem method of Label, Button and Checkbox */
DrawWindowText(HDC hDC,jobject font,jstring text,int x,int y)4335 void AwtComponent::DrawWindowText(HDC hDC, jobject font, jstring text,
4336                                   int x, int y)
4337 {
4338     int nOldBkMode = ::SetBkMode(hDC,TRANSPARENT);
4339     DASSERT(nOldBkMode != 0);
4340     AwtFont::drawMFString(hDC, font, text, x, y, GetCodePage());
4341     VERIFY(::SetBkMode(hDC,nOldBkMode));
4342 }
4343 
4344 /*
4345  * Draw text in gray (the color being set to COLOR_GRAYTEXT) when the
4346  * component is disabled.  Used only for label, checkbox and button in
4347  * OWNER_DRAW.  It draws the text in emboss.
4348  */
DrawGrayText(HDC hDC,jobject font,jstring text,int x,int y)4349 void AwtComponent::DrawGrayText(HDC hDC, jobject font, jstring text,
4350                                 int x, int y)
4351 {
4352     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNHILIGHT));
4353     AwtComponent::DrawWindowText(hDC, font, text, x+1, y+1);
4354     ::SetTextColor(hDC, ::GetSysColor(COLOR_BTNSHADOW));
4355     AwtComponent::DrawWindowText(hDC, font, text, x, y);
4356 }
4357 
4358 /* for WmMeasureItem method of List and Choice */
GetItemString(JNIEnv * env,jobject target,jint index)4359 jstring AwtComponent::GetItemString(JNIEnv *env, jobject target, jint index)
4360 {
4361     jstring str = (jstring)JNU_CallMethodByName(env, NULL, target, "getItemImpl",
4362                                                 "(I)Ljava/lang/String;",
4363                                                 index).l;
4364     DASSERT(!safe_ExceptionOccurred(env));
4365     return str;
4366 }
4367 
4368 /* for WmMeasureItem method of List and Choice */
MeasureListItem(JNIEnv * env,MEASUREITEMSTRUCT & measureInfo)4369 void AwtComponent::MeasureListItem(JNIEnv *env,
4370                                    MEASUREITEMSTRUCT &measureInfo)
4371 {
4372     if (env->EnsureLocalCapacity(1) < 0) {
4373         return;
4374     }
4375     jobject dimension = PreferredItemSize(env);
4376     DASSERT(dimension);
4377     measureInfo.itemWidth =
4378       env->GetIntField(dimension, AwtDimension::widthID);
4379     measureInfo.itemHeight =
4380       env->GetIntField(dimension, AwtDimension::heightID);
4381     env->DeleteLocalRef(dimension);
4382 }
4383 
4384 /* for WmDrawItem method of List and Choice */
DrawListItem(JNIEnv * env,DRAWITEMSTRUCT & drawInfo)4385 void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
4386 {
4387     if (env->EnsureLocalCapacity(3) < 0) {
4388         return;
4389     }
4390     jobject peer = GetPeer(env);
4391     jobject target = env->GetObjectField(peer, AwtObject::targetID);
4392 
4393     HDC hDC = drawInfo.hDC;
4394     RECT rect = drawInfo.rcItem;
4395 
4396     BOOL bEnabled = isEnabled();
4397     BOOL unfocusableChoice = (drawInfo.itemState & ODS_COMBOBOXEDIT) && !IsFocusable();
4398     DWORD crBack, crText;
4399     if (drawInfo.itemState & ODS_SELECTED){
4400         /* Set background and text colors for selected item */
4401         crBack = ::GetSysColor (COLOR_HIGHLIGHT);
4402         crText = ::GetSysColor (COLOR_HIGHLIGHTTEXT);
4403     } else {
4404         /* Set background and text colors for unselected item */
4405         crBack = GetBackgroundColor();
4406         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4407     }
4408     if (unfocusableChoice) {
4409         //6190728. Shouldn't draw selection field (edit control) of an owner-drawn combo box.
4410         crBack = GetBackgroundColor();
4411         crText = bEnabled ? GetColor() : ::GetSysColor(COLOR_GRAYTEXT);
4412     }
4413 
4414     /* Fill item rectangle with background color */
4415     HBRUSH hbrBack = ::CreateSolidBrush (crBack);
4416     DASSERT(hbrBack);
4417     /* 6190728. Shouldn't draw any kind of rectangle around selection field
4418      * (edit control) of an owner-drawn combo box while unfocusable
4419      */
4420     if (!unfocusableChoice){
4421         VERIFY(::FillRect (hDC, &rect, hbrBack));
4422     }
4423     VERIFY(::DeleteObject (hbrBack));
4424 
4425     /* Set current background and text colors */
4426     ::SetBkColor (hDC, crBack);
4427     ::SetTextColor (hDC, crText);
4428 
4429     /*draw string (with left margin of 1 point) */
4430     if ((int) (drawInfo.itemID) >= 0) {
4431             jobject font = GET_FONT(target, peer);
4432             jstring text = GetItemString(env, target, drawInfo.itemID);
4433             if (env->ExceptionCheck()) {
4434                 env->DeleteLocalRef(font);
4435                 env->DeleteLocalRef(target);
4436                 return;
4437             }
4438             SIZE size = AwtFont::getMFStringSize(hDC, font, text);
4439             AwtFont::drawMFString(hDC, font, text,
4440                                   (GetRTL()) ? rect.right - size.cx - 1
4441                                              : rect.left + 1,
4442                                   (rect.top + rect.bottom - size.cy) / 2,
4443                                   GetCodePage());
4444             env->DeleteLocalRef(font);
4445             env->DeleteLocalRef(text);
4446     }
4447     if ((drawInfo.itemState & ODS_FOCUS)  &&
4448         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
4449       if (!unfocusableChoice){
4450           VERIFY(::DrawFocusRect(hDC, &rect));
4451       }
4452     }
4453     env->DeleteLocalRef(target);
4454 }
4455 
4456 /* for MeasureListItem method and WmDrawItem method of Checkbox */
GetFontHeight(JNIEnv * env)4457 jint AwtComponent::GetFontHeight(JNIEnv *env)
4458 {
4459     if (env->EnsureLocalCapacity(4) < 0) {
4460         return NULL;
4461     }
4462     jobject self = GetPeer(env);
4463     jobject target = env->GetObjectField(self, AwtObject::targetID);
4464 
4465     jobject font = GET_FONT(target, self);
4466     jobject toolkit = env->CallObjectMethod(target,
4467                                             AwtComponent::getToolkitMID);
4468 
4469     DASSERT(!safe_ExceptionOccurred(env));
4470 
4471     jobject fontMetrics =
4472         env->CallObjectMethod(toolkit, AwtToolkit::getFontMetricsMID, font);
4473 
4474     DASSERT(!safe_ExceptionOccurred(env));
4475 
4476     jint height = env->CallIntMethod(fontMetrics, AwtFont::getHeightMID);
4477     DASSERT(!safe_ExceptionOccurred(env));
4478 
4479     env->DeleteLocalRef(target);
4480     env->DeleteLocalRef(font);
4481     env->DeleteLocalRef(toolkit);
4482     env->DeleteLocalRef(fontMetrics);
4483 
4484     return height;
4485 }
4486 
4487 // If you override WmPrint, make sure to save a copy of the DC on the GDI
4488 // stack to be restored in WmPrintClient. Windows mangles the DC in
4489 // ::DefWindowProc.
WmPrint(HDC hDC,LPARAM flags)4490 MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags)
4491 {
4492     /*
4493      * DefWindowProc for WM_PRINT changes DC parameters, so we have
4494      * to restore it ourselves. Otherwise it will cause problems
4495      * when several components are printed to the same DC.
4496      */
4497     int nOriginalDC = ::SaveDC(hDC);
4498     DASSERT(nOriginalDC != 0);
4499 
4500     if (flags & PRF_NONCLIENT) {
4501 
4502         VERIFY(::SaveDC(hDC));
4503 
4504         DefWindowProc(WM_PRINT, (WPARAM)hDC,
4505                       (flags & (PRF_NONCLIENT
4506                                 | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4507 
4508         VERIFY(::RestoreDC(hDC, -1));
4509 
4510         // Special case for components with a sunken border. Windows does not
4511         // print the border correctly on PCL printers, so we have to do it ourselves.
4512         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4513             RECT r;
4514             VERIFY(::GetWindowRect(GetHWnd(), &r));
4515             VERIFY(::OffsetRect(&r, -r.left, -r.top));
4516             VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT));
4517         }
4518     }
4519 
4520     if (flags & PRF_CLIENT) {
4521 
4522         /*
4523          * Special case for components with a sunken border.
4524          * Windows prints a client area without offset to a border width.
4525          * We will first print the non-client area with the original offset,
4526          * then the client area with a corrected offset.
4527          */
4528         if (GetStyleEx() & WS_EX_CLIENTEDGE) {
4529 
4530             int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE);
4531             int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE);
4532 
4533             VERIFY(::OffsetWindowOrgEx(hDC, -nEdgeWidth, -nEdgeHeight, NULL));
4534 
4535             // Save a copy of the DC for WmPrintClient
4536             VERIFY(::SaveDC(hDC));
4537 
4538             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4539                           (flags & (PRF_CLIENT
4540                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4541 
4542             VERIFY(::OffsetWindowOrgEx(hDC, nEdgeWidth, nEdgeHeight, NULL));
4543 
4544         } else {
4545 
4546             // Save a copy of the DC for WmPrintClient
4547             VERIFY(::SaveDC(hDC));
4548             DefWindowProc(WM_PRINT, (WPARAM) hDC,
4549                           (flags & (PRF_CLIENT
4550                                     | PRF_CHECKVISIBLE | PRF_ERASEBKGND)));
4551         }
4552     }
4553 
4554     if (flags & (PRF_CHILDREN | PRF_OWNED)) {
4555         DefWindowProc(WM_PRINT, (WPARAM) hDC,
4556                       (flags & ~PRF_CLIENT & ~PRF_NONCLIENT));
4557     }
4558 
4559     VERIFY(::RestoreDC(hDC, nOriginalDC));
4560 
4561     return mrConsume;
4562 }
4563 
4564 // If you override WmPrintClient, make sure to obtain a valid copy of
4565 // the DC from the GDI stack. The copy of the DC should have been placed
4566 // there by WmPrint. Windows mangles the DC in ::DefWindowProc.
WmPrintClient(HDC hDC,LPARAM)4567 MsgRouting AwtComponent::WmPrintClient(HDC hDC, LPARAM)
4568 {
4569     // obtain valid DC from GDI stack
4570     ::RestoreDC(hDC, -1);
4571 
4572     return mrDoDefault;
4573 }
4574 
WmNcCalcSize(BOOL fCalcValidRects,LPNCCALCSIZE_PARAMS lpncsp,LRESULT & retVal)4575 MsgRouting AwtComponent::WmNcCalcSize(BOOL fCalcValidRects,
4576                                       LPNCCALCSIZE_PARAMS lpncsp,
4577                                       LRESULT &retVal)
4578 {
4579     return mrDoDefault;
4580 }
4581 
WmNcPaint(HRGN hrgn)4582 MsgRouting AwtComponent::WmNcPaint(HRGN hrgn)
4583 {
4584     return mrDoDefault;
4585 }
4586 
WmNcHitTest(UINT x,UINT y,LRESULT & retVal)4587 MsgRouting AwtComponent::WmNcHitTest(UINT x, UINT y, LRESULT &retVal)
4588 {
4589     return mrDoDefault;
4590 }
4591 
4592 /**
4593  * WmQueryNewPalette is called whenever our component is coming to
4594  * the foreground; this gives us an opportunity to install our
4595  * custom palette.  If this install actually changes entries in
4596  * the system palette, then we get a further call to WmPaletteChanged
4597  * (but note that we only need to realize our palette once).
4598  */
WmQueryNewPalette(LRESULT & retVal)4599 MsgRouting AwtComponent::WmQueryNewPalette(LRESULT &retVal)
4600 {
4601     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4602     m_QueryNewPaletteCalled = TRUE;
4603     HDC hDC = ::GetDC(GetHWnd());
4604     DASSERT(hDC);
4605     AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4606     AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4607     ::ReleaseDC(GetHWnd(), hDC);
4608     // We must realize the palettes of all of our DC's
4609     // There is sometimes a problem where the realization of
4610     // our temporary hDC here does not actually do what
4611     // we want.  Not clear why, but presumably fallout from
4612     // our use of several simultaneous hDC's.
4613     activeDCList.RealizePalettes(screen);
4614     // Do not invalidate here; if the palette
4615     // has not changed we will get an extra repaint
4616     retVal = TRUE;
4617 
4618     return mrDoDefault;
4619 }
4620 
4621 /**
4622  * We should not need to track this event since we handle our
4623  * palette management effectively in the WmQueryNewPalette and
4624  * WmPaletteChanged methods.  However, there seems to be a bug
4625  * on some win32 systems (e.g., NT4) whereby the palette
4626  * immediately after a displayChange is not yet updated to its
4627  * final post-display-change values (hence we adjust our palette
4628  * using the wrong system palette entries), then the palette is
4629  * updated, but a WM_PALETTECHANGED message is never sent.
4630  * By tracking the ISCHANGING message as well (and by tracking
4631  * displayChange events in the AwtToolkit object), we can account
4632  * for this error by forcing our WmPaletteChanged method to be
4633  * called and thereby realizing our logical palette and updating
4634  * our dynamic colorModel object.
4635  */
WmPaletteIsChanging(HWND hwndPalChg)4636 MsgRouting AwtComponent::WmPaletteIsChanging(HWND hwndPalChg)
4637 {
4638     if (AwtToolkit::GetInstance().HasDisplayChanged()) {
4639         WmPaletteChanged(hwndPalChg);
4640         AwtToolkit::GetInstance().ResetDisplayChanged();
4641     }
4642     return mrDoDefault;
4643 }
4644 
WmPaletteChanged(HWND hwndPalChg)4645 MsgRouting AwtComponent::WmPaletteChanged(HWND hwndPalChg)
4646 {
4647     // We need to re-realize our palette here (unless we're the one
4648     // that was realizing it in the first place).  That will let us match the
4649     // remaining colors in the system palette as best we can.  We always
4650     // invalidate because the palette will have changed when we receive this
4651     // message.
4652 
4653     int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd());
4654     if (hwndPalChg != GetHWnd()) {
4655         HDC hDC = ::GetDC(GetHWnd());
4656         DASSERT(hDC);
4657         AwtWin32GraphicsDevice::SelectPalette(hDC, screen);
4658         AwtWin32GraphicsDevice::RealizePalette(hDC, screen);
4659         ::ReleaseDC(GetHWnd(), hDC);
4660         // We must realize the palettes of all of our DC's
4661         activeDCList.RealizePalettes(screen);
4662     }
4663     if (AwtWin32GraphicsDevice::UpdateSystemPalette(screen)) {
4664         AwtWin32GraphicsDevice::UpdateDynamicColorModel(screen);
4665     }
4666     Invalidate(NULL);
4667     return mrDoDefault;
4668 }
4669 
WmStyleChanged(int wStyleType,LPSTYLESTRUCT lpss)4670 MsgRouting AwtComponent::WmStyleChanged(int wStyleType, LPSTYLESTRUCT lpss)
4671 {
4672     DASSERT(!IsBadReadPtr(lpss, sizeof(STYLESTRUCT)));
4673     return mrDoDefault;
4674 }
4675 
WmSettingChange(UINT wFlag,LPCTSTR pszSection)4676 MsgRouting AwtComponent::WmSettingChange(UINT wFlag, LPCTSTR pszSection)
4677 {
4678     DASSERT(!IsBadStringPtr(pszSection, 20));
4679     DTRACE_PRINTLN2("WM_SETTINGCHANGE: wFlag=%d pszSection=%s", (int)wFlag, pszSection);
4680     return mrDoDefault;
4681 }
4682 
GetDCFromComponent()4683 HDC AwtComponent::GetDCFromComponent()
4684 {
4685     GetDCReturnStruct *hdcStruct =
4686         (GetDCReturnStruct*)SendMessage(WM_AWT_GETDC);
4687     HDC hdc;
4688     if (hdcStruct) {
4689         if (hdcStruct->gdiLimitReached) {
4690             if (jvm != NULL) {
4691                 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4692                 if (env != NULL && !safe_ExceptionOccurred(env)) {
4693                     JNU_ThrowByName(env, "java/awt/AWTError",
4694                         "HDC creation failure - " \
4695                         "exceeded maximum GDI resources");
4696                 }
4697             }
4698         }
4699         hdc = hdcStruct->hDC;
4700         delete hdcStruct;
4701     } else {
4702         hdc = NULL;
4703     }
4704     return hdc;
4705 }
4706 
FillBackground(HDC hMemoryDC,SIZE & size)4707 void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size)
4708 {
4709     RECT eraseR = { 0, 0, size.cx, size.cy };
4710     VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
4711 }
4712 
FillAlpha(void * bitmapBits,SIZE & size,BYTE alpha)4713 void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
4714 {
4715     if (!bitmapBits) {
4716         return;
4717     }
4718 
4719     DWORD* dest = (DWORD*)bitmapBits;
4720     //XXX: might be optimized to use one loop (cy*cx -> 0)
4721     for (int i = 0; i < size.cy; i++ ) {
4722         for (int j = 0; j < size.cx; j++ ) {
4723             ((BYTE*)(dest++))[3] = alpha;
4724         }
4725     }
4726 }
4727 
CreatePrintedPixels(SIZE & loc,SIZE & size,int alpha)4728 jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
4729     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4730 
4731     if (!::IsWindowVisible(GetHWnd())) {
4732         return NULL;
4733     }
4734 
4735     HDC hdc = GetDCFromComponent();
4736     if (!hdc) {
4737         return NULL;
4738     }
4739     HDC hMemoryDC = ::CreateCompatibleDC(hdc);
4740     void *bitmapBits = NULL;
4741     HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
4742     HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
4743     SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
4744 
4745     FillBackground(hMemoryDC, size);
4746 
4747     VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
4748 
4749     // Don't bother with PRF_CHECKVISIBLE because we called IsWindowVisible
4750     // above.
4751     SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
4752 
4753     // First make sure the system completed any drawing to the bitmap.
4754     ::GdiFlush();
4755 
4756     // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
4757     // leaving it equal to zero. Hence we need to fill it manually. Otherwise
4758     // the pixels will be considered transparent when interpreting the data.
4759     FillAlpha(bitmapBits, size, alpha);
4760 
4761     ::SelectObject(hMemoryDC, hOldBitmap);
4762 
4763     BITMAPINFO bmi;
4764     memset(&bmi, 0, sizeof(BITMAPINFO));
4765     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
4766     bmi.bmiHeader.biWidth = size.cx;
4767     bmi.bmiHeader.biHeight = -size.cy;
4768     bmi.bmiHeader.biPlanes = 1;
4769     bmi.bmiHeader.biBitCount = 32;
4770     bmi.bmiHeader.biCompression = BI_RGB;
4771 
4772     jobject localPixelArray = env->NewIntArray(size.cx * size.cy);
4773     jintArray pixelArray = NULL;
4774     if (localPixelArray != NULL) {
4775         pixelArray = (jintArray)env->NewGlobalRef(localPixelArray);
4776         env->DeleteLocalRef(localPixelArray); localPixelArray = NULL;
4777 
4778         jboolean isCopy;
4779         jint *pixels = env->GetIntArrayElements(pixelArray, &isCopy);
4780 
4781         ::GetDIBits(hMemoryDC, hBitmap, 0, size.cy, (LPVOID)pixels, &bmi,
4782                     DIB_RGB_COLORS);
4783 
4784         env->ReleaseIntArrayElements(pixelArray, pixels, 0);
4785     }
4786 
4787     VERIFY(::DeleteObject(hBitmap));
4788     VERIFY(::DeleteDC(hMemoryDC));
4789 
4790     return pixelArray;
4791 }
4792 
SetNativeFocusOwner(void * self)4793 void* AwtComponent::SetNativeFocusOwner(void *self) {
4794     if (self == NULL) {
4795         // It means that the KFM wants to set focus to null
4796         sm_focusOwner = NULL;
4797         return NULL;
4798     }
4799 
4800     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4801 
4802     AwtComponent *c = NULL;
4803     jobject peer = (jobject)self;
4804 
4805     PDATA pData;
4806     JNI_CHECK_NULL_GOTO(peer, "peer", ret);
4807     pData = JNI_GET_PDATA(peer);
4808     if (pData == NULL) {
4809         goto ret;
4810     }
4811     c = (AwtComponent *)pData;
4812 
4813 ret:
4814     if (c && ::IsWindow(c->GetHWnd())) {
4815         sm_focusOwner = c->GetHWnd();
4816     } else {
4817         sm_focusOwner = NULL;
4818     }
4819     env->DeleteGlobalRef(peer);
4820     return NULL;
4821 }
4822 
GetNativeFocusedWindow()4823 void* AwtComponent::GetNativeFocusedWindow() {
4824     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4825     AwtComponent *comp =
4826         AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
4827     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4828 }
4829 
GetNativeFocusOwner()4830 void* AwtComponent::GetNativeFocusOwner() {
4831     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4832     AwtComponent *comp =
4833         AwtComponent::GetComponent(AwtComponent::sm_focusOwner);
4834     return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
4835 }
4836 
SearchChild(UINT id)4837 AwtComponent* AwtComponent::SearchChild(UINT id) {
4838     ChildListItem* child;
4839     for (child = m_childList; child != NULL;child = child->m_next) {
4840         if (child->m_ID == id)
4841             return child->m_Component;
4842     }
4843     /*
4844      * DASSERT(FALSE);
4845      * This should not be happend if all children are recorded
4846      */
4847     return NULL;        /* make compiler happy */
4848 }
4849 
RemoveChild(UINT id)4850 void AwtComponent::RemoveChild(UINT id) {
4851     ChildListItem* child = m_childList;
4852     ChildListItem* lastChild = NULL;
4853     while (child != NULL) {
4854         if (child->m_ID == id) {
4855             if (lastChild == NULL) {
4856                 m_childList = child->m_next;
4857             } else {
4858                 lastChild->m_next = child->m_next;
4859             }
4860             child->m_next = NULL;
4861             DASSERT(child != NULL);
4862             delete child;
4863             return;
4864         }
4865         lastChild = child;
4866         child = child->m_next;
4867     }
4868 }
4869 
SendKeyEvent(jint id,jlong when,jint raw,jint cooked,jint modifiers,jint keyLocation,jlong nativeCode,MSG * pMsg)4870 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
4871                                 jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
4872 {
4873     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4874     CriticalSection::Lock l(GetLock());
4875     if (GetPeer(env) == NULL) {
4876         /* event received during termination. */
4877         return;
4878     }
4879 
4880     static jclass keyEventCls;
4881     if (keyEventCls == NULL) {
4882         jclass keyEventClsLocal = env->FindClass("java/awt/event/KeyEvent");
4883         DASSERT(keyEventClsLocal);
4884         if (keyEventClsLocal == NULL) {
4885             /* exception already thrown */
4886             return;
4887         }
4888         keyEventCls = (jclass)env->NewGlobalRef(keyEventClsLocal);
4889         env->DeleteLocalRef(keyEventClsLocal);
4890     }
4891 
4892     static jmethodID keyEventConst;
4893     if (keyEventConst == NULL) {
4894         keyEventConst =  env->GetMethodID(keyEventCls, "<init>",
4895                                           "(Ljava/awt/Component;IJIICI)V");
4896         DASSERT(keyEventConst);
4897         CHECK_NULL(keyEventConst);
4898     }
4899     if (env->EnsureLocalCapacity(2) < 0) {
4900         return;
4901     }
4902     jobject target = GetTarget(env);
4903     jobject keyEvent = env->NewObject(keyEventCls, keyEventConst, target,
4904                                       id, when, modifiers, raw, cooked,
4905                                       keyLocation);
4906     if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
4907     DASSERT(!safe_ExceptionOccurred(env));
4908     DASSERT(keyEvent != NULL);
4909     if (keyEvent == NULL) {
4910         env->DeleteLocalRef(target);
4911         return;
4912     }
4913     env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
4914     if( nativeCode && nativeCode < 256 ) {
4915         env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
4916         env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
4917         if( nativeCode < 255 ) {
4918             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
4919         }else if( pMsg != NULL ) {
4920             // unknown key with virtual keycode 0xFF.
4921             // Its scancode is not in the table, pickup it from the message.
4922             env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
4923         }
4924     }
4925     if (pMsg != NULL) {
4926         AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
4927     }
4928     SendEvent(keyEvent);
4929 
4930     env->DeleteLocalRef(keyEvent);
4931     env->DeleteLocalRef(target);
4932 }
4933 
4934 void
SendKeyEventToFocusOwner(jint id,jlong when,jint raw,jint cooked,jint modifiers,jint keyLocation,jlong nativeCode,MSG * msg)4935 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
4936                                        jint raw, jint cooked,
4937                                        jint modifiers, jint keyLocation,
4938                                        jlong nativeCode,
4939                                        MSG *msg)
4940 {
4941     /*
4942      * if focus owner is null, but focused window isn't
4943      * we will send key event to focused window
4944      */
4945     HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());
4946 
4947     if (hwndTarget == GetHWnd()) {
4948         SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
4949     } else {
4950         AwtComponent *target = NULL;
4951         if (hwndTarget != NULL) {
4952             target = AwtComponent::GetComponent(hwndTarget);
4953             if (target == NULL) {
4954                 target = this;
4955             }
4956         }
4957         if (target != NULL) {
4958             target->SendKeyEvent(id, when, raw, cooked, modifiers,
4959               keyLocation, nativeCode, msg);
4960         }
4961     }
4962 }
4963 
SetDragCapture(UINT flags)4964 void AwtComponent::SetDragCapture(UINT flags)
4965 {
4966     // don't want to interfere with other controls
4967     if (::GetCapture() == NULL) {
4968         ::SetCapture(GetHWnd());
4969     }
4970 }
4971 
ReleaseDragCapture(UINT flags)4972 void AwtComponent::ReleaseDragCapture(UINT flags)
4973 {
4974     if ((::GetCapture() == GetHWnd()) && ((flags & ALL_MK_BUTTONS) == 0)) {
4975         // user has released all buttons, so release the capture
4976         ::ReleaseCapture();
4977     }
4978 }
4979 
SendMouseEvent(jint id,jlong when,jint x,jint y,jint modifiers,jint clickCount,jboolean popupTrigger,jint button,MSG * pMsg,BOOL causedByTouchEvent)4980 void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
4981                                   jint modifiers, jint clickCount,
4982                                   jboolean popupTrigger, jint button,
4983                                   MSG *pMsg, BOOL causedByTouchEvent)
4984 {
4985     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
4986     CriticalSection::Lock l(GetLock());
4987     if (GetPeer(env) == NULL) {
4988         /* event received during termination. */
4989         return;
4990     }
4991 
4992     static jclass mouseEventCls;
4993     if (mouseEventCls == NULL) {
4994         jclass mouseEventClsLocal =
4995             env->FindClass("java/awt/event/MouseEvent");
4996         CHECK_NULL(mouseEventClsLocal);
4997         mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
4998         env->DeleteLocalRef(mouseEventClsLocal);
4999     }
5000     RECT insets;
5001     GetInsets(&insets);
5002 
5003     static jmethodID mouseEventConst;
5004     if (mouseEventConst == NULL) {
5005         mouseEventConst =
5006             env->GetMethodID(mouseEventCls, "<init>",
5007                  "(Ljava/awt/Component;IJIIIIIIZI)V");
5008         DASSERT(mouseEventConst);
5009         CHECK_NULL(mouseEventConst);
5010     }
5011     if (env->EnsureLocalCapacity(2) < 0) {
5012         return;
5013     }
5014     jobject target = GetTarget(env);
5015     DWORD curMousePos = ::GetMessagePos();
5016     int xAbs = GET_X_LPARAM(curMousePos);
5017     int yAbs = GET_Y_LPARAM(curMousePos);
5018     jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
5019                                         target,
5020                                         id, when, modifiers,
5021                                         x+insets.left, y+insets.top,
5022                                         xAbs, yAbs,
5023                                         clickCount, popupTrigger, button);
5024 
5025     if (safe_ExceptionOccurred(env)) {
5026         env->ExceptionDescribe();
5027         env->ExceptionClear();
5028     }
5029 
5030     DASSERT(mouseEvent != NULL);
5031     CHECK_NULL(mouseEvent);
5032     if (causedByTouchEvent) {
5033         env->SetBooleanField(mouseEvent, AwtMouseEvent::causedByTouchEventID,
5034             JNI_TRUE);
5035     }
5036     if (pMsg != 0) {
5037         AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
5038     }
5039     SendEvent(mouseEvent);
5040 
5041     env->DeleteLocalRef(mouseEvent);
5042     env->DeleteLocalRef(target);
5043 }
5044 
5045 void
SendMouseWheelEvent(jint id,jlong when,jint x,jint y,jint modifiers,jint clickCount,jboolean popupTrigger,jint scrollType,jint scrollAmount,jint roundedWheelRotation,jdouble preciseWheelRotation,MSG * pMsg)5046 AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y,
5047                                   jint modifiers, jint clickCount,
5048                                   jboolean popupTrigger, jint scrollType,
5049                                   jint scrollAmount, jint roundedWheelRotation,
5050                                   jdouble preciseWheelRotation, MSG *pMsg)
5051 {
5052     /* Code based not so loosely on AwtComponent::SendMouseEvent */
5053     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5054     CriticalSection::Lock l(GetLock());
5055     if (GetPeer(env) == NULL) {
5056         /* event received during termination. */
5057         return;
5058     }
5059 
5060     static jclass mouseWheelEventCls;
5061     if (mouseWheelEventCls == NULL) {
5062         jclass mouseWheelEventClsLocal =
5063             env->FindClass("java/awt/event/MouseWheelEvent");
5064         CHECK_NULL(mouseWheelEventClsLocal);
5065         mouseWheelEventCls = (jclass)env->NewGlobalRef(mouseWheelEventClsLocal);
5066         env->DeleteLocalRef(mouseWheelEventClsLocal);
5067     }
5068     RECT insets;
5069     GetInsets(&insets);
5070 
5071     static jmethodID mouseWheelEventConst;
5072     if (mouseWheelEventConst == NULL) {
5073         mouseWheelEventConst =
5074             env->GetMethodID(mouseWheelEventCls, "<init>",
5075                            "(Ljava/awt/Component;IJIIIIIIZIIID)V");
5076         DASSERT(mouseWheelEventConst);
5077         CHECK_NULL(mouseWheelEventConst);
5078     }
5079     if (env->EnsureLocalCapacity(2) < 0) {
5080         return;
5081     }
5082     jobject target = GetTarget(env);
5083     DTRACE_PRINTLN("creating MWE in JNI");
5084 
5085     jobject mouseWheelEvent = env->NewObject(mouseWheelEventCls,
5086                                              mouseWheelEventConst,
5087                                              target,
5088                                              id, when, modifiers,
5089                                              x+insets.left, y+insets.top,
5090                                              0, 0,
5091                                              clickCount, popupTrigger,
5092                                              scrollType, scrollAmount,
5093                                              roundedWheelRotation, preciseWheelRotation);
5094 
5095     DASSERT(mouseWheelEvent != NULL);
5096     if (mouseWheelEvent == NULL || safe_ExceptionOccurred(env)) {
5097         env->ExceptionDescribe();
5098         env->ExceptionClear();
5099         env->DeleteLocalRef(target);
5100         return;
5101     }
5102     if (pMsg != NULL) {
5103         AwtAWTEvent::saveMSG(env, pMsg, mouseWheelEvent);
5104     }
5105     SendEvent(mouseWheelEvent);
5106 
5107     env->DeleteLocalRef(mouseWheelEvent);
5108     env->DeleteLocalRef(target);
5109 }
5110 
SendFocusEvent(jint id,HWND opposite)5111 void AwtComponent::SendFocusEvent(jint id, HWND opposite)
5112 {
5113     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5114 
5115     CriticalSection::Lock l(GetLock());
5116     if (GetPeer(env) == NULL) {
5117         /* event received during termination. */
5118         return;
5119     }
5120 
5121     static jclass focusEventCls;
5122     if (focusEventCls == NULL) {
5123         jclass focusEventClsLocal
5124             = env->FindClass("java/awt/event/FocusEvent");
5125         DASSERT(focusEventClsLocal);
5126         CHECK_NULL(focusEventClsLocal);
5127         focusEventCls = (jclass)env->NewGlobalRef(focusEventClsLocal);
5128         env->DeleteLocalRef(focusEventClsLocal);
5129     }
5130 
5131     static jmethodID focusEventConst;
5132     if (focusEventConst == NULL) {
5133         focusEventConst =
5134             env->GetMethodID(focusEventCls, "<init>",
5135                              "(Ljava/awt/Component;IZLjava/awt/Component;)V");
5136         DASSERT(focusEventConst);
5137         CHECK_NULL(focusEventConst);
5138     }
5139 
5140     static jclass sequencedEventCls;
5141     if (sequencedEventCls == NULL) {
5142         jclass sequencedEventClsLocal =
5143             env->FindClass("java/awt/SequencedEvent");
5144         DASSERT(sequencedEventClsLocal);
5145         CHECK_NULL(sequencedEventClsLocal);
5146         sequencedEventCls =
5147             (jclass)env->NewGlobalRef(sequencedEventClsLocal);
5148         env->DeleteLocalRef(sequencedEventClsLocal);
5149     }
5150 
5151     static jmethodID sequencedEventConst;
5152     if (sequencedEventConst == NULL) {
5153         sequencedEventConst =
5154             env->GetMethodID(sequencedEventCls, "<init>",
5155                              "(Ljava/awt/AWTEvent;)V");
5156         DASSERT(sequencedEventConst);
5157         CHECK_NULL(sequencedEventConst);
5158     }
5159 
5160     if (env->EnsureLocalCapacity(3) < 0) {
5161         return;
5162     }
5163 
5164     jobject target = GetTarget(env);
5165     jobject jOpposite = NULL;
5166     if (opposite != NULL) {
5167         AwtComponent *awtOpposite = AwtComponent::GetComponent(opposite);
5168         if (awtOpposite != NULL) {
5169             jOpposite = awtOpposite->GetTarget(env);
5170         }
5171     }
5172     jobject focusEvent = env->NewObject(focusEventCls, focusEventConst,
5173                                         target, id, JNI_FALSE, jOpposite);
5174     DASSERT(!safe_ExceptionOccurred(env));
5175     DASSERT(focusEvent != NULL);
5176     if (jOpposite != NULL) {
5177         env->DeleteLocalRef(jOpposite); jOpposite = NULL;
5178     }
5179     env->DeleteLocalRef(target); target = NULL;
5180     CHECK_NULL(focusEvent);
5181 
5182     jobject sequencedEvent = env->NewObject(sequencedEventCls,
5183                                             sequencedEventConst,
5184                                             focusEvent);
5185     DASSERT(!safe_ExceptionOccurred(env));
5186     DASSERT(sequencedEvent != NULL);
5187     env->DeleteLocalRef(focusEvent); focusEvent = NULL;
5188     CHECK_NULL(sequencedEvent);
5189     SendEvent(sequencedEvent);
5190 
5191     env->DeleteLocalRef(sequencedEvent);
5192 }
5193 
5194 /*
5195  * Forward a filtered event directly to the subclassed window.
5196  * This method is needed so that DefWindowProc is invoked on the
5197  * component's owning thread.
5198  */
HandleEvent(MSG * msg,BOOL)5199 MsgRouting AwtComponent::HandleEvent(MSG *msg, BOOL)
5200 {
5201     DefWindowProc(msg->message, msg->wParam, msg->lParam);
5202     delete msg;
5203     return mrConsume;
5204 }
5205 
5206 /* Post a WM_AWT_HANDLE_EVENT message which invokes HandleEvent
5207    on the toolkit thread. This method may pre-filter the messages. */
PostHandleEventMessage(MSG * msg,BOOL synthetic)5208 BOOL AwtComponent::PostHandleEventMessage(MSG *msg, BOOL synthetic)
5209 {
5210     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5211     // We should cut off keyboard events to disabled components
5212     // to avoid the components responding visually to keystrokes when disabled.
5213     // we shouldn't cut off WM_SYS* messages as they aren't used for normal activity
5214     // but to activate menus, close windows, etc
5215     switch(msg->message) {
5216         case WM_KEYDOWN:
5217         case WM_KEYUP:
5218         case WM_CHAR:
5219         case WM_DEADCHAR:
5220             {
5221                 if (!isRecursivelyEnabled()) {
5222                     goto quit;
5223                 }
5224                 break;
5225             }
5226     }
5227     if (PostMessage(GetHWnd(), WM_AWT_HANDLE_EVENT,
5228         (WPARAM) synthetic, (LPARAM) msg)) {
5229             return TRUE;
5230     } else {
5231         JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5232     }
5233 quit:
5234     delete msg;
5235     return FALSE;
5236 }
5237 
SynthesizeKeyMessage(JNIEnv * env,jobject keyEvent)5238 void AwtComponent::SynthesizeKeyMessage(JNIEnv *env, jobject keyEvent)
5239 {
5240     jint id = (env)->GetIntField(keyEvent, AwtAWTEvent::idID);
5241     UINT message;
5242     switch (id) {
5243       case java_awt_event_KeyEvent_KEY_PRESSED:
5244           message = WM_KEYDOWN;
5245           break;
5246       case java_awt_event_KeyEvent_KEY_RELEASED:
5247           message = WM_KEYUP;
5248           break;
5249       case java_awt_event_KeyEvent_KEY_TYPED:
5250           message = WM_CHAR;
5251           break;
5252       default:
5253           return;
5254     }
5255 
5256     /*
5257      * KeyEvent.modifiers aren't supported -- the Java apppwd must send separate
5258      * KEY_PRESSED and KEY_RELEASED events for the modifier virtual keys.
5259      */
5260     if (id == java_awt_event_KeyEvent_KEY_TYPED) {
5261         // WM_CHAR message must be posted using WM_AWT_FORWARD_CHAR
5262         // (for Edit control)
5263         jchar keyChar = (jchar)
5264           (env)->GetCharField(keyEvent, AwtKeyEvent::keyCharID);
5265 
5266         // Bugid 4724007.  If it is a Delete character, don't send the fake
5267         // KEY_TYPED we created back to the native window: Windows doesn't
5268         // expect a WM_CHAR for Delete in TextFields, so it tries to enter a
5269         // character after deleting.
5270         if (keyChar == '\177') { // the Delete character
5271             return;
5272         }
5273 
5274         // Disable forwarding WM_CHAR messages to disabled components
5275         if (isRecursivelyEnabled()) {
5276             if (!::PostMessage(GetHWnd(), WM_AWT_FORWARD_CHAR,
5277                 MAKEWPARAM(keyChar, TRUE), 0)) {
5278                 JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5279             }
5280         }
5281     } else {
5282         jint keyCode =
5283           (env)->GetIntField(keyEvent, AwtKeyEvent::keyCodeID);
5284         UINT key, modifiers;
5285         AwtComponent::JavaKeyToWindowsKey(keyCode, &key, &modifiers);
5286         MSG* msg = CreateMessage(message, key, 0);
5287         PostHandleEventMessage(msg, TRUE);
5288     }
5289 }
5290 
SynthesizeMouseMessage(JNIEnv * env,jobject mouseEvent)5291 void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent)
5292 {
5293     /*    DebugBreak(); */
5294     jint button = (env)->GetIntField(mouseEvent, AwtMouseEvent::buttonID);
5295     jint modifiers = (env)->GetIntField(mouseEvent, AwtInputEvent::modifiersID);
5296 
5297     WPARAM wParam = 0;
5298     WORD wLow = 0;
5299     jint wheelAmt = 0;
5300     jint id = (env)->GetIntField(mouseEvent, AwtAWTEvent::idID);
5301     UINT message;
5302     switch (id) {
5303       case java_awt_event_MouseEvent_MOUSE_PRESSED: {
5304           switch (button) {
5305             case java_awt_event_MouseEvent_BUTTON1:
5306                 message = WM_LBUTTONDOWN; break;
5307             case java_awt_event_MouseEvent_BUTTON3:
5308                 message = WM_MBUTTONDOWN; break;
5309             case java_awt_event_MouseEvent_BUTTON2:
5310                 message = WM_RBUTTONDOWN; break;
5311             default:
5312                 return;
5313           }
5314           break;
5315       }
5316       case java_awt_event_MouseEvent_MOUSE_RELEASED: {
5317           switch (button) {
5318             case java_awt_event_MouseEvent_BUTTON1:
5319                 message = WM_LBUTTONUP; break;
5320             case java_awt_event_MouseEvent_BUTTON3:
5321                 message = WM_MBUTTONUP; break;
5322             case java_awt_event_MouseEvent_BUTTON2:
5323                 message = WM_RBUTTONUP; break;
5324             default:
5325                 return;
5326           }
5327           break;
5328       }
5329       case java_awt_event_MouseEvent_MOUSE_MOVED:
5330           /* MOUSE_DRAGGED events must first have sent a MOUSE_PRESSED event. */
5331       case java_awt_event_MouseEvent_MOUSE_DRAGGED:
5332           message = WM_MOUSEMOVE;
5333           break;
5334       case java_awt_event_MouseEvent_MOUSE_WHEEL:
5335           if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) {
5336               wLow |= MK_CONTROL;
5337           }
5338           if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) {
5339               wLow |= MK_SHIFT;
5340           }
5341           if (modifiers & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
5342               wLow |= MK_LBUTTON;
5343           }
5344           if (modifiers & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) {
5345               wLow |= MK_RBUTTON;
5346           }
5347           if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) {
5348               wLow |= MK_MBUTTON;
5349           }
5350           if (modifiers & X1_BUTTON) {
5351               wLow |= GetButtonMK(X1_BUTTON);
5352           }
5353           if (modifiers & X2_BUTTON) {
5354               wLow |= GetButtonMK(X2_BUTTON);
5355           }
5356 
5357           wheelAmt = (jint)JNU_CallMethodByName(env,
5358                                                NULL,
5359                                                mouseEvent,
5360                                                "getWheelRotation",
5361                                                "()I").i;
5362           DASSERT(!safe_ExceptionOccurred(env));
5363           JNU_CHECK_EXCEPTION(env);
5364           DTRACE_PRINTLN1("wheelAmt = %i\n", wheelAmt);
5365 
5366           // convert Java wheel amount value to Win32
5367           wheelAmt *= -1 * WHEEL_DELTA;
5368 
5369           message = WM_MOUSEWHEEL;
5370           wParam = MAKEWPARAM(wLow, wheelAmt);
5371 
5372           break;
5373       default:
5374           return;
5375     }
5376     jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID);
5377     jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID);
5378     MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y);
5379     PostHandleEventMessage(msg, TRUE);
5380 }
5381 
InheritsNativeMouseWheelBehavior()5382 BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;}
5383 
Invalidate(RECT * r)5384 void AwtComponent::Invalidate(RECT* r)
5385 {
5386     ::InvalidateRect(GetHWnd(), r, FALSE);
5387 }
5388 
BeginValidate()5389 void AwtComponent::BeginValidate()
5390 {
5391     DASSERT(m_validationNestCount >= 0 &&
5392            m_validationNestCount < 1000); // sanity check
5393 
5394     if (m_validationNestCount == 0) {
5395     // begin deferred window positioning if we're not inside
5396     // another Begin/EndValidate pair
5397         DASSERT(m_hdwp == NULL);
5398         m_hdwp = ::BeginDeferWindowPos(32);
5399     }
5400 
5401     m_validationNestCount++;
5402 }
5403 
EndValidate()5404 void AwtComponent::EndValidate()
5405 {
5406     DASSERT(m_validationNestCount > 0 &&
5407            m_validationNestCount < 1000); // sanity check
5408     DASSERT(m_hdwp != NULL);
5409 
5410     m_validationNestCount--;
5411     if (m_validationNestCount == 0) {
5412     // if this call to EndValidate is not nested inside another
5413     // Begin/EndValidate pair, end deferred window positioning
5414         ::EndDeferWindowPos(m_hdwp);
5415         m_hdwp = NULL;
5416     }
5417 }
5418 
5419 /**
5420  * HWND, AwtComponent and Java Peer interaction
5421  */
5422 
5423 /*
5424  *Link the C++, Java peer, and HWNDs together.
5425  */
LinkObjects(JNIEnv * env,jobject peer)5426 void AwtComponent::LinkObjects(JNIEnv *env, jobject peer)
5427 {
5428     /*
5429      * Bind all three objects together thru this C++ object, two-way to each:
5430      *     JavaPeer <-> C++ <-> HWND
5431      *
5432      * C++ -> JavaPeer
5433      */
5434     if (m_peerObject == NULL) {
5435         // This may have already been set up by CreateHWnd
5436         // And we don't want to create two references so we
5437         // will leave the prior one alone
5438         m_peerObject = env->NewGlobalRef(peer);
5439     }
5440     /* JavaPeer -> HWND */
5441     env->SetLongField(peer, AwtComponent::hwndID, reinterpret_cast<jlong>(m_hwnd));
5442 
5443     /* JavaPeer -> C++ */
5444     JNI_SET_PDATA(peer, this);
5445 
5446     /* HWND -> C++ */
5447     SetComponentInHWND();
5448 }
5449 
5450 /* Cleanup above linking */
UnlinkObjects()5451 void AwtComponent::UnlinkObjects()
5452 {
5453     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5454     if (m_peerObject) {
5455         env->SetLongField(m_peerObject, AwtComponent::hwndID, 0);
5456         JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
5457         JNI_SET_DESTROYED(m_peerObject);
5458         env->DeleteGlobalRef(m_peerObject);
5459         m_peerObject = NULL;
5460     }
5461 }
5462 
Enable(BOOL bEnable)5463 void AwtComponent::Enable(BOOL bEnable)
5464 {
5465     if (bEnable && IsTopLevel()) {
5466         // we should not enable blocked toplevels
5467         bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()));
5468     }
5469     // Shouldn't trigger native focus change
5470     // (only the proxy may be the native focus owner).
5471     ::EnableWindow(GetHWnd(), bEnable);
5472 
5473     CriticalSection::Lock l(GetLock());
5474     VerifyState();
5475 }
5476 
5477 /*
5478  * associate an AwtDropTarget with this AwtComponent
5479  */
5480 
CreateDropTarget(JNIEnv * env)5481 AwtDropTarget* AwtComponent::CreateDropTarget(JNIEnv* env) {
5482     m_dropTarget = new AwtDropTarget(env, this);
5483     m_dropTarget->RegisterTarget(TRUE);
5484     return m_dropTarget;
5485 }
5486 
5487 /*
5488  * disassociate an AwtDropTarget with this AwtComponent
5489  */
5490 
DestroyDropTarget()5491 void AwtComponent::DestroyDropTarget() {
5492     if (m_dropTarget != NULL) {
5493         m_dropTarget->RegisterTarget(FALSE);
5494         m_dropTarget->Release();
5495         m_dropTarget = NULL;
5496     }
5497 }
5498 
IsFocusingMouseMessage(MSG * pMsg)5499 BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) {
5500     return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK;
5501 }
5502 
IsFocusingKeyMessage(MSG * pMsg)5503 BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) {
5504     return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE;
5505 }
5506 
_Show(void * param)5507 void AwtComponent::_Show(void *param)
5508 {
5509     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5510 
5511     jobject self = (jobject)param;
5512 
5513     AwtComponent *p;
5514 
5515     PDATA pData;
5516     JNI_CHECK_PEER_GOTO(self, ret);
5517     p = (AwtComponent *)pData;
5518     if (::IsWindow(p->GetHWnd()))
5519     {
5520         p->SendMessage(WM_AWT_COMPONENT_SHOW);
5521     }
5522 ret:
5523     env->DeleteGlobalRef(self);
5524 }
5525 
_Hide(void * param)5526 void AwtComponent::_Hide(void *param)
5527 {
5528     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5529 
5530     jobject self = (jobject)param;
5531 
5532     AwtComponent *p;
5533 
5534     PDATA pData;
5535     JNI_CHECK_PEER_GOTO(self, ret);
5536     p = (AwtComponent *)pData;
5537     if (::IsWindow(p->GetHWnd()))
5538     {
5539         p->SendMessage(WM_AWT_COMPONENT_HIDE);
5540     }
5541 ret:
5542     env->DeleteGlobalRef(self);
5543 }
5544 
_Enable(void * param)5545 void AwtComponent::_Enable(void *param)
5546 {
5547     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5548 
5549     jobject self = (jobject)param;
5550 
5551     AwtComponent *p;
5552 
5553     PDATA pData;
5554     JNI_CHECK_PEER_GOTO(self, ret);
5555     p = (AwtComponent *)pData;
5556     if (::IsWindow(p->GetHWnd()))
5557     {
5558         p->Enable(TRUE);
5559     }
5560 ret:
5561     env->DeleteGlobalRef(self);
5562 }
5563 
_Disable(void * param)5564 void AwtComponent::_Disable(void *param)
5565 {
5566     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5567 
5568     jobject self = (jobject)param;
5569 
5570     AwtComponent *p;
5571 
5572     PDATA pData;
5573     JNI_CHECK_PEER_GOTO(self, ret);
5574     p = (AwtComponent *)pData;
5575     if (::IsWindow(p->GetHWnd()))
5576     {
5577         p->Enable(FALSE);
5578     }
5579 ret:
5580     env->DeleteGlobalRef(self);
5581 }
5582 
_GetLocationOnScreen(void * param)5583 jobject AwtComponent::_GetLocationOnScreen(void *param)
5584 {
5585     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5586 
5587     jobject self = (jobject)param;
5588 
5589     jobject result = NULL;
5590     AwtComponent *p;
5591 
5592     PDATA pData;
5593     JNI_CHECK_PEER_GOTO(self, ret);
5594     p = (AwtComponent *)pData;
5595     if (::IsWindow(p->GetHWnd()))
5596     {
5597         RECT rect;
5598         VERIFY(::GetWindowRect(p->GetHWnd(),&rect));
5599         result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V",
5600             rect.left, rect.top);
5601     }
5602 ret:
5603     env->DeleteGlobalRef(self);
5604 
5605     if (result != NULL)
5606     {
5607         jobject resultGlobalRef = env->NewGlobalRef(result);
5608         env->DeleteLocalRef(result);
5609         return resultGlobalRef;
5610     }
5611     else
5612     {
5613         return NULL;
5614     }
5615 }
5616 
_Reshape(void * param)5617 void AwtComponent::_Reshape(void *param)
5618 {
5619     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5620 
5621     ReshapeStruct *rs = (ReshapeStruct*)param;
5622     jobject self = rs->component;
5623     jint x = rs->x;
5624     jint y = rs->y;
5625     jint w = rs->w;
5626     jint h = rs->h;
5627 
5628     AwtComponent *p;
5629 
5630     PDATA pData;
5631     JNI_CHECK_PEER_GOTO(self, ret);
5632     p = (AwtComponent *)pData;
5633     if (::IsWindow(p->GetHWnd()))
5634     {
5635         RECT* r = new RECT;
5636         ::SetRect(r, x, y, x + w, y + h);
5637         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, CHECK_EMBEDDED, (LPARAM)r);
5638     }
5639 ret:
5640     env->DeleteGlobalRef(self);
5641 
5642     delete rs;
5643 }
5644 
_ReshapeNoCheck(void * param)5645 void AwtComponent::_ReshapeNoCheck(void *param)
5646 {
5647     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5648 
5649     ReshapeStruct *rs = (ReshapeStruct*)param;
5650     jobject self = rs->component;
5651     jint x = rs->x;
5652     jint y = rs->y;
5653     jint w = rs->w;
5654     jint h = rs->h;
5655 
5656     AwtComponent *p;
5657 
5658     PDATA pData;
5659     JNI_CHECK_PEER_GOTO(self, ret);
5660     p = (AwtComponent *)pData;
5661     if (::IsWindow(p->GetHWnd()))
5662     {
5663         RECT* r = new RECT;
5664         ::SetRect(r, x, y, x + w, y + h);
5665         p->SendMessage(WM_AWT_RESHAPE_COMPONENT, DONT_CHECK_EMBEDDED, (LPARAM)r);
5666     }
5667 ret:
5668     env->DeleteGlobalRef(self);
5669 
5670     delete rs;
5671 }
5672 
_NativeHandleEvent(void * param)5673 void AwtComponent::_NativeHandleEvent(void *param)
5674 {
5675     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5676 
5677     NativeHandleEventStruct *nhes = (NativeHandleEventStruct *)param;
5678     jobject self = nhes->component;
5679     jobject event = nhes->event;
5680 
5681     AwtComponent *p;
5682 
5683     PDATA pData;
5684     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5685     pData = JNI_GET_PDATA(self);
5686     if (pData == NULL) {
5687         env->DeleteGlobalRef(self);
5688         if (event != NULL) {
5689             env->DeleteGlobalRef(event);
5690         }
5691         delete nhes;
5692         return;
5693     }
5694     JNI_CHECK_NULL_GOTO(event, "null AWTEvent", ret);
5695 
5696     p = (AwtComponent *)pData;
5697     if (::IsWindow(p->GetHWnd()))
5698     {
5699         if (env->EnsureLocalCapacity(1) < 0) {
5700             env->DeleteGlobalRef(self);
5701             env->DeleteGlobalRef(event);
5702             delete nhes;
5703             return;
5704         }
5705         jbyteArray bdata = (jbyteArray)(env)->GetObjectField(event, AwtAWTEvent::bdataID);
5706         int id = (env)->GetIntField(event, AwtAWTEvent::idID);
5707         DASSERT(!safe_ExceptionOccurred(env));
5708         if (bdata != 0) {
5709             MSG msg;
5710             (env)->GetByteArrayRegion(bdata, 0, sizeof(MSG), (jbyte *)&msg);
5711             (env)->DeleteLocalRef(bdata);
5712             static BOOL keyDownConsumed = FALSE;
5713             static BOOL bCharChanged = FALSE;
5714             static WCHAR modifiedChar;
5715             WCHAR unicodeChar;
5716 
5717             /* Remember if a KEY_PRESSED event is consumed, as an old model
5718              * program won't consume a subsequent KEY_TYPED event.
5719              */
5720             jboolean consumed =
5721                 (env)->GetBooleanField(event, AwtAWTEvent::consumedID);
5722             DASSERT(!safe_ExceptionOccurred(env));
5723 
5724             if (consumed) {
5725                 keyDownConsumed = (id == java_awt_event_KeyEvent_KEY_PRESSED);
5726                 env->DeleteGlobalRef(self);
5727                 env->DeleteGlobalRef(event);
5728                 delete nhes;
5729                 return;
5730 
5731             } else if (id == java_awt_event_KeyEvent_KEY_PRESSED) {
5732                 // Fix for 6637607: reset consuming
5733                 keyDownConsumed = FALSE;
5734             }
5735 
5736             /* Consume a KEY_TYPED event if a KEY_PRESSED had been, to support
5737              * the old model.
5738              */
5739             if ((id == java_awt_event_KeyEvent_KEY_TYPED) && keyDownConsumed) {
5740                 keyDownConsumed = FALSE;
5741                 env->DeleteGlobalRef(self);
5742                 env->DeleteGlobalRef(event);
5743                 delete nhes;
5744                 return;
5745             }
5746 
5747             /* Modify any event parameters, if necessary. */
5748             if (self && pData &&
5749                 id >= java_awt_event_KeyEvent_KEY_FIRST &&
5750                 id <= java_awt_event_KeyEvent_KEY_LAST) {
5751 
5752                     AwtComponent* p = (AwtComponent*)pData;
5753 
5754                     jint keyCode =
5755                       (env)->GetIntField(event, AwtKeyEvent::keyCodeID);
5756                     jchar keyChar =
5757                       (env)->GetCharField(event, AwtKeyEvent::keyCharID);
5758                     jint modifiers =
5759                       (env)->GetIntField(event, AwtInputEvent::modifiersID);
5760 
5761                     DASSERT(!safe_ExceptionOccurred(env));
5762 
5763                 /* Check to see whether the keyCode or modifiers were changed
5764                    on the keyPressed event, and tweak the following keyTyped
5765                    event (if any) accodingly.  */
5766                 switch (id) {
5767                 case java_awt_event_KeyEvent_KEY_PRESSED:
5768                 {
5769                     UINT winKey = (UINT)msg.wParam;
5770                     bCharChanged = FALSE;
5771 
5772                     if (winKey == VK_PROCESSKEY) {
5773                         // Leave it up to IME
5774                         break;
5775                     }
5776 
5777                     if (keyCode != java_awt_event_KeyEvent_VK_UNDEFINED) {
5778                         UINT newWinKey, ignored;
5779                         p->JavaKeyToWindowsKey(keyCode, &newWinKey, &ignored, winKey);
5780                         if (newWinKey != 0) {
5781                             winKey = newWinKey;
5782                         }
5783                     }
5784 
5785                     BOOL isDeadKey = FALSE;
5786                     modifiedChar = p->WindowsKeyToJavaChar(winKey, modifiers, AwtComponent::NONE, isDeadKey);
5787                     bCharChanged = (keyChar != modifiedChar);
5788                 }
5789                 break;
5790 
5791                 case java_awt_event_KeyEvent_KEY_RELEASED:
5792                 {
5793                     keyDownConsumed = FALSE;
5794                     bCharChanged = FALSE;
5795                 }
5796                 break;
5797 
5798                 case java_awt_event_KeyEvent_KEY_TYPED:
5799                 {
5800                     if (bCharChanged)
5801                     {
5802                         unicodeChar = modifiedChar;
5803                     }
5804                     else
5805                     {
5806                         unicodeChar = keyChar;
5807                     }
5808                     bCharChanged = FALSE;
5809 
5810                     // Disable forwarding KEY_TYPED messages to peers of
5811                     // disabled components
5812                     if (p->isRecursivelyEnabled()) {
5813                         // send the character back to the native window for
5814                         // processing. The WM_AWT_FORWARD_CHAR handler will send
5815                         // this character to DefWindowProc
5816                         if (!::PostMessage(p->GetHWnd(), WM_AWT_FORWARD_CHAR,
5817                             MAKEWPARAM(unicodeChar, FALSE), msg.lParam)) {
5818                             JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
5819                         }
5820                     }
5821                     env->DeleteGlobalRef(self);
5822                     env->DeleteGlobalRef(event);
5823                     delete nhes;
5824                     return;
5825                 }
5826                 break;
5827 
5828                 default:
5829                     break;
5830                 }
5831             }
5832 
5833             // ignore all InputMethodEvents
5834             if (self && (pData = JNI_GET_PDATA(self)) &&
5835                 id >= java_awt_event_InputMethodEvent_INPUT_METHOD_FIRST &&
5836                 id <= java_awt_event_InputMethodEvent_INPUT_METHOD_LAST) {
5837                 env->DeleteGlobalRef(self);
5838                 env->DeleteGlobalRef(event);
5839                 delete nhes;
5840                 return;
5841             }
5842 
5843             // Create copy for local msg
5844             MSG* pCopiedMsg = new MSG;
5845             memmove(pCopiedMsg, &msg, sizeof(MSG));
5846             // Event handler deletes msg
5847             p->PostHandleEventMessage(pCopiedMsg, FALSE);
5848 
5849             env->DeleteGlobalRef(self);
5850             env->DeleteGlobalRef(event);
5851             delete nhes;
5852             return;
5853         }
5854 
5855         /* Forward any valid synthesized events.  Currently only mouse and
5856          * key events are supported.
5857          */
5858         if (self == NULL || (pData = JNI_GET_PDATA(self)) == NULL) {
5859             env->DeleteGlobalRef(self);
5860             env->DeleteGlobalRef(event);
5861             delete nhes;
5862             return;
5863         }
5864 
5865         AwtComponent* p = (AwtComponent*)pData;
5866         if (id >= java_awt_event_KeyEvent_KEY_FIRST &&
5867             id <= java_awt_event_KeyEvent_KEY_LAST) {
5868             p->SynthesizeKeyMessage(env, event);
5869         } else if (id >= java_awt_event_MouseEvent_MOUSE_FIRST &&
5870                    id <= java_awt_event_MouseEvent_MOUSE_LAST) {
5871             p->SynthesizeMouseMessage(env, event);
5872         }
5873     }
5874 
5875 ret:
5876     if (self != NULL) {
5877         env->DeleteGlobalRef(self);
5878     }
5879     if (event != NULL) {
5880         env->DeleteGlobalRef(event);
5881     }
5882 
5883     delete nhes;
5884 }
5885 
_SetForeground(void * param)5886 void AwtComponent::_SetForeground(void *param)
5887 {
5888     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5889 
5890     SetColorStruct *scs = (SetColorStruct *)param;
5891     jobject self = scs->component;
5892     jint rgb = scs->rgb;
5893 
5894     AwtComponent *c = NULL;
5895 
5896     PDATA pData;
5897     JNI_CHECK_PEER_GOTO(self, ret);
5898     c = (AwtComponent *)pData;
5899     if (::IsWindow(c->GetHWnd()))
5900     {
5901         c->SetColor(PALETTERGB((rgb>>16)&0xff,
5902                                (rgb>>8)&0xff,
5903                                (rgb)&0xff));
5904         c->VerifyState();
5905     }
5906 ret:
5907     env->DeleteGlobalRef(self);
5908 
5909     delete scs;
5910 }
5911 
_SetBackground(void * param)5912 void AwtComponent::_SetBackground(void *param)
5913 {
5914     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5915 
5916     SetColorStruct *scs = (SetColorStruct *)param;
5917     jobject self = scs->component;
5918     jint rgb = scs->rgb;
5919 
5920     AwtComponent *c = NULL;
5921 
5922     PDATA pData;
5923     JNI_CHECK_PEER_GOTO(self, ret);
5924     c = (AwtComponent *)pData;
5925     if (::IsWindow(c->GetHWnd()))
5926     {
5927         c->SetBackgroundColor(PALETTERGB((rgb>>16)&0xff,
5928                                          (rgb>>8)&0xff,
5929                                          (rgb)&0xff));
5930         c->VerifyState();
5931     }
5932 ret:
5933     env->DeleteGlobalRef(self);
5934 
5935     delete scs;
5936 }
5937 
_SetFont(void * param)5938 void AwtComponent::_SetFont(void *param)
5939 {
5940     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5941 
5942     SetFontStruct *sfs = (SetFontStruct *)param;
5943     jobject self = sfs->component;
5944     jobject font = sfs->font;
5945 
5946     AwtComponent *c = NULL;
5947 
5948     PDATA pData;
5949     JNI_CHECK_PEER_GOTO(self, ret);
5950     JNI_CHECK_NULL_GOTO(font, "null font", ret);
5951     c = (AwtComponent *)pData;
5952     if (::IsWindow(c->GetHWnd()))
5953     {
5954         AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID);
5955         if (awtFont == NULL) {
5956             /*arguments of AwtFont::Create are changed for multifont component */
5957             awtFont = AwtFont::Create(env, font);
5958         }
5959         env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont);
5960 
5961         c->SetFont(awtFont);
5962     }
5963 ret:
5964     env->DeleteGlobalRef(self);
5965     env->DeleteGlobalRef(font);
5966 
5967     delete sfs;
5968 }
5969 
5970 // Sets or kills focus for a component.
_SetFocus(void * param)5971 void AwtComponent::_SetFocus(void *param)
5972 {
5973     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
5974 
5975     SetFocusStruct *sfs = (SetFocusStruct *)param;
5976     jobject self = sfs->component;
5977     jboolean doSetFocus = sfs->doSetFocus;
5978 
5979     AwtComponent *c = NULL;
5980 
5981     PDATA pData;
5982     JNI_CHECK_NULL_GOTO(self, "peer", ret);
5983     pData = JNI_GET_PDATA(self);
5984     if (pData == NULL) {
5985         // do nothing just return false
5986         goto ret;
5987     }
5988 
5989     c = (AwtComponent *)pData;
5990     if (::IsWindow(c->GetHWnd())) {
5991         c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0);
5992     }
5993 ret:
5994     env->DeleteGlobalRef(self);
5995 
5996     delete sfs;
5997 }
5998 
_Start(void * param)5999 void AwtComponent::_Start(void *param)
6000 {
6001     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6002 
6003     jobject self = (jobject)param;
6004 
6005     AwtComponent *c = NULL;
6006 
6007     PDATA pData;
6008     JNI_CHECK_PEER_GOTO(self, ret);
6009     c = (AwtComponent *)pData;
6010     if (::IsWindow(c->GetHWnd()))
6011     {
6012         jobject target = c->GetTarget(env);
6013 
6014         /* Disable window if specified -- windows are enabled by default. */
6015         jboolean enabled = (jboolean)env->GetBooleanField(target,
6016                                                           AwtComponent::enabledID);
6017         if (!enabled) {
6018             ::EnableWindow(c->GetHWnd(), FALSE);
6019         }
6020 
6021         /* The peer is now ready for callbacks, since this is the last
6022          * initialization call
6023          */
6024         c->EnableCallbacks(TRUE);
6025 
6026         // Fix 4745222: we need to invalidate region since we validated it before initialization.
6027         ::InvalidateRgn(c->GetHWnd(), NULL, FALSE);
6028 
6029         // Fix 4530093: WM_PAINT after EnableCallbacks
6030         ::UpdateWindow(c->GetHWnd());
6031 
6032         env->DeleteLocalRef(target);
6033     }
6034 ret:
6035     env->DeleteGlobalRef(self);
6036 }
6037 
_BeginValidate(void * param)6038 void AwtComponent::_BeginValidate(void *param)
6039 {
6040     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6041     if (AwtToolkit::IsMainThread()) {
6042         jobject self = (jobject)param;
6043         if (self != NULL) {
6044             PDATA pData = JNI_GET_PDATA(self);
6045             if (pData) {
6046                 AwtComponent *c = (AwtComponent *)pData;
6047                 if (::IsWindow(c->GetHWnd())) {
6048                     c->SendMessage(WM_AWT_BEGIN_VALIDATE);
6049                 }
6050             }
6051             env->DeleteGlobalRef(self);
6052         }
6053     } else {
6054         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_BeginValidate, param);
6055     }
6056 }
6057 
_EndValidate(void * param)6058 void AwtComponent::_EndValidate(void *param)
6059 {
6060     if (AwtToolkit::IsMainThread()) {
6061         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6062         jobject self = (jobject)param;
6063         if (self != NULL) {
6064             PDATA pData = JNI_GET_PDATA(self);
6065             if (pData) {
6066                 AwtComponent *c = (AwtComponent *)pData;
6067                 if (::IsWindow(c->GetHWnd())) {
6068                     c->SendMessage(WM_AWT_END_VALIDATE);
6069                 }
6070             }
6071             env->DeleteGlobalRef(self);
6072         }
6073     } else {
6074         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_EndValidate, param);
6075     }
6076 }
6077 
_UpdateWindow(void * param)6078 void AwtComponent::_UpdateWindow(void *param)
6079 {
6080     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6081     if (AwtToolkit::IsMainThread()) {
6082         jobject self = (jobject)param;
6083         AwtComponent *c = NULL;
6084         PDATA pData;
6085         JNI_CHECK_PEER_GOTO(self, ret);
6086         c = (AwtComponent *)pData;
6087         if (::IsWindow(c->GetHWnd())) {
6088             ::UpdateWindow(c->GetHWnd());
6089         }
6090 ret:
6091         env->DeleteGlobalRef(self);
6092     } else {
6093         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_UpdateWindow, param);
6094     }
6095 }
6096 
_AddNativeDropTarget(void * param)6097 jlong AwtComponent::_AddNativeDropTarget(void *param)
6098 {
6099     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6100 
6101     jobject self = (jobject)param;
6102 
6103     jlong result = 0;
6104     AwtComponent *c = NULL;
6105 
6106     PDATA pData;
6107     JNI_CHECK_PEER_GOTO(self, ret);
6108     c = (AwtComponent *)pData;
6109     if (::IsWindow(c->GetHWnd()))
6110     {
6111         result = (jlong)(c->CreateDropTarget(env));
6112     }
6113 ret:
6114     env->DeleteGlobalRef(self);
6115 
6116     return result;
6117 }
6118 
_RemoveNativeDropTarget(void * param)6119 void AwtComponent::_RemoveNativeDropTarget(void *param)
6120 {
6121     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6122 
6123     jobject self = (jobject)param;
6124 
6125     AwtComponent *c = NULL;
6126 
6127     PDATA pData;
6128     JNI_CHECK_PEER_GOTO(self, ret);
6129     c = (AwtComponent *)pData;
6130     if (::IsWindow(c->GetHWnd()))
6131     {
6132         c->DestroyDropTarget();
6133     }
6134 ret:
6135     env->DeleteGlobalRef(self);
6136 }
6137 
_CreatePrintedPixels(void * param)6138 jintArray AwtComponent::_CreatePrintedPixels(void *param)
6139 {
6140     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6141 
6142     CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
6143     jobject self = cpps->component;
6144 
6145     jintArray result = NULL;
6146     AwtComponent *c = NULL;
6147 
6148     PDATA pData;
6149     JNI_CHECK_PEER_GOTO(self, ret);
6150     c = (AwtComponent *)pData;
6151     if (::IsWindow(c->GetHWnd()))
6152     {
6153         result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
6154     }
6155 ret:
6156     env->DeleteGlobalRef(self);
6157 
6158     delete cpps;
6159     return result; // this reference is global
6160 }
6161 
_IsObscured(void * param)6162 jboolean AwtComponent::_IsObscured(void *param)
6163 {
6164     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6165 
6166     jobject self = (jobject)param;
6167 
6168     jboolean result = JNI_FALSE;
6169     AwtComponent *c = NULL;
6170 
6171     PDATA pData;
6172     JNI_CHECK_PEER_GOTO(self, ret);
6173 
6174     c = (AwtComponent *)pData;
6175 
6176     if (::IsWindow(c->GetHWnd()))
6177     {
6178         HWND hWnd = c->GetHWnd();
6179         HDC hDC = ::GetDC(hWnd);
6180         RECT clipbox;
6181         int callresult = ::GetClipBox(hDC, &clipbox);
6182         switch(callresult) {
6183             case NULLREGION :
6184                 result = JNI_FALSE;
6185                 break;
6186             case SIMPLEREGION : {
6187                 RECT windowRect;
6188                 if (!::GetClientRect(hWnd, &windowRect)) {
6189                     result = JNI_TRUE;
6190                 } else {
6191                     result  = (jboolean)((clipbox.bottom != windowRect.bottom)
6192                         || (clipbox.left != windowRect.left)
6193                         || (clipbox.right != windowRect.right)
6194                         || (clipbox.top != windowRect.top));
6195                 }
6196                 break;
6197             }
6198             case COMPLEXREGION :
6199             default :
6200                 result = JNI_TRUE;
6201                 break;
6202         }
6203         ::ReleaseDC(hWnd, hDC);
6204     }
6205 ret:
6206     env->DeleteGlobalRef(self);
6207 
6208     return result;
6209 }
6210 
_NativeHandlesWheelScrolling(void * param)6211 jboolean AwtComponent::_NativeHandlesWheelScrolling(void *param)
6212 {
6213     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6214 
6215     jobject self = (jobject)param;
6216 
6217     jboolean result = JNI_FALSE;
6218     AwtComponent *c = NULL;
6219 
6220     PDATA pData;
6221     JNI_CHECK_PEER_GOTO(self, ret);
6222     c = (AwtComponent *)pData;
6223     if (::IsWindow(c->GetHWnd()))
6224     {
6225         result = JNI_IS_TRUE(c->InheritsNativeMouseWheelBehavior());
6226     }
6227 ret:
6228     env->DeleteGlobalRef(self);
6229 
6230     return result;
6231 }
6232 
_SetParent(void * param)6233 void AwtComponent::_SetParent(void * param)
6234 {
6235     if (AwtToolkit::IsMainThread()) {
6236         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6237         SetParentStruct *data = (SetParentStruct*) param;
6238         jobject self = data->component;
6239         jobject parent = data->parentComp;
6240 
6241         AwtComponent *awtComponent = NULL;
6242         AwtComponent *awtParent = NULL;
6243 
6244         PDATA pData;
6245         JNI_CHECK_PEER_GOTO(self, ret);
6246         awtComponent = (AwtComponent *)pData;
6247         JNI_CHECK_PEER_GOTO(parent, ret);
6248         awtParent = (AwtComponent *)pData;
6249 
6250         HWND selfWnd = awtComponent->GetHWnd();
6251         HWND parentWnd = awtParent->GetHWnd();
6252         if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) {
6253             // Shouldn't trigger native focus change
6254             // (only the proxy may be the native focus owner).
6255             ::SetParent(selfWnd, parentWnd);
6256         }
6257 ret:
6258         env->DeleteGlobalRef(self);
6259         env->DeleteGlobalRef(parent);
6260         delete data;
6261     } else {
6262         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetParent, param);
6263     }
6264 }
6265 
_SetRectangularShape(void * param)6266 void AwtComponent::_SetRectangularShape(void *param)
6267 {
6268     if (!AwtToolkit::IsMainThread()) {
6269         AwtToolkit::GetInstance().InvokeFunction(AwtComponent::_SetRectangularShape, param);
6270     } else {
6271         JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6272 
6273         SetRectangularShapeStruct *data = (SetRectangularShapeStruct *)param;
6274         jobject self = data->component;
6275         jint x1 = data->x1;
6276         jint x2 = data->x2;
6277         jint y1 = data->y1;
6278         jint y2 = data->y2;
6279         jobject region = data->region;
6280 
6281         AwtComponent *c = NULL;
6282 
6283         PDATA pData;
6284         JNI_CHECK_PEER_GOTO(self, ret);
6285 
6286         c = (AwtComponent *)pData;
6287         if (::IsWindow(c->GetHWnd())) {
6288             HRGN hRgn = NULL;
6289 
6290             // If all the params are zeros, the shape must be simply reset.
6291             // Otherwise, convert it into a region.
6292             if (region || x1 || x2 || y1 || y2) {
6293                 RECT_T rects[256];
6294                 RECT_T *pRect = rects;
6295 
6296                 const int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2,
6297                         region, &pRect, sizeof(rects)/sizeof(rects[0]));
6298                 if (!pRect) {
6299                     // RegionToYXBandedRectangles doesn't use safe_Malloc(),
6300                     // so throw the exception explicitly
6301                     throw std::bad_alloc();
6302                 }
6303 
6304                 RGNDATA *pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
6305                         sizeof(RGNDATAHEADER), sizeof(RECT_T), numrects);
6306                 memcpy((BYTE*)pRgnData + sizeof(RGNDATAHEADER), pRect, sizeof(RECT_T) * numrects);
6307                 if (pRect != rects) {
6308                     free(pRect);
6309                 }
6310                 pRect = NULL;
6311 
6312                 RGNDATAHEADER *pRgnHdr = (RGNDATAHEADER *) pRgnData;
6313                 pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
6314                 pRgnHdr->iType = RDH_RECTANGLES;
6315                 pRgnHdr->nRgnSize = 0;
6316                 pRgnHdr->rcBound.top = 0;
6317                 pRgnHdr->rcBound.left = 0;
6318                 pRgnHdr->rcBound.bottom = LONG(y2 - y1);
6319                 pRgnHdr->rcBound.right = LONG(x2 - x1);
6320                 pRgnHdr->nCount = numrects;
6321 
6322                 hRgn = ::ExtCreateRegion(NULL,
6323                         sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData);
6324 
6325                 free(pRgnData);
6326             }
6327 
6328             ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE);
6329         }
6330 
6331 ret:
6332         env->DeleteGlobalRef(self);
6333         if (region) {
6334             env->DeleteGlobalRef(region);
6335         }
6336 
6337         delete data;
6338     }
6339 }
6340 
_SetZOrder(void * param)6341 void AwtComponent::_SetZOrder(void *param) {
6342     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6343 
6344     SetZOrderStruct *data = (SetZOrderStruct *)param;
6345     jobject self = data->component;
6346     HWND above = HWND_TOP;
6347     if (data->above != 0) {
6348         above = reinterpret_cast<HWND>(data->above);
6349     }
6350 
6351     AwtComponent *c = NULL;
6352 
6353     PDATA pData;
6354     JNI_CHECK_PEER_GOTO(self, ret);
6355 
6356     c = (AwtComponent *)pData;
6357     if (::IsWindow(c->GetHWnd())) {
6358         ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0,
6359                        SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS);
6360     }
6361 
6362 ret:
6363     env->DeleteGlobalRef(self);
6364 
6365     delete data;
6366 }
6367 
PostUngrabEvent()6368 void AwtComponent::PostUngrabEvent() {
6369     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6370     jobject target = GetTarget(env);
6371     jobject event = JNU_NewObjectByName(env, "sun/awt/UngrabEvent", "(Ljava/awt/Component;)V",
6372                                         target);
6373     if (safe_ExceptionOccurred(env)) {
6374         env->ExceptionDescribe();
6375         env->ExceptionClear();
6376     }
6377     env->DeleteLocalRef(target);
6378     if (event != NULL) {
6379         SendEvent(event);
6380         env->DeleteLocalRef(event);
6381     }
6382 }
6383 
SetFocusedWindow(HWND window)6384 void AwtComponent::SetFocusedWindow(HWND window)
6385 {
6386     HWND old = sm_focusedWindow;
6387     sm_focusedWindow = window;
6388 
6389     AwtWindow::FocusedWindowChanged(old, window);
6390 }
6391 
6392 /************************************************************************
6393  * Component native methods
6394  */
6395 
6396 extern "C" {
6397 
6398 /**
6399  * This method is called from the WGL pipeline when it needs to retrieve
6400  * the HWND associated with a ComponentPeer's C++ level object.
6401  */
6402 HWND
AwtComponent_GetHWnd(JNIEnv * env,jlong pData)6403 AwtComponent_GetHWnd(JNIEnv *env, jlong pData)
6404 {
6405     AwtComponent *p = (AwtComponent *)jlong_to_ptr(pData);
6406     if (p == NULL) {
6407         return (HWND)0;
6408     }
6409     return p->GetHWnd();
6410 }
6411 
_GetInsets(void * param)6412 static void _GetInsets(void* param)
6413 {
6414     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
6415 
6416     GetInsetsStruct *gis = (GetInsetsStruct *)param;
6417     jobject self = gis->window;
6418 
6419     gis->insets->left = gis->insets->top =
6420         gis->insets->right = gis->insets->bottom = 0;
6421 
6422     PDATA pData;
6423     JNI_CHECK_PEER_GOTO(self, ret);
6424     AwtComponent *component = (AwtComponent *)pData;
6425 
6426     component->GetInsets(gis->insets);
6427 
6428   ret:
6429     env->DeleteGlobalRef(self);
6430     delete gis;
6431 }
6432 
6433 /**
6434  * This method is called from the WGL pipeline when it needs to retrieve
6435  * the insets associated with a ComponentPeer's C++ level object.
6436  */
AwtComponent_GetInsets(JNIEnv * env,jobject peer,RECT * insets)6437 void AwtComponent_GetInsets(JNIEnv *env, jobject peer, RECT *insets)
6438 {
6439     TRY;
6440 
6441     GetInsetsStruct *gis = new GetInsetsStruct;
6442     gis->window = env->NewGlobalRef(peer);
6443     gis->insets = insets;
6444 
6445     AwtToolkit::GetInstance().InvokeFunction(_GetInsets, gis);
6446     // global refs and mds are deleted in _UpdateWindow
6447 
6448     CATCH_BAD_ALLOC;
6449 
6450 }
6451 
6452 JNIEXPORT void JNICALL
Java_java_awt_Component_initIDs(JNIEnv * env,jclass cls)6453 Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls)
6454 {
6455     TRY;
6456     jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent");
6457     CHECK_NULL(inputEventClazz);
6458     jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I");
6459     CHECK_NULL(getButtonDownMasksID);
6460     jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID);
6461     jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE);
6462     CHECK_NULL(tmp);
6463     jsize len = env->GetArrayLength(obj);
6464     AwtComponent::masks = SAFE_SIZE_NEW_ARRAY(jint, len);
6465     for (int i = 0; i < len; i++) {
6466         AwtComponent::masks[i] = tmp[i];
6467     }
6468     env->ReleaseIntArrayElements(obj, tmp, 0);
6469     env->DeleteLocalRef(obj);
6470 
6471     /* class ids */
6472     jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
6473 
6474     DASSERT(peerCls);
6475     CHECK_NULL(peerCls);
6476 
6477     /* field ids */
6478     AwtComponent::peerID =
6479       env->GetFieldID(cls, "peer", "Ljava/awt/peer/ComponentPeer;");
6480     DASSERT(AwtComponent::peerID);
6481     CHECK_NULL(AwtComponent::peerID);
6482 
6483     AwtComponent::xID = env->GetFieldID(cls, "x", "I");
6484     DASSERT(AwtComponent::xID);
6485     CHECK_NULL(AwtComponent::xID);
6486 
6487     AwtComponent::yID = env->GetFieldID(cls, "y", "I");
6488     DASSERT(AwtComponent::yID);
6489     CHECK_NULL(AwtComponent::yID);
6490 
6491     AwtComponent::heightID = env->GetFieldID(cls, "height", "I");
6492     DASSERT(AwtComponent::heightID);
6493     CHECK_NULL(AwtComponent::heightID);
6494 
6495     AwtComponent::widthID = env->GetFieldID(cls, "width", "I");
6496     DASSERT(AwtComponent::widthID);
6497     CHECK_NULL(AwtComponent::widthID);
6498 
6499     AwtComponent::visibleID = env->GetFieldID(cls, "visible", "Z");
6500     DASSERT(AwtComponent::visibleID);
6501     CHECK_NULL(AwtComponent::visibleID);
6502 
6503     AwtComponent::backgroundID =
6504         env->GetFieldID(cls, "background", "Ljava/awt/Color;");
6505     DASSERT(AwtComponent::backgroundID);
6506     CHECK_NULL(AwtComponent::backgroundID);
6507 
6508     AwtComponent::foregroundID =
6509         env->GetFieldID(cls, "foreground", "Ljava/awt/Color;");
6510     DASSERT(AwtComponent::foregroundID);
6511     CHECK_NULL(AwtComponent::foregroundID);
6512 
6513     AwtComponent::enabledID = env->GetFieldID(cls, "enabled", "Z");
6514     DASSERT(AwtComponent::enabledID);
6515     CHECK_NULL(AwtComponent::enabledID);
6516 
6517     AwtComponent::parentID = env->GetFieldID(cls, "parent", "Ljava/awt/Container;");
6518     DASSERT(AwtComponent::parentID);
6519     CHECK_NULL(AwtComponent::parentID);
6520 
6521     AwtComponent::graphicsConfigID =
6522      env->GetFieldID(cls, "graphicsConfig", "Ljava/awt/GraphicsConfiguration;");
6523     DASSERT(AwtComponent::graphicsConfigID);
6524     CHECK_NULL(AwtComponent::graphicsConfigID);
6525 
6526     AwtComponent::focusableID = env->GetFieldID(cls, "focusable", "Z");
6527     DASSERT(AwtComponent::focusableID);
6528     CHECK_NULL(AwtComponent::focusableID);
6529 
6530     AwtComponent::appContextID = env->GetFieldID(cls, "appContext",
6531                                                  "Lsun/awt/AppContext;");
6532     DASSERT(AwtComponent::appContextID);
6533     CHECK_NULL(AwtComponent::appContextID);
6534 
6535     AwtComponent::peerGCID = env->GetFieldID(peerCls, "winGraphicsConfig",
6536                                         "Lsun/awt/Win32GraphicsConfig;");
6537     DASSERT(AwtComponent::peerGCID);
6538     CHECK_NULL(AwtComponent::peerGCID);
6539 
6540     AwtComponent::hwndID = env->GetFieldID(peerCls, "hwnd", "J");
6541     DASSERT(AwtComponent::hwndID);
6542     CHECK_NULL(AwtComponent::hwndID);
6543 
6544     AwtComponent::cursorID = env->GetFieldID(cls, "cursor", "Ljava/awt/Cursor;");
6545     DASSERT(AwtComponent::cursorID);
6546     CHECK_NULL(AwtComponent::cursorID);
6547 
6548     /* method ids */
6549     AwtComponent::getFontMID =
6550         env->GetMethodID(cls, "getFont_NoClientCode", "()Ljava/awt/Font;");
6551     DASSERT(AwtComponent::getFontMID);
6552     CHECK_NULL(AwtComponent::getFontMID);
6553 
6554     AwtComponent::getToolkitMID =
6555         env->GetMethodID(cls, "getToolkitImpl", "()Ljava/awt/Toolkit;");
6556     DASSERT(AwtComponent::getToolkitMID);
6557     CHECK_NULL(AwtComponent::getToolkitMID);
6558 
6559     AwtComponent::isEnabledMID = env->GetMethodID(cls, "isEnabledImpl", "()Z");
6560     DASSERT(AwtComponent::isEnabledMID);
6561     CHECK_NULL(AwtComponent::isEnabledMID);
6562 
6563     AwtComponent::getLocationOnScreenMID =
6564         env->GetMethodID(cls, "getLocationOnScreen_NoTreeLock", "()Ljava/awt/Point;");
6565     DASSERT(AwtComponent::getLocationOnScreenMID);
6566     CHECK_NULL(AwtComponent::getLocationOnScreenMID);
6567 
6568     AwtComponent::replaceSurfaceDataMID =
6569         env->GetMethodID(peerCls, "replaceSurfaceData", "()V");
6570     DASSERT(AwtComponent::replaceSurfaceDataMID);
6571     CHECK_NULL(AwtComponent::replaceSurfaceDataMID);
6572 
6573     AwtComponent::replaceSurfaceDataLaterMID =
6574         env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V");
6575     DASSERT(AwtComponent::replaceSurfaceDataLaterMID);
6576     CHECK_NULL(AwtComponent::replaceSurfaceDataLaterMID);
6577 
6578     AwtComponent::disposeLaterMID = env->GetMethodID(peerCls, "disposeLater", "()V");
6579     DASSERT(AwtComponent::disposeLaterMID);
6580     CHECK_NULL(AwtComponent::disposeLaterMID);
6581 
6582     CATCH_BAD_ALLOC;
6583 }
6584 
6585 } /* extern "C" */
6586 
6587 
6588 /************************************************************************
6589  * ComponentPeer native methods
6590  */
6591 
6592 extern "C" {
6593 
6594 /*
6595  * Class:     sun_awt_windows_WComponentPeer
6596  * Method:    pShow
6597  * Signature: ()V
6598  */
6599 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv * env,jobject self)6600 Java_sun_awt_windows_WComponentPeer_pShow(JNIEnv *env, jobject self)
6601 {
6602     TRY;
6603 
6604     jobject selfGlobalRef = env->NewGlobalRef(self);
6605 
6606     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Show, (void *)selfGlobalRef);
6607     // selfGlobalRef is deleted in _Show
6608 
6609     CATCH_BAD_ALLOC;
6610 }
6611 
6612 /*
6613  * Class:     sun_awt_windows_WComponentPeer
6614  * Method:    hide
6615  * Signature: ()V
6616  */
6617 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_hide(JNIEnv * env,jobject self)6618 Java_sun_awt_windows_WComponentPeer_hide(JNIEnv *env, jobject self)
6619 {
6620     TRY;
6621 
6622     jobject selfGlobalRef = env->NewGlobalRef(self);
6623 
6624     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Hide, (void *)selfGlobalRef);
6625     // selfGlobalRef is deleted in _Hide
6626 
6627     CATCH_BAD_ALLOC;
6628 }
6629 
6630 /*
6631  * Class:     sun_awt_windows_WComponentPeer
6632  * Method:    enable
6633  * Signature: ()V
6634  */
6635 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_enable(JNIEnv * env,jobject self)6636 Java_sun_awt_windows_WComponentPeer_enable(JNIEnv *env, jobject self)
6637 {
6638     TRY;
6639 
6640     jobject selfGlobalRef = env->NewGlobalRef(self);
6641 
6642     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Enable, (void *)selfGlobalRef);
6643     // selfGlobalRef is deleted in _Enable
6644 
6645     CATCH_BAD_ALLOC;
6646 }
6647 
6648 /*
6649  * Class:     sun_awt_windows_WComponentPeer
6650  * Method:    disable
6651  * Signature: ()V
6652  */
6653 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_disable(JNIEnv * env,jobject self)6654 Java_sun_awt_windows_WComponentPeer_disable(JNIEnv *env, jobject self)
6655 {
6656     TRY;
6657 
6658     jobject selfGlobalRef = env->NewGlobalRef(self);
6659 
6660     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Disable, (void *)selfGlobalRef);
6661     // selfGlobalRef is deleted in _Disable
6662 
6663     CATCH_BAD_ALLOC;
6664 }
6665 
6666 /*
6667  * Class:     sun_awt_windows_WComponentPeer
6668  * Method:    getLocationOnScreen
6669  * Signature: ()Ljava/awt/Point;
6670  */
6671 JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv * env,jobject self)6672 Java_sun_awt_windows_WComponentPeer_getLocationOnScreen(JNIEnv *env, jobject self)
6673 {
6674     TRY;
6675 
6676     jobject selfGlobalRef = env->NewGlobalRef(self);
6677 
6678     jobject resultGlobalRef = (jobject)AwtToolkit::GetInstance().SyncCall(
6679         (void*(*)(void*))AwtComponent::_GetLocationOnScreen, (void *)selfGlobalRef);
6680     // selfGlobalRef is deleted in _GetLocationOnScreen
6681     if (resultGlobalRef != NULL)
6682     {
6683         jobject resultLocalRef = env->NewLocalRef(resultGlobalRef);
6684         env->DeleteGlobalRef(resultGlobalRef);
6685         return resultLocalRef;
6686     }
6687 
6688     return NULL;
6689 
6690     CATCH_BAD_ALLOC_RET(NULL);
6691 }
6692 
6693 /*
6694  * Class:     sun_awt_windows_WComponentPeer
6695  * Method:    reshape
6696  * Signature: (IIII)V
6697  */
6698 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv * env,jobject self,jint x,jint y,jint w,jint h)6699 Java_sun_awt_windows_WComponentPeer_reshape(JNIEnv *env, jobject self,
6700                                             jint x, jint y, jint w, jint h)
6701 {
6702     TRY;
6703 
6704     ReshapeStruct *rs = new ReshapeStruct;
6705     rs->component = env->NewGlobalRef(self);
6706     rs->x = x;
6707     rs->y = y;
6708     rs->w = w;
6709     rs->h = h;
6710 
6711     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Reshape, rs);
6712     // global ref and rs are deleted in _Reshape
6713 
6714     CATCH_BAD_ALLOC;
6715 }
6716 
6717 /*
6718  * Class:     sun_awt_windows_WComponentPeer
6719  * Method:    reshape
6720  * Signature: (IIII)V
6721  */
6722 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv * env,jobject self,jint x,jint y,jint w,jint h)6723 Java_sun_awt_windows_WComponentPeer_reshapeNoCheck(JNIEnv *env, jobject self,
6724                                             jint x, jint y, jint w, jint h)
6725 {
6726     TRY;
6727 
6728     ReshapeStruct *rs = new ReshapeStruct;
6729     rs->component = env->NewGlobalRef(self);
6730     rs->x = x;
6731     rs->y = y;
6732     rs->w = w;
6733     rs->h = h;
6734 
6735     AwtToolkit::GetInstance().SyncCall(AwtComponent::_ReshapeNoCheck, rs);
6736     // global ref and rs are deleted in _ReshapeNoCheck
6737 
6738     CATCH_BAD_ALLOC;
6739 }
6740 
6741 
6742 /*
6743  * Class:     sun_awt_windows_WComponentPeer
6744  * Method:    nativeHandleEvent
6745  * Signature: (Ljava/awt/AWTEvent;)V
6746  */
6747 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv * env,jobject self,jobject event)6748 Java_sun_awt_windows_WComponentPeer_nativeHandleEvent(JNIEnv *env,
6749                                                       jobject self,
6750                                                       jobject event)
6751 {
6752     TRY;
6753 
6754     jobject selfGlobalRef = env->NewGlobalRef(self);
6755     jobject eventGlobalRef = env->NewGlobalRef(event);
6756 
6757     NativeHandleEventStruct *nhes = new NativeHandleEventStruct;
6758     nhes->component = selfGlobalRef;
6759     nhes->event = eventGlobalRef;
6760 
6761     AwtToolkit::GetInstance().SyncCall(AwtComponent::_NativeHandleEvent, nhes);
6762     // global refs and nhes are deleted in _NativeHandleEvent
6763 
6764     CATCH_BAD_ALLOC;
6765 }
6766 
6767 /*
6768  * Class:     sun_awt_windows_WComponentPeer
6769  * Method:    _dispose
6770  * Signature: ()V
6771  */
6772 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv * env,jobject self)6773 Java_sun_awt_windows_WComponentPeer__1dispose(JNIEnv *env, jobject self)
6774 {
6775     TRY_NO_HANG;
6776 
6777     AwtObject::_Dispose(self);
6778 
6779     CATCH_BAD_ALLOC;
6780 }
6781 
6782 /*
6783  * Class:     sun_awt_windows_WComponentPeer
6784  * Method:    _setForeground
6785  * Signature: (I)V
6786  */
6787 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv * env,jobject self,jint rgb)6788 Java_sun_awt_windows_WComponentPeer__1setForeground(JNIEnv *env, jobject self,
6789                                                     jint rgb)
6790 {
6791     TRY;
6792 
6793     jobject selfGlobalRef = env->NewGlobalRef(self);
6794 
6795     SetColorStruct *scs = new SetColorStruct;
6796     scs->component = selfGlobalRef;
6797     scs->rgb = rgb;
6798 
6799     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetForeground, scs);
6800     // selfGlobalRef and scs are deleted in _SetForeground()
6801 
6802     CATCH_BAD_ALLOC;
6803 }
6804 
6805 /*
6806  * Class:     sun_awt_windows_WComponentPeer
6807  * Method:    _setBackground
6808  * Signature: (I)V
6809  */
6810 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv * env,jobject self,jint rgb)6811 Java_sun_awt_windows_WComponentPeer__1setBackground(JNIEnv *env, jobject self,
6812                                                     jint rgb)
6813 {
6814     TRY;
6815 
6816     jobject selfGlobalRef = env->NewGlobalRef(self);
6817 
6818     SetColorStruct *scs = new SetColorStruct;
6819     scs->component = selfGlobalRef;
6820     scs->rgb = rgb;
6821 
6822     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetBackground, scs);
6823     // selfGlobalRef and scs are deleted in _SetBackground()
6824 
6825     CATCH_BAD_ALLOC;
6826 }
6827 
6828 /*
6829  * Class:     sun_awt_windows_WComponentPeer
6830  * Method:    _setFont
6831  * Signature: (Ljava/awt/Font;)V
6832  */
6833 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv * env,jobject self,jobject font)6834 Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self,
6835                         jobject font)
6836 {
6837     TRY;
6838 
6839     jobject selfGlobalRef = env->NewGlobalRef(self);
6840     jobject fontGlobalRef = env->NewGlobalRef(font);
6841 
6842     SetFontStruct *sfs = new SetFontStruct;
6843     sfs->component = selfGlobalRef;
6844     sfs->font = fontGlobalRef;
6845 
6846     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetFont, sfs);
6847     // global refs and sfs are deleted in _SetFont()
6848 
6849     CATCH_BAD_ALLOC;
6850 }
6851 
6852 /*
6853  * Class:     sun_awt_windows_WComponentPeer
6854  * Method:    focusGained
6855  * Signature: (Z)
6856  */
Java_sun_awt_windows_WComponentPeer_setFocus(JNIEnv * env,jobject self,jboolean doSetFocus)6857 JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus
6858     (JNIEnv *env, jobject self, jboolean doSetFocus)
6859 {
6860     TRY;
6861 
6862     jobject selfGlobalRef = env->NewGlobalRef(self);
6863 
6864     SetFocusStruct *sfs = new SetFocusStruct;
6865     sfs->component = selfGlobalRef;
6866     sfs->doSetFocus = doSetFocus;
6867 
6868     AwtToolkit::GetInstance().SyncCall(
6869         (void*(*)(void*))AwtComponent::_SetFocus, sfs);
6870     // global refs and self are deleted in _SetFocus
6871 
6872     CATCH_BAD_ALLOC;
6873 }
6874 
6875 /*
6876  * Class:     sun_awt_windows_WComponentPeer
6877  * Method:    start
6878  * Signature: ()V
6879  */
6880 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_start(JNIEnv * env,jobject self)6881 Java_sun_awt_windows_WComponentPeer_start(JNIEnv *env, jobject self)
6882 {
6883     TRY;
6884 
6885     jobject selfGlobalRef = env->NewGlobalRef(self);
6886 
6887     AwtToolkit::GetInstance().SyncCall(AwtComponent::_Start, (void *)selfGlobalRef);
6888     // selfGlobalRef is deleted in _Start
6889 
6890     CATCH_BAD_ALLOC;
6891 }
6892 
6893 /*
6894  * Class:     sun_awt_windows_WComponentPeer
6895  * Method:    beginValidate
6896  * Signature: ()V
6897  */
6898 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv * env,jobject self)6899 Java_sun_awt_windows_WComponentPeer_beginValidate(JNIEnv *env, jobject self)
6900 {
6901     TRY;
6902 
6903     jobject selfGlobalRef = env->NewGlobalRef(self);
6904 
6905     AwtToolkit::GetInstance().SyncCall(AwtComponent::_BeginValidate, (void *)selfGlobalRef);
6906     // selfGlobalRef is deleted in _BeginValidate
6907 
6908     CATCH_BAD_ALLOC;
6909 }
6910 
6911 /*
6912  * Class:     sun_awt_windows_WComponentPeer
6913  * Method:    endValidate
6914  * Signature: ()V
6915  */
6916 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv * env,jobject self)6917 Java_sun_awt_windows_WComponentPeer_endValidate(JNIEnv *env, jobject self)
6918 {
6919     TRY;
6920 
6921     jobject selfGlobalRef = env->NewGlobalRef(self);
6922 
6923     AwtToolkit::GetInstance().SyncCall(AwtComponent::_EndValidate, (void *)selfGlobalRef);
6924     // selfGlobalRef is deleted in _EndValidate
6925 
6926     CATCH_BAD_ALLOC;
6927 }
6928 
6929 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv * env,jobject self)6930 Java_sun_awt_windows_WComponentPeer_updateWindow(JNIEnv *env, jobject self)
6931 {
6932     TRY;
6933 
6934     jobject selfGlobalRef = env->NewGlobalRef(self);
6935 
6936     AwtToolkit::GetInstance().SyncCall(AwtComponent::_UpdateWindow, (void *)selfGlobalRef);
6937     // selfGlobalRef is deleted in _UpdateWindow
6938 
6939     CATCH_BAD_ALLOC;
6940 }
6941 
6942 /*
6943  * Class:     sun_awt_windows_WComponentPeer
6944  * Method:    addNativeDropTarget
6945  * Signature: ()L
6946  */
6947 
6948 JNIEXPORT jlong JNICALL
Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv * env,jobject self)6949 Java_sun_awt_windows_WComponentPeer_addNativeDropTarget(JNIEnv *env,
6950                                                         jobject self)
6951 {
6952     TRY;
6953 
6954     jobject selfGlobalRef = env->NewGlobalRef(self);
6955 
6956     return ptr_to_jlong(AwtToolkit::GetInstance().SyncCall(
6957         (void*(*)(void*))AwtComponent::_AddNativeDropTarget,
6958         (void *)selfGlobalRef));
6959     // selfGlobalRef is deleted in _AddNativeDropTarget
6960 
6961     CATCH_BAD_ALLOC_RET(0);
6962 }
6963 
6964 /*
6965  * Class:     sun_awt_windows_WComponentPeer
6966  * Method:    removeNativeDropTarget
6967  * Signature: ()V
6968  */
6969 
6970 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv * env,jobject self)6971 Java_sun_awt_windows_WComponentPeer_removeNativeDropTarget(JNIEnv *env,
6972                                                            jobject self)
6973 {
6974     TRY;
6975 
6976     jobject selfGlobalRef = env->NewGlobalRef(self);
6977 
6978     AwtToolkit::GetInstance().SyncCall(
6979         AwtComponent::_RemoveNativeDropTarget, (void *)selfGlobalRef);
6980     // selfGlobalRef is deleted in _RemoveNativeDropTarget
6981 
6982     CATCH_BAD_ALLOC;
6983 }
6984 
6985 /*
6986  * Class:     sun_awt_windows_WComponentPeer
6987  * Method:    getTargetGC
6988  * Signature: ()Ljava/awt/GraphicsConfiguration;
6989  */
6990 JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv * env,jobject theThis)6991 Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
6992 {
6993     TRY;
6994 
6995     jobject targetObj;
6996     jobject gc = 0;
6997 
6998     targetObj = env->GetObjectField(theThis, AwtObject::targetID);
6999     DASSERT(targetObj);
7000 
7001     gc = env->GetObjectField(targetObj, AwtComponent::graphicsConfigID);
7002     return gc;
7003 
7004     CATCH_BAD_ALLOC_RET(NULL);
7005 }
7006 
7007 /*
7008  * Class:     sun_awt_windows_WComponentPeer
7009  * Method:    createPrintedPixels
7010  * Signature: (IIIIII)I[
7011  */
7012 JNIEXPORT jintArray JNICALL
Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv * env,jobject self,jint srcX,jint srcY,jint srcW,jint srcH,jint alpha)7013 Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
7014     jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
7015 {
7016     TRY;
7017 
7018     jobject selfGlobalRef = env->NewGlobalRef(self);
7019 
7020     CreatePrintedPixelsStruct *cpps = new CreatePrintedPixelsStruct;
7021     cpps->component = selfGlobalRef;
7022     cpps->srcx = srcX;
7023     cpps->srcy = srcY;
7024     cpps->srcw = srcW;
7025     cpps->srch = srcH;
7026     cpps->alpha = alpha;
7027 
7028     jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
7029         (void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
7030     // selfGlobalRef and cpps are deleted in _CreatePrintedPixels
7031     if (globalRef != NULL)
7032     {
7033         jintArray localRef = (jintArray)env->NewLocalRef(globalRef);
7034         env->DeleteGlobalRef(globalRef);
7035         return localRef;
7036     }
7037     else
7038     {
7039         return NULL;
7040     }
7041 
7042     CATCH_BAD_ALLOC_RET(NULL);
7043 }
7044 
7045 /*
7046  * Class:     sun_awt_windows_WComponentPeer
7047  * Method:    nativeHandlesWheelScrolling
7048  * Signature: ()Z
7049  */
7050 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling(JNIEnv * env,jobject self)7051 Java_sun_awt_windows_WComponentPeer_nativeHandlesWheelScrolling (JNIEnv* env,
7052     jobject self)
7053 {
7054     TRY;
7055 
7056     return (jboolean)AwtToolkit::GetInstance().SyncCall(
7057         (void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
7058         env->NewGlobalRef(self));
7059     // global ref is deleted in _NativeHandlesWheelScrolling
7060 
7061     CATCH_BAD_ALLOC_RET(NULL);
7062 }
7063 
7064 /*
7065  * Class:     sun_awt_windows_WComponentPeer
7066  * Method:    isObscured
7067  * Signature: ()Z
7068  */
7069 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv * env,jobject self)7070 Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env,
7071     jobject self)
7072 {
7073     TRY;
7074 
7075     jobject selfGlobalRef = env->NewGlobalRef(self);
7076 
7077     return (jboolean)AwtToolkit::GetInstance().SyncCall(
7078         (void*(*)(void*))AwtComponent::_IsObscured,
7079         (void *)selfGlobalRef);
7080     // selfGlobalRef is deleted in _IsObscured
7081 
7082     CATCH_BAD_ALLOC_RET(NULL);
7083 }
7084 
7085 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv * env,jobject self,jobject parent)7086 Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) {
7087     TRY;
7088 
7089     SetParentStruct * data = new SetParentStruct;
7090     data->component = env->NewGlobalRef(self);
7091     data->parentComp = env->NewGlobalRef(parent);
7092 
7093     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetParent, data);
7094     // global refs and data are deleted in SetParent
7095 
7096     CATCH_BAD_ALLOC;
7097 }
7098 
7099 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv * env,jobject self,jint x1,jint y1,jint x2,jint y2,jobject region)7100 Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject self,
7101         jint x1, jint y1, jint x2, jint y2, jobject region)
7102 {
7103     TRY;
7104 
7105     SetRectangularShapeStruct * data = new SetRectangularShapeStruct;
7106     data->component = env->NewGlobalRef(self);
7107     data->x1 = x1;
7108     data->x2 = x2;
7109     data->y1 = y1;
7110     data->y2 = y2;
7111     if (region) {
7112         data->region = env->NewGlobalRef(region);
7113     } else {
7114         data->region = NULL;
7115     }
7116 
7117     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetRectangularShape, data);
7118     // global refs and data are deleted in _SetRectangularShape
7119 
7120     CATCH_BAD_ALLOC;
7121 }
7122 
7123 JNIEXPORT void JNICALL
Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv * env,jobject self,jlong above)7124 Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above)
7125 {
7126     TRY;
7127 
7128     SetZOrderStruct * data = new SetZOrderStruct;
7129     data->component = env->NewGlobalRef(self);
7130     data->above = above;
7131 
7132     AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data);
7133     // global refs and data are deleted in _SetLower
7134 
7135     CATCH_BAD_ALLOC;
7136 }
7137 
7138 } /* extern "C" */
7139 
7140 
7141 /************************************************************************
7142  * Diagnostic routines
7143  */
7144 
7145 #ifdef DEBUG
7146 
VerifyState()7147 void AwtComponent::VerifyState()
7148 {
7149     if (AwtToolkit::GetInstance().VerifyComponents() == FALSE) {
7150         return;
7151     }
7152 
7153     if (m_callbacksEnabled == FALSE) {
7154         /* Component is not fully setup yet. */
7155         return;
7156     }
7157 
7158     /* Get target bounds. */
7159     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
7160     if (env->PushLocalFrame(10) < 0)
7161         return;
7162 
7163     jobject target = GetTarget(env);
7164 
7165     jint x = env->GetIntField(target, AwtComponent::xID);
7166     jint y = env->GetIntField(target, AwtComponent::yID);
7167     jint width = env->GetIntField(target, AwtComponent::widthID);
7168     jint height = env->GetIntField(target, AwtComponent::heightID);
7169 
7170     /* Convert target origin to absolute coordinates */
7171     while (TRUE) {
7172 
7173         jobject parent = env->GetObjectField(target, AwtComponent::parentID);
7174         if (parent == NULL) {
7175             break;
7176         }
7177         x += env->GetIntField(parent, AwtComponent::xID);
7178         y += env->GetIntField(parent, AwtComponent::yID);
7179 
7180         /* If this component has insets, factor them in, but ignore
7181          * top-level windows.
7182          */
7183         jobject parent2 = env->GetObjectField(parent, AwtComponent::parentID);
7184         if (parent2 != NULL) {
7185             jobject peer = GetPeerForTarget(env, parent);
7186             if (peer != NULL &&
7187                 JNU_IsInstanceOfByName(env, peer,
7188                                        "sun/awt/windows/WPanelPeer") > 0) {
7189                 jobject insets =
7190                     JNU_CallMethodByName(env, NULL, peer,"insets",
7191                                          "()Ljava/awt/Insets;").l;
7192                 x += (env)->GetIntField(insets, AwtInsets::leftID);
7193                 y += (env)->GetIntField(insets, AwtInsets::topID);
7194             }
7195         }
7196         env->DeleteLocalRef(target);
7197         target = parent;
7198     }
7199 
7200     // Test whether component's bounds match the native window's
7201     RECT rect;
7202     VERIFY(::GetWindowRect(GetHWnd(), &rect));
7203 #if 0
7204     DASSERT( (x == rect.left) &&
7205             (y == rect.top) &&
7206             (width == (rect.right-rect.left)) &&
7207             (height == (rect.bottom-rect.top)) );
7208 #else
7209     BOOL fSizeValid = ( (x == rect.left) &&
7210             (y == rect.top) &&
7211             (width == (rect.right-rect.left)) &&
7212             (height == (rect.bottom-rect.top)) );
7213 #endif
7214 
7215     // See if visible state matches
7216     BOOL wndVisible = ::IsWindowVisible(GetHWnd());
7217     jboolean targetVisible;
7218     // To avoid possibly running client code on the toolkit thread, don't
7219     // do the following check if we're running on the toolkit thread.
7220     if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7221         targetVisible = JNU_CallMethodByName(env, NULL, GetTarget(env),
7222                                                   "isShowing", "()Z").z;
7223         DASSERT(!safe_ExceptionOccurred(env));
7224     } else {
7225         targetVisible = wndVisible ? 1 : 0;
7226     }
7227 #if 0
7228     DASSERT( (targetVisible && wndVisible) ||
7229             (!targetVisible && !wndVisible) );
7230 #else
7231     BOOL fVisibleValid = ( (targetVisible && wndVisible) ||
7232             (!targetVisible && !wndVisible) );
7233 #endif
7234 
7235     // Check enabled state
7236     BOOL wndEnabled = ::IsWindowEnabled(GetHWnd());
7237     jboolean enabled = (jboolean)env->GetBooleanField(target,
7238                                                       AwtComponent::enabledID);
7239 #if 0
7240     DASSERT( (enabled && wndEnabled) ||
7241             (!enabled && !wndEnabled) );
7242 #else
7243     BOOL fEnabledValid = ((enabled && wndEnabled) ||
7244                           (!(enabled && !wndEnabled) ));
7245 
7246     if (!fSizeValid || !fVisibleValid || !fEnabledValid) {
7247         printf("AwtComponent::ValidateState() failed:\n");
7248         // To avoid possibly running client code on the toolkit thread, don't
7249         // do the following call if we're running on the toolkit thread.
7250         if (AwtToolkit::MainThread() != ::GetCurrentThreadId()) {
7251             jstring targetStr =
7252                 (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
7253                                               "getName",
7254                                               "()Ljava/lang/String;").l;
7255             DASSERT(!safe_ExceptionOccurred(env));
7256             LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
7257             printf("\t%S\n", targetStrW);
7258             JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
7259         }
7260         printf("\twas:       [%d,%d,%dx%d]\n", x, y, width, height);
7261         if (!fSizeValid) {
7262             printf("\tshould be: [%d,%d,%dx%d]\n", rect.left, rect.top,
7263                    rect.right-rect.left, rect.bottom-rect.top);
7264         }
7265         if (!fVisibleValid) {
7266             printf("\tshould be: %s\n",
7267                    (targetVisible) ? "visible" : "hidden");
7268         }
7269         if (!fEnabledValid) {
7270             printf("\tshould be: %s\n",
7271                    enabled ? "enabled" : "disabled");
7272         }
7273     }
7274 #endif
7275     env->PopLocalFrame(0);
7276 }
7277 #endif //DEBUG
7278 
7279 // Methods for globally managed DC list
7280 
7281 /**
7282  * Add a new DC to the DC list for this component.
7283  */
AddDC(HDC hDC,HWND hWnd)7284 void DCList::AddDC(HDC hDC, HWND hWnd)
7285 {
7286     DCItem *newItem = new DCItem;
7287     newItem->hDC = hDC;
7288     newItem->hWnd = hWnd;
7289     AddDCItem(newItem);
7290 }
7291 
AddDCItem(DCItem * newItem)7292 void DCList::AddDCItem(DCItem *newItem)
7293 {
7294     listLock.Enter();
7295     newItem->next = head;
7296     head = newItem;
7297     listLock.Leave();
7298 }
7299 
7300 /**
7301  * Given a DC and window handle, remove the DC from the DC list
7302  * and return TRUE if it exists on the current list.  Otherwise
7303  * return FALSE.
7304  * A DC may not exist on the list because it has already
7305  * been released elsewhere (for example, the window
7306  * destruction process may release a DC while a rendering
7307  * thread may also want to release a DC when it notices that
7308  * its DC is obsolete for the current window).
7309  */
RemoveDC(HDC hDC,HWND hWnd)7310 DCItem *DCList::RemoveDC(HDC hDC, HWND hWnd)
7311 {
7312     listLock.Enter();
7313     DCItem **prevPtrPtr = &head;
7314     DCItem *listPtr = head;
7315     while (listPtr) {
7316         DCItem *nextPtr = listPtr->next;
7317         if (listPtr->hDC == hDC && listPtr->hWnd == hWnd) {
7318             *prevPtrPtr = nextPtr;
7319             break;
7320         }
7321         prevPtrPtr = &listPtr->next;
7322         listPtr = nextPtr;
7323     }
7324     listLock.Leave();
7325     return listPtr;
7326 }
7327 
7328 /**
7329  * Remove all DCs from the DC list which are associated with
7330  * the same window as hWnd.  Return the list of those
7331  * DC's to the caller (which will then probably want to
7332  * call ReleaseDC() for the returned DCs).
7333  */
RemoveAllDCs(HWND hWnd)7334 DCItem *DCList::RemoveAllDCs(HWND hWnd)
7335 {
7336     listLock.Enter();
7337     DCItem **prevPtrPtr = &head;
7338     DCItem *listPtr = head;
7339     DCItem *newListPtr = NULL;
7340     BOOL ret = FALSE;
7341     while (listPtr) {
7342         DCItem *nextPtr = listPtr->next;
7343         if (listPtr->hWnd == hWnd) {
7344             *prevPtrPtr = nextPtr;
7345             listPtr->next = newListPtr;
7346             newListPtr = listPtr;
7347         } else {
7348             prevPtrPtr = &listPtr->next;
7349         }
7350         listPtr = nextPtr;
7351     }
7352     listLock.Leave();
7353     return newListPtr;
7354 }
7355 
7356 
7357 /**
7358  * Realize palettes of all existing HDC objects
7359  */
RealizePalettes(int screen)7360 void DCList::RealizePalettes(int screen)
7361 {
7362     listLock.Enter();
7363     DCItem *listPtr = head;
7364     while (listPtr) {
7365         AwtWin32GraphicsDevice::RealizePalette(listPtr->hDC, screen);
7366         listPtr = listPtr->next;
7367     }
7368     listLock.Leave();
7369 }
7370 
MoveDCToPassiveList(HDC hDC,HWND hWnd)7371 void MoveDCToPassiveList(HDC hDC, HWND hWnd) {
7372     DCItem *removedDC;
7373     if ((removedDC = activeDCList.RemoveDC(hDC, hWnd)) != NULL) {
7374         passiveDCList.AddDCItem(removedDC);
7375     }
7376 }
7377 
ReleaseDCList(HWND hwnd,DCList & list)7378 void ReleaseDCList(HWND hwnd, DCList &list) {
7379     DCItem *removedDCs = list.RemoveAllDCs(hwnd);
7380     while (removedDCs) {
7381         DCItem *tmpDCList = removedDCs;
7382         DASSERT(::GetObjectType(tmpDCList->hDC) == OBJ_DC);
7383         int retValue = ::ReleaseDC(tmpDCList->hWnd, tmpDCList->hDC);
7384         VERIFY(retValue != 0);
7385         if (retValue != 0) {
7386             // Valid ReleaseDC call; need to decrement GDI object counter
7387             AwtGDIObject::Decrement();
7388         }
7389         removedDCs = removedDCs->next;
7390         delete tmpDCList;
7391     }
7392 }
7393 
7394