Fixing issues when color picker freezes (#8376)

* Fixing issue when color picker was frozen because other application was locking clipboard

* Fixed another issue where holding activation keys constantly would trigger show color picker numberous times and it would cause some events to be attached multiple times
This commit is contained in:
martinchrzan 2020-12-05 14:25:55 +01:00 committed by GitHub
parent aa3dd133c7
commit 375953641b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 17 deletions

View file

@ -14,6 +14,8 @@ namespace ColorPicker.Helpers
{
private readonly IColorEditorViewModel _colorEditorViewModel;
private ColorEditorWindow _colorEditorWindow;
private bool _colorPickerShown;
private object _colorPickerVisibilityLock = new object();
[ImportingConstructor]
public AppStateHandler(IColorEditorViewModel colorEditorViewModel)
@ -30,16 +32,30 @@ namespace ColorPicker.Helpers
public void ShowColorPicker()
{
AppShown?.Invoke(this, EventArgs.Empty);
Application.Current.MainWindow.Opacity = 0;
Application.Current.MainWindow.Visibility = Visibility.Visible;
lock (_colorPickerVisibilityLock)
{
if (!_colorPickerShown)
{
AppShown?.Invoke(this, EventArgs.Empty);
Application.Current.MainWindow.Opacity = 0;
Application.Current.MainWindow.Visibility = Visibility.Visible;
_colorPickerShown = true;
}
}
}
public void HideColorPicker()
{
Application.Current.MainWindow.Opacity = 0;
Application.Current.MainWindow.Visibility = Visibility.Collapsed;
AppHidden?.Invoke(this, EventArgs.Empty);
lock (_colorPickerVisibilityLock)
{
if (_colorPickerShown)
{
Application.Current.MainWindow.Opacity = 0;
Application.Current.MainWindow.Visibility = Visibility.Collapsed;
AppHidden?.Invoke(this, EventArgs.Empty);
_colorPickerShown = false;
}
}
}
public void ShowColorPickerEditor()

View file

@ -3,7 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using static ColorPicker.NativeMethods;
namespace ColorPicker.Helpers
{
@ -23,15 +25,24 @@ namespace ColorPicker.Helpers
{
try
{
Clipboard.SetText(colorRepresentationToCopy);
Clipboard.SetDataObject(colorRepresentationToCopy);
break;
}
catch (COMException ex)
{
var hwnd = GetOpenClipboardWindow();
var sb = new StringBuilder(501);
_ = GetWindowText(hwnd.ToInt32(), sb, 500);
var applicationUsingClipboard = sb.ToString();
if ((uint)ex.ErrorCode != ErrorCodeClipboardCantOpen)
{
Logger.LogError("Failed to set text into clipboard", ex);
}
else
{
Logger.LogError("Failed to set text into clipboard, application that is locking clipboard - " + applicationUsingClipboard, ex);
}
}
System.Threading.Thread.Sleep(10);

View file

@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Windows.Input;
using ColorPicker.Helpers;
using ColorPicker.Settings;
@ -21,10 +22,12 @@ namespace ColorPicker.Keyboard
{
private readonly AppStateHandler _appStateHandler;
private readonly IUserSettings _userSettings;
private List<string> _previouslyPressedKeys;
private List<string> _activationKeys = new List<string>();
private GlobalKeyboardHook _keyboardHook;
private bool disposedValue;
private bool _activationShortcutPressed;
[ImportingConstructor]
public KeyboardMonitor(AppStateHandler appStateHandler, IUserSettings userSettings)
@ -80,26 +83,38 @@ namespace ColorPicker.Keyboard
// If the last key pressed is a modifier key, then currentlyPressedKeys cannot possibly match with _activationKeys
// because _activationKeys contains exactly 1 non-modifier key. Hence, there's no need to check if `name` is a
// modifier key or to do any additional processing on it.
// Check pressed modifier keys.
AddModifierKeys(currentlyPressedKeys);
if (e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown || e.KeyboardState == GlobalKeyboardHook.KeyboardState.SysKeyDown)
{
// Check pressed modifier keys.
AddModifierKeys(currentlyPressedKeys);
currentlyPressedKeys.Add(name);
}
currentlyPressedKeys.Sort();
if (currentlyPressedKeys.Count == 0 && _previouslyPressedKeys.Count != 0)
{
// no keys pressed, we can enable activation shortcut again
_activationShortcutPressed = false;
}
_previouslyPressedKeys = currentlyPressedKeys;
if (ArraysAreSame(currentlyPressedKeys, _activationKeys))
{
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
// avoid triggering this action multiple times as this will be called nonstop while keys are pressed
if (!_activationShortcutPressed)
{
_appStateHandler.ShowColorPickerEditor();
}
else
{
_appStateHandler.ShowColorPicker();
_activationShortcutPressed = true;
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
{
_appStateHandler.ShowColorPickerEditor();
}
else
{
_appStateHandler.ShowColorPicker();
}
}
}
}

View file

@ -5,6 +5,7 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
namespace ColorPicker
{
@ -161,5 +162,11 @@ namespace ColorPicker
/// </summary>
public IntPtr AdditionalInformation;
}
[DllImport("user32.dll")]
internal static extern IntPtr GetOpenClipboardWindow();
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int GetWindowText(int hwnd, StringBuilder text, int count);
}
}