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 id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoshmoz
bugs326743
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;
+}