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