diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5c956dc..fd830ef 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -53,3 +53,4 @@ jobs: artifacts: "*.zip" prerelease: true generateReleaseNotes: true + bodyFile: RELEASE.md diff --git a/PowerControl/App.config b/PowerControl/App.config index c500d4a..bc56eba 100644 --- a/PowerControl/App.config +++ b/PowerControl/App.config @@ -22,6 +22,9 @@ True + + True + \ No newline at end of file diff --git a/PowerControl/Controller.cs b/PowerControl/Controller.cs index f40e5d7..e1e8a3b 100644 --- a/PowerControl/Controller.cs +++ b/PowerControl/Controller.cs @@ -97,26 +97,38 @@ namespace PowerControl GlobalHotKey.RegisterHotKey(Settings.Default.MenuUpKey, () => { + if (!isForeground()) + return; rootMenu.Prev(); setDismissTimer(); - }); + dismissNeptuneInput(); + }, true); GlobalHotKey.RegisterHotKey(Settings.Default.MenuDownKey, () => { + if (!isForeground()) + return; rootMenu.Next(); setDismissTimer(); - }); + dismissNeptuneInput(); + }, true); GlobalHotKey.RegisterHotKey(Settings.Default.MenuLeftKey, () => { + if (!isForeground()) + return; rootMenu.SelectPrev(); setDismissTimer(); + dismissNeptuneInput(); }); GlobalHotKey.RegisterHotKey(Settings.Default.MenuRightKey, () => { + if (!isForeground()) + return; rootMenu.SelectNext(); setDismissTimer(); + dismissNeptuneInput(); }); if (Settings.Default.EnableNeptuneController) @@ -130,6 +142,29 @@ namespace PowerControl neptuneDevice.OpenDevice(); neptuneDevice.BeginRead(); } + + if (Settings.Default.EnableVolumeControls) + { + GlobalHotKey.RegisterHotKey("VolumeUp", () => + { + if ((neptuneDeviceState.buttons5 & (byte)SDCButton5.BTN_QUICK_ACCESS) != 0) + rootMenu.SelectNext("Brightness"); + else + rootMenu.SelectNext("Volume"); + setDismissTimer(); + dismissNeptuneInput(); + }); + + GlobalHotKey.RegisterHotKey("VolumeDown", () => + { + if ((neptuneDeviceState.buttons5 & (byte)SDCButton5.BTN_QUICK_ACCESS) != 0) + rootMenu.SelectPrev("Brightness"); + else + rootMenu.SelectPrev("Volume"); + setDismissTimer(); + dismissNeptuneInput(); + }); + } } private bool isForeground() @@ -197,6 +232,11 @@ namespace PowerControl Thread.Sleep(250); } + private void dismissNeptuneInput() + { + neptuneDeviceNextKey = DateTime.UtcNow.AddDays(1); + } + private void NeptuneTimer_Tick(object? sender, EventArgs e) { var input = neptuneDeviceState; @@ -210,6 +250,8 @@ namespace PowerControl if ((input.buttons5 & (byte)SDCButton5.BTN_QUICK_ACCESS) == 0 || !isForeground()) { + // schedule next repeat far in the future + dismissNeptuneInput(); hideOSD(); return; } @@ -251,6 +293,7 @@ namespace PowerControl if (!rootMenu.Visible) return; + Trace.WriteLine("Hide OSD"); rootMenu.Visible = false; osdDismissTimer.Stop(); updateOSD(); @@ -270,7 +313,10 @@ namespace PowerControl if (OSDHelpers.OSDIndex("Power Control") == 0 && OSD.GetOSDCount() > 1) osdClose(); if (osd == null) + { osd = new OSD("Power Control"); + Trace.WriteLine("Show OSD"); + } osd.Update(rootMenu.Render(null)); } catch (SystemException) @@ -294,7 +340,10 @@ namespace PowerControl try { if (osd != null) + { osd.Dispose(); + Trace.WriteLine("Close OSD"); + } osd = null; } catch (SystemException) diff --git a/PowerControl/External/GlobalHotKey.cs b/PowerControl/External/GlobalHotKey.cs index df5ab1f..0015a77 100644 --- a/PowerControl/External/GlobalHotKey.cs +++ b/PowerControl/External/GlobalHotKey.cs @@ -14,7 +14,7 @@ namespace PowerControl.External /// e.g. Alt + Shift + Control + Win + S /// Action to be called when hotkey is pressed /// true, if registration succeeded, otherwise false - public static bool RegisterHotKey(string aKeyGestureString, Action aAction) + public static bool RegisterHotKey(string aKeyGestureString, Action aAction, bool repeat = false) { if (aKeyGestureString == "") return false; @@ -24,13 +24,13 @@ namespace PowerControl.External foreach (var gesture in aKeyGestureString.Split(",")) { KeyGesture aKeyGesture = (KeyGesture)c.ConvertFrom(gesture); - if (RegisterHotKey(aKeyGesture.Modifiers, aKeyGesture.Key, aAction)) + if (RegisterHotKey(aKeyGesture.Modifiers, aKeyGesture.Key, aAction, repeat)) success = true; } return success; } - public static bool RegisterHotKey(ModifierKeys aModifier, Key aKey, Action aAction) + public static bool RegisterHotKey(ModifierKeys aModifier, Key aKey, Action aAction, bool repeat = false) { if (aModifier == ModifierKeys.None && false) { @@ -44,7 +44,7 @@ namespace PowerControl.External System.Windows.Forms.Keys aVirtualKeyCode = (System.Windows.Forms.Keys)KeyInterop.VirtualKeyFromKey(aKey); currentID = currentID + 1; bool aRegistered = RegisterHotKey(window.Handle, currentID, - (uint)aModifier | MOD_NOREPEAT, + (uint)aModifier | (repeat ? 0 : MOD_NOREPEAT), (uint)aVirtualKeyCode); if (aRegistered) diff --git a/PowerControl/Menu.cs b/PowerControl/Menu.cs index bc11a82..1992f8f 100644 --- a/PowerControl/Menu.cs +++ b/PowerControl/Menu.cs @@ -272,6 +272,19 @@ namespace PowerControl public delegate void VisibleChangedDelegate(); public VisibleChangedDelegate? VisibleChanged; + public MenuItem this[String name] + { + get + { + foreach(var item in Items) + { + if (item.Name == name) + return item; + } + return null; + } + } + public override void CreateMenu(ToolStripItemCollection collection) { foreach(var item in Items) @@ -374,6 +387,19 @@ namespace PowerControl } } + public void SelectNext(String name) + { + var item = this[name]; + if (item is null) + return; + + Show(); + Selected = item; + item.SelectNext(); + if (VisibleChanged != null) + VisibleChanged(); + } + public override void SelectPrev() { if (Show()) @@ -386,6 +412,19 @@ namespace PowerControl VisibleChanged(); } } + + public void SelectPrev(String name) + { + var item = this[name]; + if (item is null) + return; + + Show(); + Selected = item; + item.SelectPrev(); + if (VisibleChanged != null) + VisibleChanged(); + } } } } diff --git a/PowerControl/Settings.Designer.cs b/PowerControl/Settings.Designer.cs index 7f78a01..b01e243 100644 --- a/PowerControl/Settings.Designer.cs +++ b/PowerControl/Settings.Designer.cs @@ -67,5 +67,14 @@ namespace PowerControl { return ((bool)(this["EnableNeptuneController"])); } } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool EnableVolumeControls { + get { + return ((bool)(this["EnableVolumeControls"])); + } + } } } diff --git a/PowerControl/Settings.settings b/PowerControl/Settings.settings index 39119ea..432282a 100644 --- a/PowerControl/Settings.settings +++ b/PowerControl/Settings.settings @@ -17,5 +17,8 @@ True + + True + \ No newline at end of file diff --git a/README.md b/README.md index bd4dd72..e6776bf 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,9 @@ There are currently 4 configurable settings: It will only work in OSD mode when rendering graphics. The notification setting is always available. -- SteamDeck Controller: press Quick Access (3 dots), and then together DPad Left, Rigth, Up, Down. +- SteamDeck Controller: press and hold Quick Access (3 dots), and then DPad Left, Rigth, Up, Down. +- Control Volume: use Volume Up and Down +- Control Brightness: press and hold Quick Access (3 dots), and then Volume Up and Down - Keyboard: `Ctrl+Win+Numpad2` (Down), `Ctrl+Win+Numpad4` (Left), `Ctrl+Win+Numpad6` (Right), `Ctrl+Win+Numpad8` (Up) ### 3.2. SWICD configuration diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..a602410 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,7 @@ +- Adds Power Control +- Repeat keystrokes +- Allow to control OSD and Fan from Power Control +- Improve flickering of OSD +- Add Volume Up/Down controls (disable with `EnableVolumeControl` in `PowerControl.dll.config`) + +If you found it useful buy me [Ko-fi](https://ko-fi.com/ayufan).