From 7273e1218a70265ca06408ee420b8b0f57906c13 Mon Sep 17 00:00:00 2001 From: Boris Makogonyuk Date: Thu, 8 Oct 2015 00:17:37 +0200 Subject: [PATCH 1/3] Wox now has an option to ignore hotkeys when the focused window is topmost. This will ignore not only the main Wox hotkey but also plugin hotkeys. ~ WindowIntelopHelper edited ~ User settings entry added ~ Checkbox added to General tab (as well as its events) ~ Language entries added for en/ru --- Wox.Core/UserSettings/UserSettingStorage.cs | 3 +++ Wox/Helper/WindowIntelopHelper.cs | 16 +++++++++++++++- Wox/Languages/en.xaml | 1 + Wox/Languages/ru.xaml | 1 + Wox/Languages/zh-cn.xaml | 1 + Wox/Languages/zh-tw.xaml | 1 + Wox/MainWindow.xaml.cs | 16 ++++++++++++++++ Wox/SettingWindow.xaml | 3 +++ Wox/SettingWindow.xaml.cs | 16 +++++++++++++++- 9 files changed, 56 insertions(+), 2 deletions(-) diff --git a/Wox.Core/UserSettings/UserSettingStorage.cs b/Wox.Core/UserSettings/UserSettingStorage.cs index c01538e623..75f00ce48a 100644 --- a/Wox.Core/UserSettings/UserSettingStorage.cs +++ b/Wox.Core/UserSettings/UserSettingStorage.cs @@ -86,6 +86,9 @@ namespace Wox.Core.UserSettings [JsonProperty] public bool RememberLastLaunchLocation { get; set; } + [JsonProperty] + public bool IgnoreHotkeysOnTopMostFocus { get; set; } + [JsonProperty] public string ProxyServer { get; set; } diff --git a/Wox/Helper/WindowIntelopHelper.cs b/Wox/Helper/WindowIntelopHelper.cs index 2e5179b7b4..caf7c2a89c 100644 --- a/Wox/Helper/WindowIntelopHelper.cs +++ b/Wox/Helper/WindowIntelopHelper.cs @@ -10,14 +10,28 @@ namespace Wox.Helper public class WindowIntelopHelper { private const int GWL_STYLE = -16; //WPF's Message code for Title Bar's Style + private const int GWL_EXSTYLE = -20; //Gets the exstyle of the window + private const int WS_EX_TOPMOST = 0x00000008; //Topmost flag private const int WS_SYSMENU = 0x80000; //WPF's Message code for System Menu - + [DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + /// + ///Checks if the foreground window is TopMost (even Wox) + /// + /// + public static bool IsForegroundWindowTopMost() + { + return (GetWindowLong(GetForegroundWindow(), GWL_EXSTYLE) & WS_EX_TOPMOST) == WS_EX_TOPMOST; + } + /// /// disable windows toolbar's control box /// this will also disable system menu with Alt+Space hotkey diff --git a/Wox/Languages/en.xaml b/Wox/Languages/en.xaml index 3d0946aa3b..5871b9fae2 100644 --- a/Wox/Languages/en.xaml +++ b/Wox/Languages/en.xaml @@ -23,6 +23,7 @@ Remember last launch location Language Maximum show results + Ignore hotkeys if foreground window is TopMost Plugin diff --git a/Wox/Languages/ru.xaml b/Wox/Languages/ru.xaml index efb3d9521a..ebf3f14886 100644 --- a/Wox/Languages/ru.xaml +++ b/Wox/Languages/ru.xaml @@ -23,6 +23,7 @@ Запомнить последнее место запуска Язык Максимальное количество результатов + Игнорировать горячие клавиши, если окно в фокусе самое верхнее Плагины diff --git a/Wox/Languages/zh-cn.xaml b/Wox/Languages/zh-cn.xaml index e2ab87c4b2..7768be27ee 100644 --- a/Wox/Languages/zh-cn.xaml +++ b/Wox/Languages/zh-cn.xaml @@ -23,6 +23,7 @@ 记住上次启动位置 语言 最大结果显示个数 + Ignore hotkeys if foreground window is TopMost 插件 diff --git a/Wox/Languages/zh-tw.xaml b/Wox/Languages/zh-tw.xaml index c0fd4a63b5..ae59971755 100644 --- a/Wox/Languages/zh-tw.xaml +++ b/Wox/Languages/zh-tw.xaml @@ -23,6 +23,7 @@ 记住上次启动位置 語言 最大結果顯示個數 + Ignore hotkeys if foreground window is TopMost 插件 diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 35e7df4965..01d9f94f79 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -356,6 +356,20 @@ namespace Wox } } + /// + /// Checks if Wox should ignore any hotkeys + /// + /// + private bool ShouldIgnoreHotkeys() + { + + if (!IsVisible + && UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus + && WindowIntelopHelper.IsForegroundWindowTopMost()) + return true; + return false; + } + private void SetCustomPluginHotkey() { if (UserSettingStorage.Instance.CustomPluginHotkeys == null) return; @@ -364,6 +378,7 @@ namespace Wox CustomPluginHotkey hotkey1 = hotkey; SetHotkey(hotkey.Hotkey, delegate { + if (ShouldIgnoreHotkeys()) return; ShowApp(); ChangeQuery(hotkey1.ActionKeyword, true); }); @@ -372,6 +387,7 @@ namespace Wox private void OnHotkey(object sender, HotkeyEventArgs e) { + if (ShouldIgnoreHotkeys()) return; ToggleWox(); e.Handled = true; } diff --git a/Wox/SettingWindow.xaml b/Wox/SettingWindow.xaml index ac40627a54..bc504df44c 100644 --- a/Wox/SettingWindow.xaml +++ b/Wox/SettingWindow.xaml @@ -35,6 +35,9 @@ + + + diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs index 7ede741c6a..36021206de 100644 --- a/Wox/SettingWindow.xaml.cs +++ b/Wox/SettingWindow.xaml.cs @@ -49,7 +49,6 @@ namespace Wox private void Setting_Loaded(object sender, RoutedEventArgs ev) { #region General - cbHideWhenDeactive.Checked += (o, e) => { UserSettingStorage.Instance.HideWhenDeactive = true; @@ -86,6 +85,20 @@ namespace Wox UserSettingStorage.Instance.Save(); }; + cbIgnoreHotkeysIfWindowIsTopmost.Checked += (o, e) => + { + UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus = true; + UserSettingStorage.Instance.Save(); + }; + + + cbIgnoreHotkeysIfWindowIsTopmost.Unchecked += (o, e) => + { + UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus = false; + UserSettingStorage.Instance.Save(); + }; + + cbStartWithWindows.IsChecked = CheckApplicationIsStartupWithWindow(); comboMaxResultsToShow.SelectionChanged += (o, e) => { @@ -97,6 +110,7 @@ namespace Wox cbHideWhenDeactive.IsChecked = UserSettingStorage.Instance.HideWhenDeactive; cbDontPromptUpdateMsg.IsChecked = UserSettingStorage.Instance.DontPromptUpdateMsg; cbRememberLastLocation.IsChecked = UserSettingStorage.Instance.RememberLastLaunchLocation; + cbIgnoreHotkeysIfWindowIsTopmost.IsChecked = UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus; LoadLanguages(); comboMaxResultsToShow.ItemsSource = Enumerable.Range(2, 16); From 3fbebfc283bfe48ef56b2e03fe2b9b0057a8f5a1 Mon Sep 17 00:00:00 2001 From: Boris Makogonyuk Date: Thu, 8 Oct 2015 00:52:52 +0200 Subject: [PATCH 2/3] ~Changed how the fullscreen detection work. Checking by Topmost was a stupid idea. It will now check for the window to fill the whole screen area. --- Wox/Helper/WindowIntelopHelper.cs | 77 +++++++++++++++++++++++++------ Wox/MainWindow.xaml.cs | 10 ++-- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/Wox/Helper/WindowIntelopHelper.cs b/Wox/Helper/WindowIntelopHelper.cs index caf7c2a89c..feccd8f6a4 100644 --- a/Wox/Helper/WindowIntelopHelper.cs +++ b/Wox/Helper/WindowIntelopHelper.cs @@ -1,19 +1,36 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Drawing; using System.Runtime.InteropServices; using System.Windows; +using System.Windows.Forms; +using System.Windows.Interop; namespace Wox.Helper { public class WindowIntelopHelper { private const int GWL_STYLE = -16; //WPF's Message code for Title Bar's Style - private const int GWL_EXSTYLE = -20; //Gets the exstyle of the window - private const int WS_EX_TOPMOST = 0x00000008; //Topmost flag private const int WS_SYSMENU = 0x80000; //WPF's Message code for System Menu + private static IntPtr _hwnd_shell; + private static IntPtr _hwnd_desktop; + //Accessors for shell and desktop handlers + //Will set the variables once and then will return them + private static IntPtr HWND_SHELL + { + get + { + return _hwnd_shell != null ? _hwnd_shell : _hwnd_shell = GetShellWindow(); + } + } + private static IntPtr HWND_DESKTOP + { + get + { + return _hwnd_desktop != null ? _hwnd_desktop : _hwnd_desktop = GetDesktopWindow(); + } + } + [DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowLong(IntPtr hWnd, int nIndex); @@ -23,23 +40,53 @@ namespace Wox.Helper [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); - /// - ///Checks if the foreground window is TopMost (even Wox) - /// - /// - public static bool IsForegroundWindowTopMost() + [DllImport("user32.dll")] + private static extern IntPtr GetDesktopWindow(); + + [DllImport("user32.dll")] + private static extern IntPtr GetShellWindow(); + + [DllImport("user32.dll", SetLastError = true)] + private static extern int GetWindowRect(IntPtr hwnd, out RECT rc); + + public static bool IsWindowFullscreen() { - return (GetWindowLong(GetForegroundWindow(), GWL_EXSTYLE) & WS_EX_TOPMOST) == WS_EX_TOPMOST; + RECT foreWinBounds; + Rectangle screenBounds; + var hWnd = GetForegroundWindow(); + if (!hWnd.Equals(IntPtr.Zero)) + { + if (!(hWnd.Equals(HWND_DESKTOP) || hWnd.Equals(HWND_SHELL))) + { + GetWindowRect(hWnd, out foreWinBounds); + screenBounds = Screen.FromHandle(hWnd).Bounds; + if ((foreWinBounds.Bottom - foreWinBounds.Top) == screenBounds.Height && (foreWinBounds.Right - foreWinBounds.Left) == screenBounds.Width) + { + return true; + } + } + } + + return false; } /// - /// disable windows toolbar's control box - /// this will also disable system menu with Alt+Space hotkey + /// disable windows toolbar's control box + /// this will also disable system menu with Alt+Space hotkey /// public static void DisableControlBox(Window win) { - var hwnd = new System.Windows.Interop.WindowInteropHelper(win).Handle; + var hwnd = new WindowInteropHelper(win).Handle; SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU); } + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } } -} +} \ No newline at end of file diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 01d9f94f79..07a98f0872 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -362,11 +362,11 @@ namespace Wox /// private bool ShouldIgnoreHotkeys() { - - if (!IsVisible - && UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus - && WindowIntelopHelper.IsForegroundWindowTopMost()) - return true; + //double if to omit calling win32 function + if (UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus) + if(WindowIntelopHelper.IsWindowFullscreen()) + return true; + return false; } From dc4c33c0d5db8b05c1c7f5594f2f3c429fb0a41f Mon Sep 17 00:00:00 2001 From: Boris Makogonyuk Date: Thu, 8 Oct 2015 01:02:36 +0200 Subject: [PATCH 3/3] Reflected functionality changes from the last commit on the whole project. --- Wox.Core/UserSettings/UserSettingStorage.cs | 2 +- Wox/Languages/en.xaml | 2 +- Wox/Languages/ru.xaml | 2 +- Wox/Languages/zh-cn.xaml | 2 +- Wox/Languages/zh-tw.xaml | 2 +- Wox/MainWindow.xaml.cs | 2 +- Wox/SettingWindow.xaml | 4 ++-- Wox/SettingWindow.xaml.cs | 10 +++++----- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Wox.Core/UserSettings/UserSettingStorage.cs b/Wox.Core/UserSettings/UserSettingStorage.cs index 75f00ce48a..632aaaa507 100644 --- a/Wox.Core/UserSettings/UserSettingStorage.cs +++ b/Wox.Core/UserSettings/UserSettingStorage.cs @@ -87,7 +87,7 @@ namespace Wox.Core.UserSettings public bool RememberLastLaunchLocation { get; set; } [JsonProperty] - public bool IgnoreHotkeysOnTopMostFocus { get; set; } + public bool IgnoreHotkeysOnFullscreen { get; set; } [JsonProperty] public string ProxyServer { get; set; } diff --git a/Wox/Languages/en.xaml b/Wox/Languages/en.xaml index 5871b9fae2..fe252ebb98 100644 --- a/Wox/Languages/en.xaml +++ b/Wox/Languages/en.xaml @@ -23,7 +23,7 @@ Remember last launch location Language Maximum show results - Ignore hotkeys if foreground window is TopMost + Ignore hotkeys if window is fullscreen Plugin diff --git a/Wox/Languages/ru.xaml b/Wox/Languages/ru.xaml index ebf3f14886..e09aa9bc73 100644 --- a/Wox/Languages/ru.xaml +++ b/Wox/Languages/ru.xaml @@ -23,7 +23,7 @@ Запомнить последнее место запуска Язык Максимальное количество результатов - Игнорировать горячие клавиши, если окно в фокусе самое верхнее + Игнорировать горячие клавиши, если окно в полноэкранном режиме Плагины diff --git a/Wox/Languages/zh-cn.xaml b/Wox/Languages/zh-cn.xaml index 7768be27ee..7e00547603 100644 --- a/Wox/Languages/zh-cn.xaml +++ b/Wox/Languages/zh-cn.xaml @@ -23,7 +23,7 @@ 记住上次启动位置 语言 最大结果显示个数 - Ignore hotkeys if foreground window is TopMost + Ignore hotkeys if foreground window is TopMost 插件 diff --git a/Wox/Languages/zh-tw.xaml b/Wox/Languages/zh-tw.xaml index ae59971755..0f1ab8f9c4 100644 --- a/Wox/Languages/zh-tw.xaml +++ b/Wox/Languages/zh-tw.xaml @@ -23,7 +23,7 @@ 记住上次启动位置 語言 最大結果顯示個數 - Ignore hotkeys if foreground window is TopMost + Ignore hotkeys if foreground window is TopMost 插件 diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 07a98f0872..9e305ff40c 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -363,7 +363,7 @@ namespace Wox private bool ShouldIgnoreHotkeys() { //double if to omit calling win32 function - if (UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus) + if (UserSettingStorage.Instance.IgnoreHotkeysOnFullscreen) if(WindowIntelopHelper.IsWindowFullscreen()) return true; diff --git a/Wox/SettingWindow.xaml b/Wox/SettingWindow.xaml index bc504df44c..b322cf16d5 100644 --- a/Wox/SettingWindow.xaml +++ b/Wox/SettingWindow.xaml @@ -35,8 +35,8 @@ - - + + diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs index 36021206de..5520b4c534 100644 --- a/Wox/SettingWindow.xaml.cs +++ b/Wox/SettingWindow.xaml.cs @@ -85,16 +85,16 @@ namespace Wox UserSettingStorage.Instance.Save(); }; - cbIgnoreHotkeysIfWindowIsTopmost.Checked += (o, e) => + cbIgnoreHotkeysOnFullscreen.Checked += (o, e) => { - UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus = true; + UserSettingStorage.Instance.IgnoreHotkeysOnFullscreen = true; UserSettingStorage.Instance.Save(); }; - cbIgnoreHotkeysIfWindowIsTopmost.Unchecked += (o, e) => + cbIgnoreHotkeysOnFullscreen.Unchecked += (o, e) => { - UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus = false; + UserSettingStorage.Instance.IgnoreHotkeysOnFullscreen = false; UserSettingStorage.Instance.Save(); }; @@ -110,7 +110,7 @@ namespace Wox cbHideWhenDeactive.IsChecked = UserSettingStorage.Instance.HideWhenDeactive; cbDontPromptUpdateMsg.IsChecked = UserSettingStorage.Instance.DontPromptUpdateMsg; cbRememberLastLocation.IsChecked = UserSettingStorage.Instance.RememberLastLaunchLocation; - cbIgnoreHotkeysIfWindowIsTopmost.IsChecked = UserSettingStorage.Instance.IgnoreHotkeysOnTopMostFocus; + cbIgnoreHotkeysOnFullscreen.IsChecked = UserSettingStorage.Instance.IgnoreHotkeysOnFullscreen; LoadLanguages(); comboMaxResultsToShow.ItemsSource = Enumerable.Range(2, 16);