diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs index 3a7b37bb9a..0b1f479cc6 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs @@ -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() diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ClipboardHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ClipboardHelper.cs index 7f4adb7239..627bd382c2 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/ClipboardHelper.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ClipboardHelper.cs @@ -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); diff --git a/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs b/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs index 40b3ea51a5..8c30f9fa5b 100644 --- a/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs +++ b/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs @@ -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 _previouslyPressedKeys; private List _activationKeys = new List(); 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(); + } } } } diff --git a/src/modules/colorPicker/ColorPickerUI/NativeMethods.cs b/src/modules/colorPicker/ColorPickerUI/NativeMethods.cs index f1faefb6f1..80284a5626 100644 --- a/src/modules/colorPicker/ColorPickerUI/NativeMethods.cs +++ b/src/modules/colorPicker/ColorPickerUI/NativeMethods.cs @@ -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 /// 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); } }