Skip to content

Commit

Permalink
fix(copy): crash on clipboard access from non-focused window
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzzzerd committed Jul 16, 2020
1 parent 517d5f8 commit 5a535f0
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 52 deletions.
9 changes: 4 additions & 5 deletions SharpFM.App/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<Grid DataContext="{Binding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="350" />
</Grid.ColumnDefinitions>

<controls:MasterDetailsView
Expand Down Expand Up @@ -101,7 +100,7 @@

</controls:MasterDetailsView>

<StackPanel Grid.Column="1" Width="350" Height="Auto" DataContext="{Binding}">
<!--<StackPanel Grid.Column="1" Width="350" Height="Auto" DataContext="{Binding}">
<ComboBox x:Name="LayoutPickerComboBox"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Layouts}"
Expand All @@ -116,10 +115,10 @@
</TextBlock>
<!--<monaco:CodeEditor x:Name="XamlCodeRendererCsharp"
--><!--<monaco:CodeEditor x:Name="XamlCodeRendererCsharp"
CodeLanguage="csharp"
Text="{ Binding SelectedClip.XmlData, Mode=OneWay}" />-->
</StackPanel>
Text="{ Binding SelectedClip.XmlData, Mode=OneWay}" />--><!--
</StackPanel>-->

</Grid>
</Page>
94 changes: 60 additions & 34 deletions SharpFM.App/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Windows.ApplicationModel.DataTransfer;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
Expand All @@ -32,10 +33,15 @@ public sealed partial class MainPage : Page

public string SelectedClipAsCsharp { get; set; }

CoreWindow window;

public MainPage()
{
InitializeComponent();

window = CoreWindow.GetForCurrentThread();
window.Activated += Window_Activated;

Keys = new ObservableCollection<FileMakerClip>();
Layouts = new ObservableCollection<FileMakerClip>();

Expand All @@ -51,57 +57,75 @@ public MainPage()
Clipboard.ContentChanged += Clipboard_ContentChanged;
}

private async void Clipboard_ContentChanged(object sender, object e)
private async Task ProcessClipboard()
{
var clip = Clipboard.GetContent();

var formats = clip.AvailableFormats.Where(f => f.StartsWith("Mac-", StringComparison.CurrentCultureIgnoreCase)).Distinct();
try
{
var clip = Clipboard.GetContent();

Debug.WriteLine($"Formats: {formats.Count()}");
var formats = clip.AvailableFormats.Where(f => f.StartsWith("Mac-", StringComparison.CurrentCultureIgnoreCase)).Distinct();

foreach (var format in formats)
{
object clipData = null;
Debug.WriteLine($"Formats: {formats.Count()}");

try
foreach (var format in formats)
{
if (format.Equals("bitmap", StringComparison.CurrentCultureIgnoreCase))
object clipData = null;

try
{
clipData = await clip.GetBitmapAsync();
if (format.Equals("bitmap", StringComparison.CurrentCultureIgnoreCase))
{
clipData = await clip.GetBitmapAsync();
}
clipData = await clip.GetDataAsync(format);
}
clipData = await clip.GetDataAsync(format);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Debug.WriteLine(ex.Message);
}
{
Debug.WriteLine(ex.Message);
}

if (!(clipData is IRandomAccessStream dataObj))
{
// this is some type of clipboard data this program can't handle
continue;
}
if (!(clipData is IRandomAccessStream dataObj))
{
// this is some type of clipboard data this program can't handle
continue;
}

var stream = dataObj.GetInputStreamAt(0);
IBuffer buff = new Windows.Storage.Streams.Buffer((uint)dataObj.Size);
await stream.ReadAsync(buff, (uint)dataObj.Size, InputStreamOptions.None);
var buffArray = buff.ToArray();
var stream = dataObj.GetInputStreamAt(0);
IBuffer buff = new Windows.Storage.Streams.Buffer((uint)dataObj.Size);
await stream.ReadAsync(buff, (uint)dataObj.Size, InputStreamOptions.None);
var buffArray = buff.ToArray();

var fmclip = new FileMakerClip("new-clip", format, buffArray);
var fmclip = new FileMakerClip("new-clip", format, buffArray);

// don't bother adding a duplicate. For some reason entries were getting entered twice per clip
// this is not the most efficient method to detect it, but it works well enough for now
if (Keys.Any(k => k.XmlData == fmclip.XmlData))
{
continue;
}
// don't bother adding a duplicate. For some reason entries were getting entered twice per clip
// this is not the most efficient method to detect it, but it works well enough for now
if (Keys.Any(k => k.XmlData == fmclip.XmlData))
{
continue;
}

Keys.Add(fmclip);
Keys.Add(fmclip);
}
}
catch (Exception ex)
{
var md = new MessageDialog(ex.Message + "\r\n" + ex.StackTrace);
await md.ShowAsync();
}
}

private async void Window_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
await ProcessClipboard();
}

private void Clipboard_ContentChanged(object sender, object e)
{
window.Activate();
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
var dp = new DataPackage();
Expand Down Expand Up @@ -146,6 +170,8 @@ private async void asModelAppBarButton_Click(object sender, RoutedEventArgs e)
if (pickerResult == ContentDialogResult.Primary)
{
// regenerate using the layout picker
SelectedLayout = picker.DialogResult;

var classString = data.CreateClass(SelectedLayout);
var dp = new DataPackage();
dp.SetText(classString);
Expand Down
4 changes: 2 additions & 2 deletions SharpFM.App/SharpFM.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<AssemblyName>SharpFM.App</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17134.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
Expand Down
68 changes: 57 additions & 11 deletions SharpFM.Core/FileMakerClipExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SharpFM.Core
{
Expand Down Expand Up @@ -42,26 +43,54 @@ public static string CreateClass(this FileMakerClip _clip, IEnumerable<string> f

// Add System using statement: (using System)
@namespace = @namespace.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")));
@namespace = @namespace.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Runtime.Serialization")));

var dataContractAttribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName("DataContract"));

// Create a class: (class [_clip.Name])
var classDeclaration = SyntaxFactory.ClassDeclaration(_clip.Name);

// Add the public modifier: (public class [_clip.Name])
classDeclaration = classDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
classDeclaration = classDeclaration.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(dataContractAttribute)));

// add each field from the underling _clip as a public property with the data member attribute
List<PropertyDeclarationSyntax> fieldsToBeAddedAsProperties = new List<PropertyDeclarationSyntax>(_clip.Fields.Count());
List <PropertyDeclarationSyntax> fieldsToBeAddedAsProperties = new List<PropertyDeclarationSyntax>(_clip.Fields.Count());
// include the field projection
foreach (var field in _clip.Fields.Where(fmF => fieldProjectionList.Contains(fmF.Name)))
{
// filemaker to C# data type mapping
var propertyTypeCSharp = field.DataType
.Replace("Text", "string")
.Replace("Number", "int")
.Replace("Binary", "byte[]")
.Replace("Date", "DateTime")
.Replace("Time", "TimeStamp")
.Replace("TimeStamp", "DateTime");
var propertyTypeCSharp = string.Empty;

switch (field.DataType)
{
case "Text":
propertyTypeCSharp = "string";
break;
case "Number":
propertyTypeCSharp = "int";
break;
case "Binary":
propertyTypeCSharp = "byte[]";
break;
case "Date":
propertyTypeCSharp = "DateTime";
break;
case "Time":
propertyTypeCSharp = "TimeSpan";
break;
case "TimeStamp":
propertyTypeCSharp = "DateTime";
break;
default:
propertyTypeCSharp = "string";
break;
}

if(field.NotEmpty == false && propertyTypeCSharp != "string")
{
propertyTypeCSharp += "?";
}

var propertyTypeSyntax = SyntaxFactory.ParseTypeName(propertyTypeCSharp);

Expand All @@ -72,8 +101,9 @@ public static string CreateClass(this FileMakerClip _clip, IEnumerable<string> f
.AddAccessorListAccessors(
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)))
.NormalizeWhitespace()
.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(dataMemberAttribute)));
.NormalizeWhitespace(indentation: "", eol: " ")
.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(dataMemberAttribute)))
.NormalizeWhitespace();

fieldsToBeAddedAsProperties.Add(propertyDeclaration);
}
Expand All @@ -85,10 +115,26 @@ public static string CreateClass(this FileMakerClip _clip, IEnumerable<string> f
@namespace = @namespace.AddMembers(classDeclaration);

// Normalize and get code as string.
var code = @namespace.NormalizeWhitespace().ToFullString();
var code = @namespace.NormalizeWhitespace().ToFullString().FormatAutoPropertiesOnOneLine();

// Output new code to the console.
return code;
}


/// <summary>
/// https://stackoverflow.com/a/52339795/86860
/// </summary>
private static readonly Regex AutoPropRegex = new Regex(@"\s*\{\s*get;\s*set;\s*}\s");

/// <summary>
/// https://stackoverflow.com/a/52339795/86860
/// </summary>
/// <param name="str">Code string to format.</param>
/// <returns>The code string with auto properties formatted to a single line</returns>
private static string FormatAutoPropertiesOnOneLine(this string str)
{
return AutoPropRegex.Replace(str, " { get; set; }");
}
}
}

0 comments on commit 5a535f0

Please sign in to comment.