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