8056914: Right Click Menu for Paste not showing after upgrading to java 7
Reviewed-by: serb, bae
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp Fri Sep 26 18:43:44 2014 +0400
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp Tue Sep 30 14:51:33 2014 +0400
@@ -47,16 +47,12 @@
jfieldID AwtTextArea::scrollbarVisibilityID;
-WNDPROC AwtTextArea::sm_pDefWindowProc = NULL;
-
/************************************************************************
* AwtTextArea methods
*/
AwtTextArea::AwtTextArea() {
- m_bIgnoreEnChange = FALSE;
m_bCanUndo = FALSE;
- m_hEditCtrl = NULL;
m_lHDeltaAccum = 0;
m_lVDeltaAccum = 0;
}
@@ -67,10 +63,6 @@
void AwtTextArea::Dispose()
{
- if (m_hEditCtrl != NULL) {
- VERIFY(::DestroyWindow(m_hEditCtrl));
- m_hEditCtrl = NULL;
- }
AwtTextComponent::Dispose();
}
@@ -91,10 +83,6 @@
}
}
-void AwtTextArea::EditGetSel(CHARRANGE &cr) {
- SendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&cr));
-}
-
/* Count how many '\n's are there in jStr */
size_t AwtTextArea::CountNewLines(JNIEnv *env, jstring jStr, size_t maxlen)
{
@@ -149,159 +137,6 @@
return retValue;
}
-/*
- * This routine is a window procedure for the subclass of the standard edit control
- * used to generate context menu. RichEdit controls don't have built-in context menu.
- * To implement this functionality we have to create an invisible edit control and
- * forward WM_CONTEXTMENU messages from a RichEdit control to this helper edit control.
- * While the edit control context menu is active we intercept the message generated in
- * response to particular item selection and forward it back to the RichEdit control.
- * (See AwtTextArea::WmContextMenu for more details).
- */
-LRESULT
-AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
-
- static BOOL bContextMenuActive = FALSE;
-
- LRESULT retValue = 0;
- MsgRouting mr = mrDoDefault;
-
- DASSERT(::IsWindow(::GetParent(hWnd)));
-
- switch (message) {
- case WM_UNDO:
- case WM_CUT:
- case WM_COPY:
- case WM_PASTE:
- case WM_CLEAR:
- case EM_SETSEL:
- if (bContextMenuActive) {
- ::SendMessage(::GetParent(hWnd), message, wParam, lParam);
- mr = mrConsume;
- }
- break;
- case WM_CONTEXTMENU:
- bContextMenuActive = TRUE;
- break;
- }
-
- if (mr == mrDoDefault) {
- DASSERT(sm_pDefWindowProc != NULL);
- retValue = ::CallWindowProc(sm_pDefWindowProc,
- hWnd, message, wParam, lParam);
- }
-
- if (message == WM_CONTEXTMENU) {
- bContextMenuActive = FALSE;
- }
-
- return retValue;
-}
-
-MsgRouting
-AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
- /* Use the system provided edit control class to generate context menu. */
- if (m_hEditCtrl == NULL) {
- DWORD dwStyle = WS_CHILD;
- DWORD dwExStyle = 0;
- m_hEditCtrl = ::CreateWindowEx(dwExStyle,
- L"EDIT",
- L"TEXT",
- dwStyle,
- 0, 0, 0, 0,
- GetHWnd(),
- reinterpret_cast<HMENU>(
- static_cast<INT_PTR>(
- CreateControlID())),
- AwtToolkit::GetInstance().GetModuleHandle(),
- NULL);
- DASSERT(m_hEditCtrl != NULL);
- if (sm_pDefWindowProc == NULL) {
- sm_pDefWindowProc = (WNDPROC)::GetWindowLongPtr(m_hEditCtrl,
- GWLP_WNDPROC);
- }
- ::SetLastError(0);
- INT_PTR ret = ::SetWindowLongPtr(m_hEditCtrl, GWLP_WNDPROC,
- (INT_PTR)AwtTextArea::EditProc);
- DASSERT(ret != 0 || ::GetLastError() == 0);
- }
-
- /*
- * Tricks on the edit control to ensure that its context menu has
- * the correct set of enabled items according to the RichEdit state.
- */
- ::SetWindowText(m_hEditCtrl, TEXT("TEXT"));
-
- if (m_bCanUndo == TRUE && SendMessage(EM_CANUNDO)) {
- /* Enable 'Undo' item. */
- ::SendMessage(m_hEditCtrl, WM_CHAR, 'A', 0);
- }
-
- {
- /*
- * Initial selection for the edit control - (0,1).
- * This enables 'Cut', 'Copy' and 'Delete' and 'Select All'.
- */
- INT nStart = 0;
- INT nEnd = 1;
- if (SendMessage(EM_SELECTIONTYPE) == SEL_EMPTY) {
- /*
- * RichEdit selection is empty - clear selection of the edit control.
- * This disables 'Cut', 'Copy' and 'Delete'.
- */
- nStart = -1;
- nEnd = 0;
- } else {
-
- CHARRANGE cr;
- EditGetSel(cr);
- /* Check if all the text is selected. */
- if (cr.cpMin == 0) {
-
- int len = ::GetWindowTextLength(GetHWnd());
- if (cr.cpMin == 0 && cr.cpMax >= len) {
- /*
- * All the text is selected in RichEdit - select all the
- * text in the edit control. This disables 'Select All'.
- */
- nStart = 0;
- nEnd = -1;
- }
- }
- }
- ::SendMessage(m_hEditCtrl, EM_SETSEL, (WPARAM)nStart, (LPARAM)nEnd);
- }
-
- /* Disable 'Paste' item if the RichEdit control is read-only. */
- ::SendMessage(m_hEditCtrl, EM_SETREADONLY,
- GetStyle() & ES_READONLY ? TRUE : FALSE, 0);
-
- POINT p;
- p.x = xPos;
- p.y = yPos;
-
- /*
- * If the context menu is requested with SHIFT+F10 or VK_APPS key,
- * we position its top left corner to the center of the RichEdit
- * client rect.
- */
- if (p.x == -1 && p.y == -1) {
- RECT r;
- VERIFY(::GetClientRect(GetHWnd(), &r));
- p.x = (r.left + r.right) / 2;
- p.y = (r.top + r.bottom) / 2;
- VERIFY(::ClientToScreen(GetHWnd(), &p));
- }
-
- // The context menu steals focus from the proxy.
- // So, set the focus-restore flag up.
- SetRestoreFocus(TRUE);
- ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y));
- SetRestoreFocus(FALSE);
-
- return mrConsume;
-}
-
MsgRouting
AwtTextArea::WmNcHitTest(UINT x, UINT y, LRESULT& retVal)
{
@@ -314,27 +149,8 @@
MsgRouting
-AwtTextArea::WmNotify(UINT notifyCode)
-{
- if (notifyCode == EN_CHANGE) {
- /*
- * Ignore notifications if the text hasn't been changed.
- * EN_CHANGE sent on character formatting changes as well.
- */
- if (m_bIgnoreEnChange == FALSE) {
- m_bCanUndo = TRUE;
- DoCallback("valueChanged", "()V");
- } else {
- m_bCanUndo = FALSE;
- }
- }
- return mrDoDefault;
-}
-
-MsgRouting
AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic)
{
- MsgRouting returnVal;
/*
* RichEdit 1.0 control starts internal message loop if the
* left mouse button is pressed while the cursor is not over
@@ -486,26 +302,6 @@
}
delete msg;
return mrConsume;
- } else if (msg->message == WM_RBUTTONUP ||
- (msg->message == WM_SYSKEYDOWN && msg->wParam == VK_F10 &&
- HIBYTE(::GetKeyState(VK_SHIFT)))) {
- POINT p;
- if (msg->message == WM_RBUTTONUP) {
- VERIFY(::GetCursorPos(&p));
- } else {
- p.x = -1;
- p.y = -1;
- }
-
- if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(),
- MAKELPARAM(p.x, p.y))) {
- JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
- JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
- env->ExceptionDescribe();
- env->ExceptionClear();
- }
- delete msg;
- return mrConsume;
} else if (msg->message == WM_MOUSEWHEEL) {
// 4417236: If there is an old version of RichEd32.dll which
// does not provide the mouse wheel scrolling we have to
@@ -596,15 +392,7 @@
// 4417236: end of fix
}
- /*
- * Store the 'synthetic' parameter so that the WM_PASTE security check
- * happens only for synthetic events.
- */
- m_synthetic = synthetic;
- returnVal = AwtComponent::HandleEvent(msg, synthetic);
- m_synthetic = FALSE;
-
- return returnVal;
+ return AwtTextComponent::HandleEvent(msg, synthetic);
}
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h Fri Sep 26 18:43:44 2014 +0400
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h Tue Sep 30 14:51:33 2014 +0400
@@ -57,17 +57,11 @@
static size_t GetALength(JNIEnv* env, jstring jStr, size_t maxlen);
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
- static LRESULT CALLBACK EditProc(HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam);
MsgRouting WmEnable(BOOL fEnabled);
- MsgRouting WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos);
- MsgRouting WmNotify(UINT notifyCode);
MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT &retVal);
MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
- INLINE void SetIgnoreEnChange(BOOL b) { m_bIgnoreEnChange = b; }
-
virtual BOOL InheritsNativeMouseWheelBehavior();
virtual void Reshape(int x, int y, int w, int h);
@@ -81,22 +75,7 @@
protected:
void EditSetSel(CHARRANGE &cr);
- void EditGetSel(CHARRANGE &cr);
private:
- // RichEdit 1.0 control generates EN_CHANGE notifications not only
- // on text changes, but also on any character formatting change.
- // This flag is true when the latter case is detected.
- BOOL m_bIgnoreEnChange;
-
- // RichEdit 1.0 control undoes a character formatting change
- // if it is the latest. We don't create our own undo buffer,
- // but just prohibit undo in case if the latest operation
- // is a formatting change.
- BOOL m_bCanUndo;
-
- HWND m_hEditCtrl;
- static WNDPROC sm_pDefWindowProc;
-
LONG m_lHDeltaAccum;
LONG m_lVDeltaAccum;
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp Fri Sep 26 18:43:44 2014 +0400
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp Tue Sep 30 14:51:33 2014 +0400
@@ -66,6 +66,8 @@
m_lLastPos = -1;
m_isLFonly = FALSE;
m_EOLchecked = FALSE;
+ m_hEditCtrl = NULL;
+ m_bIgnoreEnChange = FALSE;
// javaEventsMask = 0; // accessibility support
}
@@ -213,6 +215,16 @@
return c;
}
+void AwtTextComponent::Dispose()
+{
+ if (m_hEditCtrl != NULL) {
+ VERIFY(::DestroyWindow(m_hEditCtrl));
+ m_hEditCtrl = NULL;
+ }
+ AwtComponent::Dispose();
+}
+
+
LRESULT
AwtTextComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
@@ -322,7 +334,16 @@
AwtTextComponent::WmNotify(UINT notifyCode)
{
if (notifyCode == EN_CHANGE) {
- DoCallback("valueChanged", "()V");
+ /*
+ * Ignore notifications if the text hasn't been changed.
+ * EN_CHANGE sent on character formatting changes as well.
+ */
+ if (m_bIgnoreEnChange == FALSE) {
+ m_bCanUndo = TRUE;
+ DoCallback("valueChanged", "()V");
+ } else {
+ m_bCanUndo = FALSE;
+ }
}
return mrDoDefault;
}
@@ -337,6 +358,28 @@
{
MsgRouting returnVal;
+ if (msg->message == WM_RBUTTONUP ||
+ (msg->message == WM_SYSKEYDOWN && msg->wParam == VK_F10 &&
+ HIBYTE(::GetKeyState(VK_SHIFT)))) {
+ POINT p;
+ if (msg->message == WM_RBUTTONUP) {
+ VERIFY(::GetCursorPos(&p));
+ } else {
+ p.x = -1;
+ p.y = -1;
+ }
+
+ if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(),
+ MAKELPARAM(p.x, p.y))) {
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ JNU_ThrowInternalError(env, "Message not posted, native event queue may be full.");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+ delete msg;
+ return mrConsume;
+ }
+
/*
* Store the 'synthetic' parameter so that the WM_PASTE security check
* happens only for synthetic events.
@@ -701,6 +744,10 @@
SendMessage(EM_SETBKGNDCOLOR, (WPARAM)FALSE, (LPARAM)GetBackgroundColor());
}
+void AwtTextComponent::EditGetSel(CHARRANGE &cr) {
+ SendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&cr));
+}
+
/************************************************************************
* WTextComponentPeer native methods
@@ -983,6 +1030,161 @@
}
+/*
+ * This routine is a window procedure for the subclass of the standard edit control
+ * used to generate context menu. RichEdit controls don't have built-in context menu.
+ * To implement this functionality we have to create an invisible edit control and
+ * forward WM_CONTEXTMENU messages from a RichEdit control to this helper edit control.
+ * While the edit control context menu is active we intercept the message generated in
+ * response to particular item selection and forward it back to the RichEdit control.
+ * (See AwtTextArea::WmContextMenu for more details).
+ */
+
+WNDPROC AwtTextComponent::sm_pDefWindowProc = NULL;
+
+LRESULT
+AwtTextComponent::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+
+ static BOOL bContextMenuActive = FALSE;
+
+ LRESULT retValue = 0;
+ MsgRouting mr = mrDoDefault;
+
+ DASSERT(::IsWindow(::GetParent(hWnd)));
+
+ switch (message) {
+ case WM_UNDO:
+ case WM_CUT:
+ case WM_COPY:
+ case WM_PASTE:
+ case WM_CLEAR:
+ case EM_SETSEL:
+ if (bContextMenuActive) {
+ ::SendMessage(::GetParent(hWnd), message, wParam, lParam);
+ mr = mrConsume;
+ }
+ break;
+ case WM_CONTEXTMENU:
+ bContextMenuActive = TRUE;
+ break;
+ }
+
+ if (mr == mrDoDefault) {
+ DASSERT(sm_pDefWindowProc != NULL);
+ retValue = ::CallWindowProc(sm_pDefWindowProc,
+ hWnd, message, wParam, lParam);
+ }
+
+ if (message == WM_CONTEXTMENU) {
+ bContextMenuActive = FALSE;
+ }
+
+ return retValue;
+}
+
+MsgRouting
+AwtTextComponent::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) {
+ /* Use the system provided edit control class to generate context menu. */
+ if (m_hEditCtrl == NULL) {
+ DWORD dwStyle = WS_CHILD;
+ DWORD dwExStyle = 0;
+ m_hEditCtrl = ::CreateWindowEx(dwExStyle,
+ L"EDIT",
+ L"TEXT",
+ dwStyle,
+ 0, 0, 0, 0,
+ GetHWnd(),
+ reinterpret_cast<HMENU>(
+ static_cast<INT_PTR>(
+ CreateControlID())),
+ AwtToolkit::GetInstance().GetModuleHandle(),
+ NULL);
+ DASSERT(m_hEditCtrl != NULL);
+ if (sm_pDefWindowProc == NULL) {
+ sm_pDefWindowProc = (WNDPROC)::GetWindowLongPtr(m_hEditCtrl,
+ GWLP_WNDPROC);
+ }
+ ::SetLastError(0);
+ INT_PTR ret = ::SetWindowLongPtr(m_hEditCtrl, GWLP_WNDPROC,
+ (INT_PTR)AwtTextArea::EditProc);
+ DASSERT(ret != 0 || ::GetLastError() == 0);
+ }
+
+ /*
+ * Tricks on the edit control to ensure that its context menu has
+ * the correct set of enabled items according to the RichEdit state.
+ */
+ ::SetWindowText(m_hEditCtrl, TEXT("TEXT"));
+
+ if (m_bCanUndo == TRUE && SendMessage(EM_CANUNDO)) {
+ /* Enable 'Undo' item. */
+ ::SendMessage(m_hEditCtrl, WM_CHAR, 'A', 0);
+ }
+
+ {
+ /*
+ * Initial selection for the edit control - (0,1).
+ * This enables 'Cut', 'Copy' and 'Delete' and 'Select All'.
+ */
+ INT nStart = 0;
+ INT nEnd = 1;
+ if (SendMessage(EM_SELECTIONTYPE) == SEL_EMPTY) {
+ /*
+ * RichEdit selection is empty - clear selection of the edit control.
+ * This disables 'Cut', 'Copy' and 'Delete'.
+ */
+ nStart = -1;
+ nEnd = 0;
+ } else {
+
+ CHARRANGE cr;
+ EditGetSel(cr);
+ /* Check if all the text is selected. */
+ if (cr.cpMin == 0) {
+
+ int len = ::GetWindowTextLength(GetHWnd());
+ if (cr.cpMin == 0 && cr.cpMax >= len) {
+ /*
+ * All the text is selected in RichEdit - select all the
+ * text in the edit control. This disables 'Select All'.
+ */
+ nStart = 0;
+ nEnd = -1;
+ }
+ }
+ }
+ ::SendMessage(m_hEditCtrl, EM_SETSEL, (WPARAM)nStart, (LPARAM)nEnd);
+ }
+
+ /* Disable 'Paste' item if the RichEdit control is read-only. */
+ ::SendMessage(m_hEditCtrl, EM_SETREADONLY,
+ GetStyle() & ES_READONLY ? TRUE : FALSE, 0);
+
+ POINT p;
+ p.x = xPos;
+ p.y = yPos;
+
+ /*
+ * If the context menu is requested with SHIFT+F10 or VK_APPS key,
+ * we position its top left corner to the center of the RichEdit
+ * client rect.
+ */
+ if (p.x == -1 && p.y == -1) {
+ RECT r;
+ VERIFY(::GetClientRect(GetHWnd(), &r));
+ p.x = (r.left + r.right) / 2;
+ p.y = (r.top + r.bottom) / 2;
+ VERIFY(::ClientToScreen(GetHWnd(), &p));
+ }
+
+ // The context menu steals focus from the proxy.
+ // So, set the focus-restore flag up.
+ SetRestoreFocus(TRUE);
+ ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y));
+ SetRestoreFocus(FALSE);
+
+ return mrConsume;
+}
//
// Accessibility support
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.h Fri Sep 26 18:43:44 2014 +0400
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.h Tue Sep 30 14:51:33 2014 +0400
@@ -47,6 +47,8 @@
static AwtTextComponent* Create(jobject self, jobject parent, BOOL isMultiline);
+ virtual void Dispose();
+
virtual LPCTSTR GetClassName();
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
@@ -83,6 +85,8 @@
MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
MsgRouting WmPaste();
+ INLINE void SetIgnoreEnChange(BOOL b) { m_bIgnoreEnChange = b; }
+
virtual BOOL IsFocusingMouseMessage(MSG *pMsg);
/* To be fully implemented in a future release
@@ -115,11 +119,24 @@
INLINE VOID SetEndSelectionPos(LONG lPos) { m_lEndPos = lPos; }
INLINE VOID SetLastSelectionPos(LONG lPos) { m_lLastPos = lPos; }
+ void EditGetSel(CHARRANGE &cr);
+
// Used to prevent untrusted code from synthesizing a WM_PASTE message
// by posting a <CTRL>-V KeyEvent
BOOL m_synthetic;
LONG EditGetCharFromPos(POINT& pt);
+ // RichEdit 1.0 control generates EN_CHANGE notifications not only
+ // on text changes, but also on any character formatting change.
+ // This flag is true when the latter case is detected.
+ BOOL m_bIgnoreEnChange;
+
+ // RichEdit 1.0 control undoes a character formatting change
+ // if it is the latest. We don't create our own undo buffer,
+ // but just prohibit undo in case if the latest operation
+ // is a formatting change.
+ BOOL m_bCanUndo;
+
/*****************************************************************
* Inner class OleCallback declaration.
*/
@@ -166,6 +183,13 @@
static OleCallback sm_oleCallback;
+ static WNDPROC sm_pDefWindowProc;
+ HWND m_hEditCtrl;
+
+ static LRESULT CALLBACK EditProc(HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+ MsgRouting WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos);
+
//
// Accessibility support
//
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp Fri Sep 26 18:43:44 2014 +0400
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp Tue Sep 30 14:51:33 2014 +0400
@@ -249,13 +249,7 @@
}
}
- /*
- * Store the 'synthetic' parameter so that the WM_PASTE security check
- * happens only for synthetic events.
- */
- m_synthetic = synthetic;
- returnVal = AwtComponent::HandleEvent(msg, synthetic);
- m_synthetic = FALSE;
+ returnVal = AwtTextComponent::HandleEvent(msg, synthetic);
if(systemBeeperEnabled){
SystemParametersInfo(SPI_SETBEEP, 1, NULL, 0);