Bug 326743: add find clipboard to the list of available clipboard on OSX. r=joshmoz
authorMike de Boer <mdeboer@mozilla.com>
Fri, 28 Feb 2014 16:07:30 +0100
changeset 188383 0acfd7cfea948de87fcd8374e7906ffc3fbb41cc
parent 188382 e942764f652704a3f2fbb914117e55621e485084
child 188384 ce1491d00b42d11eb3a3435cd2967fb6b926b644
push idunknown
push userunknown
push dateunknown
reviewersjoshmoz
bugs326743
milestone30.0a1
Bug 326743: add find clipboard to the list of available clipboard on OSX. r=joshmoz
widget/android/nsClipboard.cpp
widget/cocoa/nsClipboard.h
widget/cocoa/nsClipboard.mm
widget/gtk/nsClipboard.cpp
widget/nsIClipboard.idl
widget/qt/nsClipboard.cpp
widget/xpwidgets/nsBaseClipboard.cpp
widget/xpwidgets/nsClipboardHelper.cpp
widget/xpwidgets/nsClipboardProxy.cpp
--- a/widget/android/nsClipboard.cpp
+++ b/widget/android/nsClipboard.cpp
@@ -104,8 +104,14 @@ nsClipboard::HasDataMatchingFlavors(cons
 
 NS_IMETHODIMP
 nsClipboard::SupportsSelectionClipboard(bool *aIsSupported)
 {
   *aIsSupported = false;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsClipboard::SupportsFindClipboard(bool* _retval)
+{
+  *_retval = false;
+  return NS_OK;
+}
--- a/widget/cocoa/nsClipboard.h
+++ b/widget/cocoa/nsClipboard.h
@@ -18,27 +18,33 @@ class nsClipboard : public nsBaseClipboa
 
 public:
   nsClipboard();
   virtual ~nsClipboard();
 
   // nsIClipboard  
   NS_IMETHOD HasDataMatchingFlavors(const char** aFlavorList, uint32_t aLength,
                                     int32_t aWhichClipboard, bool *_retval);
+  NS_IMETHOD SupportsFindClipboard(bool *_retval);
 
   // Helper methods, used also by nsDragService
   static NSDictionary* PasteboardDictFromTransferable(nsITransferable *aTransferable);
   static bool IsStringType(const nsCString& aMIMEType, NSString** aPasteboardType);
   static NSString* WrapHtmlForSystemPasteboard(NSString* aString);
   static nsresult TransferableFromPasteboard(nsITransferable *aTransferable, NSPasteboard *pboard);
 
 protected:
 
   // impelement the native clipboard behavior
   NS_IMETHOD SetNativeClipboardData(int32_t aWhichClipboard);
   NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable, int32_t aWhichClipboard);
   
 private:
-  int mChangeCount; // this is always set to the native change count after any clipboard modifications
+  // This is always set to the native change count after any modification of the
+  // general clipboard.
+  int mChangeCountGeneral;
+  // This is always set to the native change count after any modification of the
+  // find clipboard.
+  int mChangeCountFind;
 
 };
 
 #endif // nsClipboard_h_
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -30,17 +30,18 @@
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* sCocoaLog;
 #endif
 
 extern void EnsureLogInitialized();
 
 nsClipboard::nsClipboard() : nsBaseClipboard()
 {
-  mChangeCount = 0;
+  mChangeCountGeneral = 0;
+  mChangeCountFind = 0;
 
   EnsureLogInitialized();
 }
 
 nsClipboard::~nsClipboard()
 {
 }
 
@@ -60,47 +61,63 @@ GetDataFromPasteboard(NSPasteboard* aPas
   return data;
 }
 
 NS_IMETHODIMP
 nsClipboard::SetNativeClipboardData(int32_t aWhichClipboard)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  if ((aWhichClipboard != kGlobalClipboard) || !mTransferable)
+  if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !mTransferable)
     return NS_ERROR_FAILURE;
 
   mIgnoreEmptyNotification = true;
 
   NSDictionary* pasteboardOutputDict = PasteboardDictFromTransferable(mTransferable);
   if (!pasteboardOutputDict)
     return NS_ERROR_FAILURE;
 
-  // write everything out to the general pasteboard
   unsigned int outputCount = [pasteboardOutputDict count];
   NSArray* outputKeys = [pasteboardOutputDict allKeys];
-  NSPasteboard* generalPBoard = [NSPasteboard generalPasteboard];
-  [generalPBoard declareTypes:outputKeys owner:nil];
+  NSPasteboard* cocoaPasteboard;
+  if (aWhichClipboard == kFindClipboard) {
+    cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
+    [cocoaPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
+  } else {
+    // Write everything else out to the general pasteboard.
+    cocoaPasteboard = [NSPasteboard generalPasteboard];
+    [cocoaPasteboard declareTypes:outputKeys owner:nil];
+  }
+
   for (unsigned int i = 0; i < outputCount; i++) {
     NSString* currentKey = [outputKeys objectAtIndex:i];
     id currentValue = [pasteboardOutputDict valueForKey:currentKey];
-    if (currentKey == NSStringPboardType ||
-        currentKey == kCorePboardType_url ||
-        currentKey == kCorePboardType_urld ||
-        currentKey == kCorePboardType_urln) {
-      [generalPBoard setString:currentValue forType:currentKey];
-    } else if (currentKey == NSHTMLPboardType) {
-      [generalPBoard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
-                       forType:currentKey];
+    if (aWhichClipboard == kFindClipboard) {
+      if (currentKey == NSStringPboardType)
+        [cocoaPasteboard setString:currentValue forType:currentKey];
     } else {
-      [generalPBoard setData:currentValue forType:currentKey];
+      if (currentKey == NSStringPboardType ||
+          currentKey == kCorePboardType_url ||
+          currentKey == kCorePboardType_urld ||
+          currentKey == kCorePboardType_urln) {
+        [cocoaPasteboard setString:currentValue forType:currentKey];
+      } else if (currentKey == NSHTMLPboardType) {
+        [cocoaPasteboard setString:(nsClipboard::WrapHtmlForSystemPasteboard(currentValue))
+                         forType:currentKey];
+      } else {
+        [cocoaPasteboard setData:currentValue forType:currentKey];
+      }
     }
   }
 
-  mChangeCount = [generalPBoard changeCount];
+  if (aWhichClipboard == kFindClipboard) {
+    mChangeCountFind = [cocoaPasteboard changeCount];
+  } else {
+    mChangeCountGeneral = [cocoaPasteboard changeCount];
+  }
 
   mIgnoreEmptyNotification = false;
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
@@ -233,35 +250,41 @@ nsClipboard::TransferableFromPasteboard(
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsClipboard::GetNativeClipboardData(nsITransferable* aTransferable, int32_t aWhichClipboard)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  if ((aWhichClipboard != kGlobalClipboard) || !aTransferable)
+  if ((aWhichClipboard != kGlobalClipboard && aWhichClipboard != kFindClipboard) || !aTransferable)
     return NS_ERROR_FAILURE;
 
-  NSPasteboard* cocoaPasteboard = [NSPasteboard generalPasteboard];
+  NSPasteboard* cocoaPasteboard;
+  if (aWhichClipboard == kFindClipboard) {
+    cocoaPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
+  } else {
+    cocoaPasteboard = [NSPasteboard generalPasteboard];
+  }
   if (!cocoaPasteboard)
     return NS_ERROR_FAILURE;
 
   // get flavor list that includes all acceptable flavors (including ones obtained through conversion)
   nsCOMPtr<nsISupportsArray> flavorList;
   nsresult rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList));
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
   uint32_t flavorCount;
   flavorList->Count(&flavorCount);
 
+  int changeCount = (aWhichClipboard == kFindClipboard) ? mChangeCountFind : mChangeCountGeneral;
   // If we were the last ones to put something on the pasteboard, then just use the cached
   // transferable. Otherwise clear it because it isn't relevant any more.
-  if (mChangeCount == [cocoaPasteboard changeCount]) {
+  if (changeCount == [cocoaPasteboard changeCount]) {
     if (mTransferable) {
       for (uint32_t i = 0; i < flavorCount; i++) {
         nsCOMPtr<nsISupports> genericFlavor;
         flavorList->GetElementAt(i, getter_AddRefs(genericFlavor));
         nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor));
         if (!currentFlavor)
           continue;
 
@@ -272,19 +295,18 @@ nsClipboard::GetNativeClipboardData(nsIT
         uint32_t dataSize = 0;
         rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(dataSupports), &dataSize);
         if (NS_SUCCEEDED(rv)) {
           aTransferable->SetTransferData(flavorStr, dataSupports, dataSize);
           return NS_OK; // maybe try to fill in more types? Is there a point?
         }
       }
     }
-  }
-  else {
-    nsBaseClipboard::EmptyClipboard(kGlobalClipboard);
+  } else {
+    nsBaseClipboard::EmptyClipboard(aWhichClipboard);
   }
 
   // at this point we can't satisfy the request from cache data so let's look
   // for things other people put on the system clipboard
 
   return nsClipboard::TransferableFromPasteboard(aTransferable, cocoaPasteboard);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@@ -353,16 +375,24 @@ nsClipboard::HasDataMatchingFlavors(cons
     }
   }
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
+NS_IMETHODIMP
+nsClipboard::SupportsFindClipboard(bool *_retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+  *_retval = true;
+  return NS_OK;
+}
+
 // This function converts anything that other applications might understand into the system format
 // and puts it into a dictionary which it returns.
 // static
 NSDictionary* 
 nsClipboard::PasteboardDictFromTransferable(nsITransferable* aTransferable)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
 
--- a/widget/gtk/nsClipboard.cpp
+++ b/widget/gtk/nsClipboard.cpp
@@ -443,16 +443,23 @@ nsClipboard::HasDataMatchingFlavors(cons
 
 NS_IMETHODIMP
 nsClipboard::SupportsSelectionClipboard(bool *_retval)
 {
     *_retval = true; // yeah, unix supports the selection clipboard
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsClipboard::SupportsFindClipboard(bool* _retval)
+{
+  *_retval = false;
+  return NS_OK;
+}
+
 /* static */
 GdkAtom
 nsClipboard::GetSelectionAtom(int32_t aWhichClipboard)
 {
     if (aWhichClipboard == kGlobalClipboard)
         return GDK_SELECTION_CLIPBOARD;
 
     return GDK_SELECTION_PRIMARY;
--- a/widget/nsIClipboard.idl
+++ b/widget/nsIClipboard.idl
@@ -6,21 +6,22 @@
 
 
 #include "nsISupports.idl"
 #include "nsITransferable.idl"
 #include "nsIClipboardOwner.idl"
 
 interface nsIArray;
 
-[scriptable, uuid(38984945-8674-4d04-b786-5c0ca9434457)]
+[scriptable, uuid(ceaa0047-647f-4b8e-ad1c-aff9fa62aa51)]
 interface nsIClipboard : nsISupports
 {
     const long kSelectionClipboard = 0;
     const long kGlobalClipboard = 1;
+    const long kFindClipboard = 2;
     
    /**
     * Given a transferable, set the data on the native clipboard
     *
     * @param  aTransferable The transferable
     * @param  anOwner The owner of the transferable
     * @param  aWhichClipboard Specifies the clipboard to which this operation applies.
     * @result NS_Ok if no errors
@@ -68,14 +69,22 @@ interface nsIClipboard : nsISupports
    /**
     * Allows clients to determine if the implementation supports the concept of a 
     * separate clipboard for selection.
     * 
     * @outResult - true if 
     * @result NS_OK if successful.
     */
     boolean supportsSelectionClipboard ( ) ;
+
+    /**
+    * Allows clients to determine if the implementation supports the concept of a
+    * separate clipboard for find search strings.
+    *
+    * @result NS_OK if successful.
+    */
+    boolean supportsFindClipboard ( ) ;
 };
 
 
 %{ C++
 
 %}
--- a/widget/qt/nsClipboard.cpp
+++ b/widget/qt/nsClipboard.cpp
@@ -551,8 +551,17 @@ nsClipboard::SupportsSelectionClipboard(
     }
     else
     {
         *_retval = false;
     }
 
     return NS_OK;
 }
+
+NS_IMETHODIMP
+nsClipboard::SupportsFindClipboard(bool* _retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+
+  *_retval = false;
+  return NS_OK;
+}
--- a/widget/xpwidgets/nsBaseClipboard.cpp
+++ b/widget/xpwidgets/nsBaseClipboard.cpp
@@ -17,16 +17,17 @@ nsBaseClipboard::nsBaseClipboard()
   mIgnoreEmptyNotification = false;
   mEmptyingForSetData      = false;
 }
 
 nsBaseClipboard::~nsBaseClipboard()
 {
   EmptyClipboard(kSelectionClipboard);
   EmptyClipboard(kGlobalClipboard);
+  EmptyClipboard(kFindClipboard);
 }
 
 NS_IMPL_ISUPPORTS1(nsBaseClipboard, nsIClipboard)
 
 /**
   * Sets the transferable object
   *
   */
@@ -34,17 +35,19 @@ NS_IMETHODIMP nsBaseClipboard::SetData(n
                                         int32_t aWhichClipboard)
 {
   NS_ASSERTION ( aTransferable, "clipboard given a null transferable" );
 
   if (aTransferable == mTransferable && anOwner == mClipboardOwner)
     return NS_OK;
   bool selectClipPresent;
   SupportsSelectionClipboard(&selectClipPresent);
-  if ( !selectClipPresent && aWhichClipboard != kGlobalClipboard )
+  bool findClipPresent;
+  SupportsFindClipboard(&findClipPresent);
+  if ( !selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard )
     return NS_ERROR_FAILURE;
 
   mEmptyingForSetData = true;
   EmptyClipboard(aWhichClipboard);
   mEmptyingForSetData = false;
 
   mClipboardOwner = anOwner;
   if ( anOwner )
@@ -70,33 +73,37 @@ NS_IMETHODIMP nsBaseClipboard::SetData(n
 
 /**
   * Gets the transferable object
   *
   */
 NS_IMETHODIMP nsBaseClipboard::GetData(nsITransferable * aTransferable, int32_t aWhichClipboard)
 {
   NS_ASSERTION ( aTransferable, "clipboard given a null transferable" );
-  
+
   bool selectClipPresent;
   SupportsSelectionClipboard(&selectClipPresent);
-  if ( !selectClipPresent && aWhichClipboard != kGlobalClipboard )
+  bool findClipPresent;
+  SupportsFindClipboard(&findClipPresent);
+  if ( !selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard )
     return NS_ERROR_FAILURE;
 
   if ( aTransferable )
     return GetNativeClipboardData(aTransferable, aWhichClipboard);
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP nsBaseClipboard::EmptyClipboard(int32_t aWhichClipboard)
 {
   bool selectClipPresent;
   SupportsSelectionClipboard(&selectClipPresent);
-  if ( !selectClipPresent && aWhichClipboard != kGlobalClipboard )
+  bool findClipPresent;
+  SupportsFindClipboard(&findClipPresent);
+  if ( !selectClipPresent && !findClipPresent && aWhichClipboard != kGlobalClipboard )
     return NS_ERROR_FAILURE;
 
   if (mIgnoreEmptyNotification)
     return NS_OK;
 
   if ( mClipboardOwner ) {
     mClipboardOwner->LosingOwnership(mTransferable);
     NS_RELEASE(mClipboardOwner);
@@ -118,8 +125,15 @@ nsBaseClipboard::HasDataMatchingFlavors(
 }
 
 NS_IMETHODIMP
 nsBaseClipboard::SupportsSelectionClipboard(bool* _retval)
 {
   *_retval = false;   // we don't support the selection clipboard by default.
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsBaseClipboard::SupportsFindClipboard(bool* _retval)
+{
+  *_retval = false;   // we don't support the find clipboard by default.
+  return NS_OK;
+}
--- a/widget/xpwidgets/nsClipboardHelper.cpp
+++ b/widget/xpwidgets/nsClipboardHelper.cpp
@@ -46,26 +46,35 @@ nsClipboardHelper::CopyStringToClipboard
   nsresult rv;
 
   // get the clipboard
   nsCOMPtr<nsIClipboard>
     clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(clipboard, NS_ERROR_FAILURE);
 
+  bool clipboardSupported;
   // don't go any further if they're asking for the selection
   // clipboard on a platform which doesn't support it (i.e., unix)
   if (nsIClipboard::kSelectionClipboard == aClipboardID) {
-    bool clipboardSupported;
     rv = clipboard->SupportsSelectionClipboard(&clipboardSupported);
     NS_ENSURE_SUCCESS(rv, rv);
     if (!clipboardSupported)
       return NS_ERROR_FAILURE;
   }
 
+  // don't go any further if they're asking for the find clipboard on a platform
+  // which doesn't support it (i.e., non-osx)
+  if (nsIClipboard::kFindClipboard == aClipboardID) {
+    rv = clipboard->SupportsFindClipboard(&clipboardSupported);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (!clipboardSupported)
+      return NS_ERROR_FAILURE;
+  }
+
   // create a transferable for putting data on the clipboard
   nsCOMPtr<nsITransferable>
     trans(do_CreateInstance("@mozilla.org/widget/transferable;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(trans, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
   nsILoadContext* loadContext = doc ? doc->GetLoadContext() : nullptr;
--- a/widget/xpwidgets/nsClipboardProxy.cpp
+++ b/widget/xpwidgets/nsClipboardProxy.cpp
@@ -86,8 +86,15 @@ nsClipboardProxy::HasDataMatchingFlavors
 
 NS_IMETHODIMP
 nsClipboardProxy::SupportsSelectionClipboard(bool *aIsSupported)
 {
   *aIsSupported = false;
   return NS_OK;
 }
 
+
+NS_IMETHODIMP
+nsClipboardProxy::SupportsFindClipboard(bool *aIsSupported)
+{
+  *aIsSupported = false;
+  return NS_OK;
+}