Permalink
Browse files

Merge pull request #297 from ermshiperete/4959

Xamarin-4959: Fix copy of clipboard data after app exits
  • Loading branch information...
2 parents fe3efe8 + 444495f commit 68069f056621ebdafa21ae4e75e75f6e83b7202a @migueldeicaza migueldeicaza committed May 24, 2012
@@ -66,7 +66,7 @@ public static void Clear ()
IntPtr clipboard_handle;
clipboard_handle = XplatUI.ClipboardOpen (false);
- XplatUI.ClipboardStore (clipboard_handle, null, 0, null);
+ XplatUI.ClipboardStore (clipboard_handle, null, 0, null, false);
}
public static bool ContainsAudio ()
@@ -240,7 +240,7 @@ public static void SetData (string format, Object data)
converter = new XplatUI.ObjectToClipboard(ConvertToClipboardData);
clipboard_handle = XplatUI.ClipboardOpen(false);
- XplatUI.ClipboardStore(clipboard_handle, null, 0, null); // Empty clipboard
+ XplatUI.ClipboardStore(clipboard_handle, null, 0, null, copy); // Empty clipboard
native_format = -1;
@@ -261,15 +261,15 @@ public static void SetData (string format, Object data)
if (IsDataSerializable (obj))
item_format.is_serializable = true;
- XplatUI.ClipboardStore(clipboard_handle, obj, native_format, converter);
+ XplatUI.ClipboardStore(clipboard_handle, obj, native_format, converter, copy);
}
} else {
item_format = DataFormats.Format.Find(data.GetType().FullName);
if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
native_format = item_format.Id;
}
- XplatUI.ClipboardStore(clipboard_handle, data, native_format, converter);
+ XplatUI.ClipboardStore(clipboard_handle, data, native_format, converter, copy);
}
XplatUI.ClipboardClose(clipboard_handle);
}
@@ -549,10 +549,10 @@ internal static IntPtr ClipboardOpen (bool primary_selection)
return driver.ClipboardOpen (primary_selection);
}
- internal static void ClipboardStore (IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter)
+ internal static void ClipboardStore (IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy)
{
- DriverDebug ("ClipboardStore ({0:X}, {1}, {2}): Called", handle.ToInt32 (), obj, type, converter);
- driver.ClipboardStore (handle, obj, type, converter);
+ DriverDebug ("ClipboardStore ({0:X}, {1}, {2}, {3}, {4}): Called", handle.ToInt32 (), obj, type, converter, copy);
+ driver.ClipboardStore (handle, obj, type, converter, copy);
}
internal static object ClipboardRetrieve (IntPtr handle, int type, XplatUI.ClipboardToObject converter)
@@ -874,7 +874,7 @@ internal override void RaiseIdle (EventArgs e)
return Carbon.Pasteboard.Retrieve (handle, type);
}
- internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
+ internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy) {
Carbon.Pasteboard.Store (handle, obj, type);
}
@@ -399,7 +399,7 @@ internal virtual void SetAllowDrop (IntPtr handle, bool value)
internal abstract void ClipboardClose(IntPtr handle);
internal abstract IntPtr ClipboardOpen (bool primary_selection);
internal abstract int ClipboardGetID(IntPtr handle, string format);
- internal abstract void ClipboardStore(IntPtr handle, object obj, int id, XplatUI.ObjectToClipboard converter);
+ internal abstract void ClipboardStore(IntPtr handle, object obj, int id, XplatUI.ObjectToClipboard converter, bool copy);
internal abstract int[] ClipboardAvailableFormats(IntPtr handle);
internal abstract object ClipboardRetrieve(IntPtr handle, int id, XplatUI.ClipboardToObject converter);
@@ -2908,7 +2908,8 @@ internal override void SystrayBalloon(IntPtr hwnd, int timeout, string title, st
}
- internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
+ internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy)
+ {
byte[] data = null;
if (handle != clip_magic) {
@@ -2788,17 +2788,36 @@ internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.Clip
return Clipboard.Item;
}
- internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter)
+ internal override void ClipboardStore (IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy)
{
Clipboard.Converter = converter;
if (obj != null) {
Clipboard.AddSource (type, obj);
- XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
+ XSetSelectionOwner (DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
+
+ if (copy) {
+ try {
+ var clipboardAtom = gdk_atom_intern ("CLIPBOARD", true);
+ var clipboard = gtk_clipboard_get (clipboardAtom);
+ if (clipboard != null) {
+ // for now we only store text
+ var text = Clipboard.GetRtfText ();
+ if (string.IsNullOrEmpty (text))
+ text = Clipboard.GetPlainText ();
+ if (!string.IsNullOrEmpty (text)) {
+ gtk_clipboard_set_text (clipboard, text, text.Length);
+ gtk_clipboard_store (clipboard);
+ }
+ }
+ } catch {
+ // ignore any errors - most likely because gtk isn't installed?
+ }
+ }
} else {
// Clearing the selection
Clipboard.ClearSources ();
- XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
+ XSetSelectionOwner (DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
}
}
@@ -7550,6 +7569,20 @@ internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y
[DllImport ("libX11", EntryPoint="XGetInputFocus")]
internal extern static void XGetInputFocus (IntPtr display, out IntPtr focus, out IntPtr revert_to);
#endregion
+#region Gtk/Gdk imports
+ [DllImport("libgdk-x11-2.0")]
+ internal extern static IntPtr gdk_atom_intern (string atomName, bool onlyIfExists);
+
+ [DllImport("libgtk-x11-2.0")]
+ internal extern static IntPtr gtk_clipboard_get (IntPtr atom);
+
+ [DllImport("libgtk-x11-2.0")]
+ internal extern static void gtk_clipboard_store (IntPtr clipboard);
+
+ [DllImport("libgtk-x11-2.0")]
+ internal extern static void gtk_clipboard_set_text (IntPtr clipboard, string text, int len);
+#endregion
+
#endif
}
}
@@ -24,6 +24,9 @@
//
using System;
+using System.CodeDom.Compiler;
+using System.Diagnostics;
+using System.IO;
using System.Text;
using System.Windows.Forms;
using NUnit.Framework;
@@ -99,6 +102,82 @@ private class CustomSerializableClass
public string Name;
public int Id;
}
+
+ [Test]
+ public void DataRemainsOnClipboard_Xamarin4959 ()
+ {
+ // Compile an app that puts something on the clipboard
+ var source = @"
+using System;
+using System.Windows.Forms;
+public static class MainClass
+{
+ public static void Main ()
+ {
+ Clipboard.SetDataObject (""testing bug 4959"", true, 10, 100);
+ }
+}
+";
+ var exeName = Path.GetTempFileName ();
+ try {
+ var parameters = new CompilerParameters ();
+ parameters.GenerateExecutable = true;
+ parameters.ReferencedAssemblies.Add ("System.Windows.Forms.dll");
+ parameters.OutputAssembly = exeName;
+ var compiler = CodeDomProvider.CreateProvider ("CSharp");
+ var compilerResults = compiler.CompileAssemblyFromSource (parameters, source);
+ Assert.AreEqual (0, compilerResults.Errors.Count);
+
+ // Execute the app
+ using (var app = Process.Start (exeName)) {
+ app.WaitForExit ();
+ }
+
+ // Text should still be on the clipboard
+ Assert.AreEqual ("testing bug 4959", Clipboard.GetText ());
+ } finally {
+ File.Delete (exeName);
+ }
+ }
+
+ [Test]
+ public void DataGetsCleared_Xamarin4959 ()
+ {
+ // This is the reverse of the previous test
+
+ // Compile an app that puts something on the clipboard
+ var source = @"
+using System;
+using System.Windows.Forms;
+public static class MainClass
+{
+ public static void Main ()
+ {
+ Clipboard.SetDataObject (""testing bug 4959"", false, 10, 100);
+ }
+}
+";
+ var exeName = Path.GetTempFileName ();
+ try {
+ var parameters = new CompilerParameters ();
+ parameters.GenerateExecutable = true;
+ parameters.ReferencedAssemblies.Add ("System.Windows.Forms.dll");
+ parameters.OutputAssembly = exeName;
+ var compiler = CodeDomProvider.CreateProvider ("CSharp");
+ var compilerResults = compiler.CompileAssemblyFromSource (parameters, source);
+ Assert.AreEqual (0, compilerResults.Errors.Count);
+
+ // Execute the app
+ using (var app = Process.Start (exeName)) {
+ app.WaitForExit ();
+ }
+
+ // Text should no longer be on the clipboard
+ Assert.IsTrue (string.IsNullOrEmpty (Clipboard.GetText ()));
+ } finally {
+ File.Delete (exeName);
+ }
+ }
#endif
}
}

0 comments on commit 68069f0

Please sign in to comment.