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