fdorg / flashdevelop

FlashDevelop is a free and open source code editor.
MIT License
825 stars 220 forks source link

ClipboardManager sometimes throws exception when copying #2597

Open gene-pavlovsky opened 5 years ago

gene-pavlovsky commented 5 years ago

Unfortunately I didn't find a reliable way to reproduce this so far, the following happens to me from time to time. I'm currently on the latest development branch, FD is running under VS debugger.

Sometimes when I use Ctrl-C in Google Chrome to copy something, FD throws this exception:

System.ArgumentException
  HResult=0x80070057
  Message=Specified IDataObject does not contain any text data.
  Source=FlashDevelop
  StackTrace:
   at FlashDevelop.Managers.ClipboardTextData.Initialize(IDataObject dataObject) in C:\project\flashdevelop\FlashDevelop\Managers\ClipboardManager.cs:line 251
   at FlashDevelop.Managers.ClipboardTextData..ctor(IDataObject dataObject) in C:\project\flashdevelop\FlashDevelop\Managers\ClipboardManager.cs:line 189
   at FlashDevelop.Managers.ClipboardManager.HandleWndProc(Message& m) in C:\project\flashdevelop\FlashDevelop\Managers\ClipboardManager.cs:line 114
   at FlashDevelop.MainForm.WndProc(Message& m) in C:\project\flashdevelop\FlashDevelop\MainForm.cs:line 1775
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
YellowAfterlife commented 3 years ago

I'm starting to think that there's some sort of race condition (or, perhaps, Chrome not committing all of the data formats at once) because showing data.GetFormats() with the exception does show Text and Rtf that were just detected as false, but changing code to

        void Initialize(IDataObject data)
        {
            var formats = data.GetFormats();
            var hasRtf = data.GetDataPresent(DataFormats.Rtf);
            if (!hasRtf && Array.IndexOf(formats, DataFormats.Rtf) >= 0) {
                hasRtf = true;
            }
            if (hasRtf)
            {
                Format = DataFormats.Rtf;
                Rtf = (string) data.GetData(DataFormats.Rtf);
                Text = (string) data.GetData(DataFormats.Text);
                return;
            }
            var hasText = data.GetDataPresent(DataFormats.Text);
            if (!hasText && Array.IndexOf(formats, DataFormats.Text) >= 0) {
                hasText = true;
            }
            if (hasText)
            {
                Format = DataFormats.Text;
                Rtf = null;
                Text = (string) data.GetData(DataFormats.Text);
                return;
            }
            throw new ArgumentException("Specified " + nameof(IDataObject) + " does not contain any text data (formats: " + formats + ").");
        }

stops this from happening (neither hasText or hasRtf conditional assignments execute). Could be best to retry or ignore the exception if the window is not foreground?