mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JBR-2712 Typeahead mechanism doesn't work on Windows
(cherry picked from commits1a9838082e,f5b6222835,acd7e3b2da, cd6dd5c3cf8556f97f3113cb7d615a92393b57bf(partially), e8bbd8ffdd90f57cd12d7d7e89188be97ee4be0b(partially))
This commit is contained in:
committed by
alexey.ushakov@jetbrains.com
parent
7a91294571
commit
3c6aaba7af
@@ -928,7 +928,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
|
||||
int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
|
||||
getTarget(), lightweightChild, temporary,
|
||||
focusedWindowChangeAllowed, time, cause);
|
||||
focusedWindowChangeAllowed, time, cause, false);
|
||||
switch (result) {
|
||||
case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
|
||||
return false;
|
||||
@@ -982,9 +982,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
|
||||
Component focusOwner = kfmPeer.getCurrentFocusOwner();
|
||||
return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
|
||||
getTarget(), temporary,
|
||||
focusedWindowChangeAllowed,
|
||||
time, cause, focusOwner);
|
||||
getTarget(), false, cause, focusOwner);
|
||||
|
||||
case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
|
||||
return true;
|
||||
|
||||
@@ -121,10 +121,11 @@ public abstract class KeyboardFocusManager
|
||||
boolean temporary,
|
||||
boolean focusedWindowChangeAllowed,
|
||||
long time,
|
||||
FocusEvent.Cause cause)
|
||||
FocusEvent.Cause cause,
|
||||
boolean highPriorityEvents)
|
||||
{
|
||||
return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
|
||||
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
|
||||
heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause, highPriorityEvents);
|
||||
}
|
||||
public boolean processSynchronousLightweightTransfer(Component heavyweight,
|
||||
Component descendant,
|
||||
@@ -2381,7 +2382,8 @@ public abstract class KeyboardFocusManager
|
||||
*/
|
||||
static int shouldNativelyFocusHeavyweight
|
||||
(Component heavyweight, Component descendant, boolean temporary,
|
||||
boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)
|
||||
boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause,
|
||||
boolean highPriorityEvents)
|
||||
{
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
if (heavyweight == null) {
|
||||
@@ -2450,17 +2452,22 @@ public abstract class KeyboardFocusManager
|
||||
new FocusEvent(currentFocusOwner,
|
||||
FocusEvent.FOCUS_LOST,
|
||||
temporary, descendant, cause);
|
||||
// Fix 5028014. Rolled out.
|
||||
// SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
|
||||
SunToolkit.postEvent(currentFocusOwner.appContext,
|
||||
currentFocusOwnerEvent);
|
||||
if (highPriorityEvents) {
|
||||
SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
|
||||
} else {
|
||||
SunToolkit.postEvent(currentFocusOwner.appContext,
|
||||
currentFocusOwnerEvent);
|
||||
}
|
||||
}
|
||||
FocusEvent newFocusOwnerEvent =
|
||||
new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
|
||||
temporary, currentFocusOwner, cause);
|
||||
// Fix 5028014. Rolled out.
|
||||
// SunToolkit.postPriorityEvent(newFocusOwnerEvent);
|
||||
SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
|
||||
if (highPriorityEvents) {
|
||||
SunToolkit.postPriorityEvent(newFocusOwnerEvent);
|
||||
} else {
|
||||
SunToolkit.postEvent(descendant.appContext,
|
||||
newFocusOwnerEvent);
|
||||
}
|
||||
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
|
||||
focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
|
||||
|
||||
@@ -426,7 +426,8 @@ public final class AWTAccessor {
|
||||
boolean temporary,
|
||||
boolean focusedWindowChangeAllowed,
|
||||
long time,
|
||||
Cause cause);
|
||||
Cause cause,
|
||||
boolean highPriorityEvents);
|
||||
/**
|
||||
* Delivers focus for the lightweight descendant of the heavyweight
|
||||
* synchronously.
|
||||
|
||||
@@ -107,9 +107,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
|
||||
@SuppressWarnings("deprecation")
|
||||
public static boolean deliverFocus(Component lightweightChild,
|
||||
Component target,
|
||||
boolean temporary,
|
||||
boolean focusedWindowChangeAllowed,
|
||||
long time,
|
||||
boolean highPriority,
|
||||
FocusEvent.Cause cause,
|
||||
Component currentFocusOwner) // provided by the descendant peers
|
||||
{
|
||||
@@ -128,7 +126,11 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
focusLog.finer("Posting focus event: " + fl);
|
||||
}
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
|
||||
if (highPriority) {
|
||||
SunToolkit.postPriorityEvent(fl);
|
||||
} else {
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
|
||||
}
|
||||
}
|
||||
|
||||
FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
|
||||
@@ -137,7 +139,11 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
|
||||
focusLog.finer("Posting focus event: " + fg);
|
||||
}
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
|
||||
if (highPriority) {
|
||||
SunToolkit.postPriorityEvent(fg);
|
||||
} else {
|
||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,11 +158,12 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag
|
||||
boolean temporary,
|
||||
boolean focusedWindowChangeAllowed,
|
||||
long time,
|
||||
FocusEvent.Cause cause)
|
||||
FocusEvent.Cause cause,
|
||||
boolean highPriorityEvents)
|
||||
{
|
||||
return KfmAccessor.instance.shouldNativelyFocusHeavyweight(
|
||||
heavyweight, descendant, temporary, focusedWindowChangeAllowed,
|
||||
time, cause);
|
||||
time, cause, highPriorityEvents);
|
||||
}
|
||||
|
||||
public static void removeLastFocusRequest(Component heavyweight) {
|
||||
|
||||
@@ -473,6 +473,14 @@ public abstract class SunToolkit extends Toolkit
|
||||
* Post AWTEvent of high priority.
|
||||
*/
|
||||
public static void postPriorityEvent(final AWTEvent e) {
|
||||
if (e.getID() == WindowEvent.WINDOW_LOST_FOCUS &&
|
||||
e instanceof TimedWindowEvent)
|
||||
{
|
||||
TimedWindowEvent twe = (TimedWindowEvent)e;
|
||||
((SunToolkit)Toolkit.getDefaultToolkit()).
|
||||
setWindowDeactivationTime((Window)twe.getSource(), twe.getWhen());
|
||||
}
|
||||
|
||||
PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -259,7 +259,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget
|
||||
int result = XKeyboardFocusManagerPeer.
|
||||
shouldNativelyFocusHeavyweight(target, lightweightChild,
|
||||
temporary, focusedWindowChangeAllowed,
|
||||
time, cause);
|
||||
time, cause, false);
|
||||
|
||||
switch (result) {
|
||||
case XKeyboardFocusManagerPeer.SNFH_FAILURE:
|
||||
|
||||
@@ -217,7 +217,7 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{
|
||||
{
|
||||
int result = XKeyboardFocusManagerPeer
|
||||
.shouldNativelyFocusHeavyweight(proxy, lightweightChild,
|
||||
temporary, false, time, cause);
|
||||
temporary, false, time, cause, false);
|
||||
|
||||
switch (result) {
|
||||
case XKeyboardFocusManagerPeer.SNFH_FAILURE:
|
||||
|
||||
@@ -105,9 +105,7 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
|
||||
{
|
||||
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
|
||||
target,
|
||||
temporary,
|
||||
focusedWindowChangeAllowed,
|
||||
time,
|
||||
false,
|
||||
cause,
|
||||
getInstance().getCurrentFocusOwner());
|
||||
}
|
||||
|
||||
@@ -726,7 +726,7 @@ public abstract class WComponentPeer extends WObjectPeer
|
||||
int result = WKeyboardFocusManagerPeer
|
||||
.shouldNativelyFocusHeavyweight((Component)target, lightweightChild,
|
||||
temporary, focusedWindowChangeAllowed,
|
||||
time, cause);
|
||||
time, cause, true);
|
||||
|
||||
switch (result) {
|
||||
case WKeyboardFocusManagerPeer.SNFH_FAILURE:
|
||||
|
||||
@@ -80,9 +80,7 @@ final class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
|
||||
// TODO: do something to eliminate this forwarding
|
||||
return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
|
||||
target,
|
||||
temporary,
|
||||
focusedWindowChangeAllowed,
|
||||
time,
|
||||
true,
|
||||
cause,
|
||||
getNativeFocusOwner());
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ HWND AwtComponent::sm_focusOwner = NULL;
|
||||
HWND AwtComponent::sm_focusedWindow = NULL;
|
||||
BOOL AwtComponent::sm_bMenuLoop = FALSE;
|
||||
BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
|
||||
BOOL AwtComponent::sm_priorityFocusEvents = FALSE;
|
||||
|
||||
/************************************************************************/
|
||||
// Struct for _Reshape() and ReshapeNoCheck() methods
|
||||
@@ -1290,6 +1291,7 @@ void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) {
|
||||
WIN_MSG(WM_AWT_COMPONENT_HIDE)
|
||||
WIN_MSG(WM_AWT_COMPONENT_SETFOCUS)
|
||||
WIN_MSG(WM_AWT_WINDOW_SETACTIVE)
|
||||
WIN_MSG(WM_AWT_WINDOW_TOFRONT)
|
||||
WIN_MSG(WM_AWT_LIST_SETMULTISELECT)
|
||||
WIN_MSG(WM_AWT_HANDLE_EVENT)
|
||||
WIN_MSG(WM_AWT_PRINT_COMPONENT)
|
||||
@@ -1955,24 +1957,38 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
* there.
|
||||
*/
|
||||
case WM_AWT_COMPONENT_SHOW:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
Show();
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
case WM_AWT_COMPONENT_HIDE:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
Hide();
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
|
||||
case WM_AWT_COMPONENT_SETFOCUS:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
if ((BOOL)wParam) {
|
||||
retValue = SynthesizeWmSetFocus(GetHWnd(), NULL);
|
||||
} else {
|
||||
retValue = SynthesizeWmKillFocus(GetHWnd(), NULL);
|
||||
}
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
case WM_AWT_WINDOW_SETACTIVE:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam);
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
case WM_AWT_WINDOW_TOFRONT:
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
((AwtWindow*)this)->ToFront();
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
mr = mrConsume;
|
||||
break;
|
||||
|
||||
|
||||
@@ -693,6 +693,7 @@ public:
|
||||
static void *GetNativeFocusOwner();
|
||||
|
||||
static BOOL sm_inSynthesizeFocus;
|
||||
static BOOL sm_priorityFocusEvents;
|
||||
|
||||
// Execute on Toolkit only.
|
||||
INLINE static LRESULT SynthesizeWmSetFocus(HWND targetHWnd, HWND oppositeHWnd) {
|
||||
|
||||
@@ -519,7 +519,9 @@ MsgRouting AwtDialog::WmEndModal()
|
||||
jobject peer = GetPeer(env);
|
||||
jobject target = GetTarget(env);
|
||||
if (::GetForegroundWindow() == GetHWnd()) {
|
||||
sm_priorityFocusEvents = TRUE;
|
||||
ModalActivateNextWindow(GetHWnd(), target, peer);
|
||||
sm_priorityFocusEvents = FALSE;
|
||||
}
|
||||
// hide the dialog
|
||||
SendMessage(WM_AWT_COMPONENT_HIDE);
|
||||
|
||||
@@ -286,7 +286,7 @@ AwtWindow::Grab() {
|
||||
// we shouldn't perform grab in this case (see 4841881 & 6539458)
|
||||
Ungrab();
|
||||
} else if (GetHWnd() != AwtComponent::GetFocusedWindow()) {
|
||||
_ToFront(env->NewGlobalRef(GetPeer(env)));
|
||||
_ToFront(env->NewGlobalRef(GetPeer(env)), FALSE);
|
||||
// Global ref was deleted in _ToFront
|
||||
}
|
||||
}
|
||||
@@ -1599,6 +1599,34 @@ void AwtWindow::SendComponentEvent(jint eventId)
|
||||
env->DeleteLocalRef(event);
|
||||
}
|
||||
|
||||
static void SendPriorityEvent(jobject event) {
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
|
||||
static jclass toolkitClass;
|
||||
if (toolkitClass == NULL) {
|
||||
toolkitClass = env->FindClass("sun/awt/SunToolkit");
|
||||
if (toolkitClass != NULL) {
|
||||
toolkitClass = (jclass)env->NewGlobalRef(toolkitClass);
|
||||
}
|
||||
if (toolkitClass == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static jmethodID postPriorityEventMID;
|
||||
if (postPriorityEventMID == NULL) {
|
||||
postPriorityEventMID =
|
||||
env->GetStaticMethodID(toolkitClass, "postPriorityEvent",
|
||||
"(Ljava/awt/AWTEvent;)V");
|
||||
DASSERT(postPriorityEventMID);
|
||||
if (postPriorityEventMID == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
env->CallStaticVoidMethod(toolkitClass, postPriorityEventMID, event);
|
||||
}
|
||||
|
||||
void AwtWindow::SendWindowEvent(jint id, HWND opposite,
|
||||
jint oldState, jint newState)
|
||||
{
|
||||
@@ -1629,25 +1657,6 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
|
||||
}
|
||||
}
|
||||
|
||||
static jclass sequencedEventCls;
|
||||
if (sequencedEventCls == NULL) {
|
||||
jclass sequencedEventClsLocal
|
||||
= env->FindClass("java/awt/SequencedEvent");
|
||||
DASSERT(sequencedEventClsLocal);
|
||||
CHECK_NULL(sequencedEventClsLocal);
|
||||
sequencedEventCls =
|
||||
(jclass)env->NewGlobalRef(sequencedEventClsLocal);
|
||||
env->DeleteLocalRef(sequencedEventClsLocal);
|
||||
}
|
||||
|
||||
static jmethodID sequencedEventConst;
|
||||
if (sequencedEventConst == NULL) {
|
||||
sequencedEventConst =
|
||||
env->GetMethodID(sequencedEventCls, "<init>",
|
||||
"(Ljava/awt/AWTEvent;)V");
|
||||
CHECK_NULL(sequencedEventConst);
|
||||
}
|
||||
|
||||
static jclass windowCls = NULL;
|
||||
if (windowCls == NULL) {
|
||||
jclass windowClsLocal = env->FindClass("java/awt/Window");
|
||||
@@ -1701,20 +1710,15 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite,
|
||||
env->DeleteLocalRef(target); target = NULL;
|
||||
CHECK_NULL(event);
|
||||
|
||||
if (id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS ||
|
||||
id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS)
|
||||
if (AwtComponent::sm_priorityFocusEvents &&
|
||||
(id == java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS ||
|
||||
id == java_awt_event_WindowEvent_WINDOW_LOST_FOCUS))
|
||||
{
|
||||
jobject sequencedEvent = env->NewObject(sequencedEventCls,
|
||||
sequencedEventConst,
|
||||
event);
|
||||
DASSERT(!safe_ExceptionOccurred(env));
|
||||
DASSERT(sequencedEvent != NULL);
|
||||
env->DeleteLocalRef(event);
|
||||
event = sequencedEvent;
|
||||
SendPriorityEvent(event);
|
||||
} else {
|
||||
SendEvent(event);
|
||||
}
|
||||
|
||||
SendEvent(event);
|
||||
|
||||
env->DeleteLocalRef(event);
|
||||
}
|
||||
|
||||
@@ -2441,7 +2445,25 @@ ret:
|
||||
return result;
|
||||
}
|
||||
|
||||
void AwtWindow::_ToFront(void *param)
|
||||
void AwtWindow::ToFront() {
|
||||
if (::IsWindow(GetHWnd())) {
|
||||
UINT flags = SWP_NOMOVE|SWP_NOSIZE;
|
||||
BOOL focusable = IsFocusableWindow();
|
||||
BOOL autoRequestFocus = IsAutoRequestFocus();
|
||||
|
||||
if (!focusable || !autoRequestFocus)
|
||||
{
|
||||
flags = flags|SWP_NOACTIVATE;
|
||||
}
|
||||
::SetWindowPos(GetHWnd(), HWND_TOP, 0, 0, 0, 0, flags);
|
||||
if (focusable && autoRequestFocus)
|
||||
{
|
||||
::SetForegroundWindow(GetHWnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AwtWindow::_ToFront(void *param, BOOL wait)
|
||||
{
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
|
||||
@@ -2454,24 +2476,20 @@ void AwtWindow::_ToFront(void *param)
|
||||
w = (AwtWindow *)pData;
|
||||
if (::IsWindow(w->GetHWnd()))
|
||||
{
|
||||
UINT flags = SWP_NOMOVE|SWP_NOSIZE;
|
||||
BOOL focusable = w->IsFocusableWindow();
|
||||
BOOL autoRequestFocus = w->IsAutoRequestFocus();
|
||||
|
||||
if (!focusable || !autoRequestFocus)
|
||||
{
|
||||
flags = flags|SWP_NOACTIVATE;
|
||||
}
|
||||
::SetWindowPos(w->GetHWnd(), HWND_TOP, 0, 0, 0, 0, flags);
|
||||
if (focusable && autoRequestFocus)
|
||||
{
|
||||
::SetForegroundWindow(w->GetHWnd());
|
||||
if (wait) {
|
||||
w->SendMessage(WM_AWT_WINDOW_TOFRONT, 0, 0);
|
||||
} else {
|
||||
w->ToFront();
|
||||
}
|
||||
}
|
||||
ret:
|
||||
env->DeleteGlobalRef(self);
|
||||
}
|
||||
|
||||
static void _ToFrontWait(void *param) {
|
||||
AwtWindow::_ToFront(param, TRUE);
|
||||
}
|
||||
|
||||
void AwtWindow::_ToBack(void *param)
|
||||
{
|
||||
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
@@ -3458,7 +3476,7 @@ Java_sun_awt_windows_WWindowPeer__1toFront(JNIEnv *env, jobject self)
|
||||
{
|
||||
TRY;
|
||||
|
||||
AwtToolkit::GetInstance().SyncCall(AwtWindow::_ToFront,
|
||||
AwtToolkit::GetInstance().SyncCall(_ToFrontWait,
|
||||
env->NewGlobalRef(self));
|
||||
// global ref is deleted in _ToFront()
|
||||
|
||||
|
||||
@@ -218,13 +218,15 @@ public:
|
||||
void UpdateWindow(JNIEnv* env, jintArray data, int width, int height,
|
||||
HBITMAP hNewBitmap = NULL);
|
||||
|
||||
void ToFront();
|
||||
|
||||
INLINE virtual BOOL IsTopLevel() { return TRUE; }
|
||||
static AwtWindow * GetGrabbedWindow() { return m_grabbedWindow; }
|
||||
|
||||
static void FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags);
|
||||
|
||||
// some methods invoked on Toolkit thread
|
||||
static void _ToFront(void *param);
|
||||
static void _ToFront(void *param, BOOL wait);
|
||||
static void _ToBack(void *param);
|
||||
static void _Grab(void *param);
|
||||
static void _Ungrab(void *param);
|
||||
|
||||
@@ -207,6 +207,7 @@ enum {
|
||||
WM_AWT_COMPONENT_HIDE,
|
||||
WM_AWT_COMPONENT_SETFOCUS,
|
||||
WM_AWT_WINDOW_SETACTIVE,
|
||||
WM_AWT_WINDOW_TOFRONT,
|
||||
WM_AWT_LIST_SETMULTISELECT,
|
||||
WM_AWT_HANDLE_EVENT,
|
||||
WM_AWT_PRINT_COMPONENT,
|
||||
|
||||
@@ -293,15 +293,16 @@ public class EventQueueMonitor
|
||||
case MouseEvent.MOUSE_MOVED:
|
||||
case MouseEvent.MOUSE_DRAGGED:
|
||||
case FocusEvent.FOCUS_GAINED:
|
||||
case WindowEvent.WINDOW_ACTIVATED:
|
||||
case WindowEvent.WINDOW_DEACTIVATED:
|
||||
queueComponentEvent((ComponentEvent) theEvent);
|
||||
break;
|
||||
|
||||
case WindowEvent.WINDOW_ACTIVATED:
|
||||
// Dialogs fire WINDOW_ACTIVATED and FOCUS_GAINED events
|
||||
// before WINDOW_OPENED so we need to add topLevelListeners
|
||||
// for the dialog when it is first activated to get a
|
||||
// focus gained event for the focus component in the dialog.
|
||||
case WindowEvent.WINDOW_GAINED_FOCUS:
|
||||
// WINDOW_GAINED_FOCUS, WINDOW_ACTIVATED and FOCUS_GAINED events
|
||||
// are fired before WINDOW_OPENED so we need to add topLevelListeners
|
||||
// for the window when it is first focused to get a
|
||||
// focus gained event for the focus component in it.
|
||||
if (theEvent instanceof ComponentEvent) {
|
||||
ComponentEvent ce = (ComponentEvent)theEvent;
|
||||
if (ce.getComponent() instanceof Window) {
|
||||
@@ -312,7 +313,6 @@ public class EventQueueMonitor
|
||||
EventQueueMonitor.addTopLevelWindow(ce.getComponent());
|
||||
}
|
||||
}
|
||||
queueComponentEvent((ComponentEvent) theEvent);
|
||||
break;
|
||||
|
||||
// handle WINDOW_OPENED and WINDOW_CLOSED events synchronously
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key headful
|
||||
* @bug 6981400
|
||||
* @summary Tabbing between textfiled do not work properly when ALT+TAB
|
||||
* @author anton.tarasov
|
||||
* @library ../../regtesthelpers
|
||||
* @build Util
|
||||
* @run main Test2
|
||||
*/
|
||||
|
||||
// A focus request made after a char is typed ahead shouldn't affect the char's target component.
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import test.java.awt.regtesthelpers.Util;
|
||||
|
||||
public class Test2 {
|
||||
static Frame f = new Frame("frame");
|
||||
static TextArea t0 = new TextArea(1, 10) { public String toString() { return "[TA-0]";} };
|
||||
static TextArea t1 = new TextArea(1, 10) { public String toString() { return "[TA-1]";} };
|
||||
static TextArea t2 = new TextArea(1, 10) { public String toString() { return "[TA-2]";} };
|
||||
|
||||
static volatile boolean passed = true;
|
||||
|
||||
static Robot robot;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
|
||||
public void eventDispatched(AWTEvent e) {
|
||||
System.out.println(e);
|
||||
if (e.getID() == KeyEvent.KEY_TYPED) {
|
||||
if (e.getSource() != t1) {
|
||||
passed = false;
|
||||
throw new RuntimeException("Test failed: the key event has wrong source: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, FocusEvent.FOCUS_EVENT_MASK | KeyEvent.KEY_EVENT_MASK);
|
||||
|
||||
try {
|
||||
robot = new Robot();
|
||||
} catch (AWTException ex) {
|
||||
throw new RuntimeException("Error: can't create Robot");
|
||||
}
|
||||
|
||||
f.add(t0);
|
||||
f.add(t1);
|
||||
f.add(t2);
|
||||
|
||||
f.setLayout(new FlowLayout());
|
||||
f.pack();
|
||||
|
||||
t0.addFocusListener(new FocusAdapter() {
|
||||
public void focusLost(FocusEvent e) {
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (Exception ex) {}
|
||||
}
|
||||
});
|
||||
|
||||
// The request shouldn't affect the key event delivery.
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (Exception ex) {}
|
||||
System.out.println("requesting focus to " + t2);
|
||||
t2.requestFocus();
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
f.setVisible(true);
|
||||
Util.waitForIdle(robot);
|
||||
|
||||
test();
|
||||
|
||||
if (passed) System.out.println("\nTest passed.");
|
||||
}
|
||||
|
||||
static void test() {
|
||||
Util.clickOnComp(t1, robot);
|
||||
|
||||
// The key event should be eventually delivered to t1.
|
||||
robot.delay(50);
|
||||
robot.keyPress(KeyEvent.VK_A);
|
||||
robot.delay(50);
|
||||
robot.keyRelease(KeyEvent.VK_A);
|
||||
|
||||
Util.waitForIdle(robot);
|
||||
}
|
||||
}
|
||||
|
||||
127
test/jdk/jb/java/awt/Focus/ModalDialogFromMenuTest.java
Normal file
127
test/jdk/jb/java/awt/Focus/ModalDialogFromMenuTest.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Test for the case which was broken during development for JBR-2712 (Typeahead mechanism doesn't work on Windows)
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class ModalDialogFromMenuTest {
|
||||
private static final CompletableFuture<Boolean> initFinished = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> menuItemShown = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> typedInDialog = new CompletableFuture<>();
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JTextField frameField;
|
||||
private static JMenuItem menuItem;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(50); // ensure different timestamps for key events (can impact typeahead logic)
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(ModalDialogFromMenuTest::initUI);
|
||||
initFinished.get(10, TimeUnit.SECONDS);
|
||||
rightClickOn(frameField);
|
||||
menuItemShown.get(10, TimeUnit.SECONDS);
|
||||
clickOn(menuItem);
|
||||
pressAndRelease(KeyEvent.VK_A);
|
||||
typedInDialog.get(10, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(ModalDialogFromMenuTest::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("ModalDialogFromMenuTest");
|
||||
frame.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
initFinished.complete(true);
|
||||
}
|
||||
});
|
||||
frameField = new JTextField(20);
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
menuItem = new JMenuItem(new AbstractAction("open dialog") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JDialog d = new JDialog(frame, true);
|
||||
JTextField dialogField = new JTextField(10);
|
||||
dialogField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
typedInDialog.complete(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {}
|
||||
});
|
||||
d.add(dialogField);
|
||||
d.pack();
|
||||
d.setVisible(true);
|
||||
}
|
||||
});
|
||||
menuItem.addHierarchyListener(e -> {
|
||||
if (menuItem.isShowing()) menuItemShown.complete(true);
|
||||
});
|
||||
menu.add(menuItem);
|
||||
frameField.setComponentPopupMenu(menu);
|
||||
frame.add(frameField);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void pressAndRelease(int keyCode) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y, int buttons) {
|
||||
robot.delay(1000); // needed for GNOME, to give it some time to update internal state after window showing
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(buttons);
|
||||
robot.mouseRelease(buttons);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component, int buttons) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2, buttons);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
clickOn(component, InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void rightClickOn(Component component) {
|
||||
clickOn(component, InputEvent.BUTTON3_DOWN_MASK);
|
||||
}
|
||||
}
|
||||
120
test/jdk/jb/java/awt/Focus/SequentialModalDialogsTest.java
Normal file
120
test/jdk/jb/java/awt/Focus/SequentialModalDialogsTest.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-2843 No caret in merge window
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class SequentialModalDialogsTest {
|
||||
private static final CompletableFuture<Boolean> initFinished = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> secondDialogShown = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> typedInDialog = new CompletableFuture<>();
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JButton frameButton;
|
||||
private static JTextField windowField;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(SequentialModalDialogsTest::initUI);
|
||||
initFinished.get(10, TimeUnit.SECONDS);
|
||||
clickOn(frameButton);
|
||||
secondDialogShown.get(10, TimeUnit.SECONDS);
|
||||
pressAndRelease(KeyEvent.VK_ENTER);
|
||||
typedInDialog.get(10, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(SequentialModalDialogsTest::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("SequentialModalDialogsTest");
|
||||
frameButton = new JButton("Open dialogs");
|
||||
frameButton.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
initFinished.complete(true);
|
||||
}
|
||||
});
|
||||
frameButton.addActionListener(e -> {
|
||||
showDialogs();
|
||||
});
|
||||
frame.add(frameButton);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void showDialogs() {
|
||||
JDialog d1 = new JDialog(frame, true);
|
||||
JTextField t1 = new JTextField("dialog 1");
|
||||
t1.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
// using invokeLater to emulate some moment after dialog showing
|
||||
SwingUtilities.invokeLater(() -> d1.setVisible(false));
|
||||
}
|
||||
});
|
||||
d1.add(t1);
|
||||
d1.pack();
|
||||
d1.setVisible(true);
|
||||
JDialog d2 = new JDialog(frame, true);
|
||||
JTextField t2 = new JTextField("dialog 2");
|
||||
t2.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
// using invokeLater to emulate some moment after dialog showing
|
||||
SwingUtilities.invokeLater(() -> secondDialogShown.complete(true));
|
||||
}
|
||||
});
|
||||
t2.addActionListener(e -> typedInDialog.complete(true));
|
||||
d2.add(t2);
|
||||
d2.pack();
|
||||
d2.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void pressAndRelease(int keyCode) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.delay(1000); // needed for GNOME, to give it some time to update internal state after window showing
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
116
test/jdk/jb/java/awt/Focus/TypeaheadRequestFocusTest.java
Normal file
116
test/jdk/jb/java/awt/Focus/TypeaheadRequestFocusTest.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-2712 Typeahead mechanism doesn't work on Windows
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class TypeaheadRequestFocusTest {
|
||||
private static final CompletableFuture<Boolean> initFinished = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> typedInPopup = new CompletableFuture<>();
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JTextField frameField;
|
||||
private static JTextField windowField;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(50); // ensure different timestamps for key events (can impact typeahead logic)
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(TypeaheadRequestFocusTest::initUI);
|
||||
initFinished.get(10, TimeUnit.SECONDS);
|
||||
clickOn(frameField);
|
||||
SwingUtilities.invokeAndWait(TypeaheadRequestFocusTest::showPopup);
|
||||
pressAndRelease(KeyEvent.VK_ENTER);
|
||||
pressAndRelease(KeyEvent.VK_A);
|
||||
typedInPopup.get(10, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(TypeaheadRequestFocusTest::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("TypeaheadRequestFocusTest");
|
||||
frame.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
initFinished.complete(true);
|
||||
}
|
||||
});
|
||||
frameField = new JTextField(20);
|
||||
frameField.addActionListener(e -> {
|
||||
LockSupport.parkNanos(1_000_000_000L);
|
||||
windowField.requestFocus();
|
||||
});
|
||||
frame.add(frameField);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void showPopup() {
|
||||
JWindow window = new JWindow(frame);
|
||||
windowField = new JTextField(20);
|
||||
windowField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
typedInPopup.complete(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {}
|
||||
});
|
||||
window.add(windowField);
|
||||
window.pack();
|
||||
window.setAutoRequestFocus(false);
|
||||
window.setVisible(true);
|
||||
window.setAutoRequestFocus(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void pressAndRelease(int keyCode) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.delay(1000); // needed for GNOME, to give it some time to update internal state after window showing
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
108
test/jdk/jb/java/awt/Focus/TypeaheadSetVisibleTest.java
Normal file
108
test/jdk/jb/java/awt/Focus/TypeaheadSetVisibleTest.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-2712 Typeahead mechanism doesn't work on Windows
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class TypeaheadSetVisibleTest {
|
||||
private static final CompletableFuture<Boolean> initFinished = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> typedInPopup = new CompletableFuture<>();
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JTextField frameField;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(50); // ensure different timestamps for key events (can impact typeahead logic)
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(TypeaheadSetVisibleTest::initUI);
|
||||
initFinished.get(10, TimeUnit.SECONDS);
|
||||
clickOn(frameField);
|
||||
pressAndRelease(KeyEvent.VK_ENTER);
|
||||
pressAndRelease(KeyEvent.VK_A);
|
||||
typedInPopup.get(10, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(TypeaheadSetVisibleTest::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("TypeaheadSetVisibleTest");
|
||||
frame.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
initFinished.complete(true);
|
||||
}
|
||||
});
|
||||
frameField = new JTextField(20);
|
||||
frameField.addActionListener(e -> {
|
||||
LockSupport.parkNanos(1_000_000_000L);
|
||||
JWindow window = new JWindow(frame);
|
||||
JTextField windowField = new JTextField(20);
|
||||
windowField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
typedInPopup.complete(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {}
|
||||
});
|
||||
window.add(windowField);
|
||||
window.pack();
|
||||
window.setVisible(true);
|
||||
});
|
||||
frame.add(frameField);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void pressAndRelease(int keyCode) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.delay(1000); // needed for GNOME, to give it some time to update internal state after window showing
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
116
test/jdk/jb/java/awt/Focus/TypeaheadToFrontTest.java
Normal file
116
test/jdk/jb/java/awt/Focus/TypeaheadToFrontTest.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2000-2020 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Regression test for JBR-2712 Typeahead mechanism doesn't work on Windows
|
||||
* @key headful
|
||||
*/
|
||||
|
||||
public class TypeaheadToFrontTest {
|
||||
private static final CompletableFuture<Boolean> initFinished = new CompletableFuture<>();
|
||||
private static final CompletableFuture<Boolean> typedInPopup = new CompletableFuture<>();
|
||||
private static Robot robot;
|
||||
private static JFrame frame;
|
||||
private static JTextField frameField;
|
||||
private static JWindow window;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(50); // ensure different timestamps for key events (can impact typeahead logic)
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(TypeaheadToFrontTest::initUI);
|
||||
initFinished.get(10, TimeUnit.SECONDS);
|
||||
clickOn(frameField);
|
||||
SwingUtilities.invokeAndWait(TypeaheadToFrontTest::showPopup);
|
||||
pressAndRelease(KeyEvent.VK_ENTER);
|
||||
pressAndRelease(KeyEvent.VK_A);
|
||||
typedInPopup.get(10, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(TypeaheadToFrontTest::disposeUI);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initUI() {
|
||||
frame = new JFrame("TypeaheadToFrontTest");
|
||||
frame.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
initFinished.complete(true);
|
||||
}
|
||||
});
|
||||
frameField = new JTextField(20);
|
||||
frameField.addActionListener(e -> {
|
||||
LockSupport.parkNanos(1_000_000_000L);
|
||||
window.toFront();
|
||||
});
|
||||
frame.add(frameField);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void showPopup() {
|
||||
window = new JWindow(frame);
|
||||
JTextField windowField = new JTextField(20);
|
||||
windowField.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
typedInPopup.complete(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {}
|
||||
});
|
||||
window.add(windowField);
|
||||
window.pack();
|
||||
window.setAutoRequestFocus(false);
|
||||
window.setVisible(true);
|
||||
window.setAutoRequestFocus(true);
|
||||
}
|
||||
|
||||
private static void disposeUI() {
|
||||
if (frame != null) frame.dispose();
|
||||
}
|
||||
|
||||
private static void pressAndRelease(int keyCode) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
}
|
||||
|
||||
private static void clickAt(int x, int y) {
|
||||
robot.delay(1000); // needed for GNOME, to give it some time to update internal state after window showing
|
||||
robot.mouseMove(x, y);
|
||||
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
|
||||
}
|
||||
|
||||
private static void clickOn(Component component) {
|
||||
Point location = component.getLocationOnScreen();
|
||||
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user