# HG changeset patch
# User Daniel Kozar <dkk089@gmail.com>
# Date 1596141309 -7200
#      Thu Jul 30 22:35:09 2020 +0200
# Node ID f8c781fe18c84a3af4e8f15113d1535bafb62634
# Parent  447366afcf86292bd16c1a9021ac8d88004356ba
Use new APIs on Windows for monitoring available clipboard formats

This change replaces the usage of SetClipboardViewer with
Add/RemoveClipboardFormatListener, introduced in Windows Vista. This makes
OpenJDK immune to external applications failing to process clipboard messages
properly.

diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp
--- a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.cpp
@@ -42,9 +42,7 @@
 BOOL AwtClipboard::isGettingOwnership = FALSE;
 
 volatile jmethodID AwtClipboard::handleContentsChangedMID;
-volatile BOOL AwtClipboard::skipInitialWmDrawClipboardMsg = TRUE;
 volatile BOOL AwtClipboard::isClipboardViewerRegistered = FALSE;
-volatile HWND AwtClipboard::hwndNextViewer = NULL;
 
 #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT)
 
@@ -59,27 +57,11 @@
     }
 }
 
-void AwtClipboard::WmChangeCbChain(WPARAM wParam, LPARAM lParam) {
-    if ((HWND)wParam == hwndNextViewer) {
-        hwndNextViewer = (HWND)lParam;
-    } else if (hwndNextViewer != NULL) {
-        ::SendMessage(hwndNextViewer, WM_CHANGECBCHAIN, wParam, lParam);
-    }
-}
-
-void AwtClipboard::WmDrawClipboard(JNIEnv *env, WPARAM wParam, LPARAM lParam) {
-    if (skipInitialWmDrawClipboardMsg) {
-        // skipping the first contents change notification as it comes
-        // immediately after registering the clipboard viewer window
-        // and it is not caused by an actual contents change.
-        skipInitialWmDrawClipboardMsg = FALSE;
-        return;
-    }
+void AwtClipboard::WmClipboardUpdate(JNIEnv *env) {
     if (theCurrentClipboard != NULL) {
         env->CallVoidMethod(theCurrentClipboard, handleContentsChangedMID);
         DASSERT(!safe_ExceptionOccurred(env));
     }
-    ::SendMessage(hwndNextViewer, WM_DRAWCLIPBOARD, wParam, lParam);
 }
 
 void AwtClipboard::RegisterClipboardViewer(JNIEnv *env, jobject jclipboard) {
@@ -96,7 +78,7 @@
             env->GetMethodID(cls, "handleContentsChanged", "()V");
     DASSERT(AwtClipboard::handleContentsChangedMID != NULL);
 
-    hwndNextViewer = ::SetClipboardViewer(AwtToolkit::GetInstance().GetHWnd());
+    ::AddClipboardFormatListener(AwtToolkit::GetInstance().GetHWnd());
     isClipboardViewerRegistered = TRUE;
 }
 
@@ -104,10 +86,8 @@
     TRY;
 
     if (isClipboardViewerRegistered) {
-        ::ChangeClipboardChain(AwtToolkit::GetInstance().GetHWnd(), AwtClipboard::hwndNextViewer);
-        AwtClipboard::hwndNextViewer = NULL;
+        ::RemoveClipboardFormatListener(AwtToolkit::GetInstance().GetHWnd());
         isClipboardViewerRegistered = FALSE;
-        skipInitialWmDrawClipboardMsg = TRUE;
     }
 
     CATCH_BAD_ALLOC;
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h
--- a/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Clipboard.h
@@ -36,10 +36,7 @@
 class AwtClipboard {
 private:
     static BOOL isGettingOwnership;
-    // handle to the next window in the clipboard viewer chain
-    static volatile HWND hwndNextViewer;
     static volatile BOOL isClipboardViewerRegistered;
-    static volatile BOOL skipInitialWmDrawClipboardMsg;
     static volatile jmethodID handleContentsChangedMID;
 
 public:
@@ -57,8 +54,7 @@
     }
 
     static void LostOwnership(JNIEnv *env);
-    static void WmChangeCbChain(WPARAM wparam, LPARAM lparam);
-    static void WmDrawClipboard(JNIEnv *env, WPARAM wparam, LPARAM lparam);
+    static void WmClipboardUpdate(JNIEnv *env);
     static void RegisterClipboardViewer(JNIEnv *env, jobject jclipboard);
     static void UnregisterClipboardViewer(JNIEnv *env);
 };
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
--- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
@@ -1065,12 +1065,8 @@
               AwtClipboard::LostOwnership((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2));
           return 0;
       }
-      case WM_CHANGECBCHAIN: {
-          AwtClipboard::WmChangeCbChain(wParam, lParam);
-          return 0;
-      }
-      case WM_DRAWCLIPBOARD: {
-          AwtClipboard::WmDrawClipboard((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), wParam, lParam);
+      case WM_CLIPBOARDUPDATE: {
+          AwtClipboard::WmClipboardUpdate((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2));
           return 0;
       }
       case WM_AWT_LIST_SETMULTISELECT: {
diff --git a/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java b/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java
--- a/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java
+++ b/test/jdk/java/awt/datatransfer/ClipboardInterVMTest/ClipboardInterVMTest.java
@@ -83,7 +83,7 @@
             }
         });
 
-        System.out.println("Starting external clipborad modifier...");
+        System.out.println("Starting external clipboard modifier...");
         new Thread(() -> runTest(ClipboardInterVMTest.class.getCanonicalName(), "pong")).start();
 
         String content = "";
@@ -106,7 +106,7 @@
         };
 
         if (!flavorChangedMonitor.await(10, TimeUnit.SECONDS)) {
-            throw new RuntimeException("No LostOwnership event received.");
+            throw new RuntimeException("No FlavorsChanged event received.");
         };
 
         if (!content.equals("pong")) {
