Initial commit: Complete open-source Decal rebuild
All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
d1442e3747
1382 changed files with 170725 additions and 0 deletions
161
Managed/Decal.DHS/HotkeySystemImpl.cs
Normal file
161
Managed/Decal.DHS/HotkeySystemImpl.cs
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Decal.Interop.Core;
|
||||
using Decal.Interop.DHS;
|
||||
|
||||
namespace Decal.DHS
|
||||
{
|
||||
internal class RegisteredHotkey
|
||||
{
|
||||
public string PluginCookie;
|
||||
public HotkeyImpl Hotkey;
|
||||
}
|
||||
|
||||
[ComVisible(true)]
|
||||
[Guid("6B6B9FA8-37DE-4FA3-8C60-52BD6A2F9855")]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ComSourceInterfaces(typeof(_IHotkeySystemEvents))]
|
||||
[ProgId("DHS.HotkeySystem")]
|
||||
public class HotkeySystemImpl : IHotkeySystem, IDecalService
|
||||
{
|
||||
private readonly List<RegisteredHotkey> _hotkeys = new List<RegisteredHotkey>();
|
||||
private readonly Dictionary<object, IDHSHotkeyEvents> _connectedPlugins = new Dictionary<object, IDHSHotkeyEvents>();
|
||||
|
||||
// COM event — raised when a hotkey fires
|
||||
public event _IHotkeySystemEvents_HotkeyEventEventHandler HotkeyEvent;
|
||||
|
||||
public void AddHotkey(string szPlugin, Hotkey pHotkey)
|
||||
{
|
||||
var impl = pHotkey as HotkeyImpl;
|
||||
if (impl == null)
|
||||
{
|
||||
// Wrap foreign IHotkey implementation
|
||||
impl = new HotkeyImpl
|
||||
{
|
||||
EventTitle = ((IHotkey)pHotkey).EventTitle,
|
||||
EventDescription = ((IHotkey)pHotkey).EventDescription,
|
||||
AltState = ((IHotkey)pHotkey).AltState,
|
||||
ControlState = ((IHotkey)pHotkey).ControlState,
|
||||
ShiftState = ((IHotkey)pHotkey).ShiftState,
|
||||
VirtualKey = ((IHotkey)pHotkey).VirtualKey
|
||||
};
|
||||
}
|
||||
|
||||
_hotkeys.Add(new RegisteredHotkey
|
||||
{
|
||||
PluginCookie = szPlugin,
|
||||
Hotkey = impl
|
||||
});
|
||||
}
|
||||
|
||||
public bool QueryHotkey(string bstrTitle)
|
||||
{
|
||||
foreach (var rh in _hotkeys)
|
||||
{
|
||||
if (string.Equals(rh.Hotkey.EventTitle, bstrTitle, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Hotkey QueryHotkeyEx(string szPluginCookie, string szTitle)
|
||||
{
|
||||
foreach (var rh in _hotkeys)
|
||||
{
|
||||
if (string.Equals(rh.PluginCookie, szPluginCookie, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(rh.Hotkey.EventTitle, szTitle, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return (Hotkey)(object)rh.Hotkey;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Connect(object pPlugin)
|
||||
{
|
||||
// Plugin implements IDHSHotkeyEvents for receiving hotkey notifications
|
||||
var events = pPlugin as IDHSHotkeyEvents;
|
||||
if (events != null)
|
||||
{
|
||||
_connectedPlugins[pPlugin] = events;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteHotkey(string szPluginCookie, string szHotkeyName)
|
||||
{
|
||||
_hotkeys.RemoveAll(rh =>
|
||||
string.Equals(rh.PluginCookie, szPluginCookie, StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(rh.Hotkey.EventTitle, szHotkeyName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by the input system when a key combination matches a registered hotkey.
|
||||
/// Fires the HotkeyEvent and notifies connected plugins.
|
||||
/// </summary>
|
||||
internal bool FireHotkey(string eventTitle)
|
||||
{
|
||||
bool eat = false;
|
||||
|
||||
// Fire COM connection point event
|
||||
HotkeyEvent?.Invoke(eventTitle, ref eat);
|
||||
if (eat) return true;
|
||||
|
||||
// Notify connected plugins via IDHSHotkeyEvents
|
||||
foreach (var plugin in _connectedPlugins.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (plugin.OnHotkey(eventTitle))
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Plugin error — don't propagate
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a key press matches any registered hotkey and fire it.
|
||||
/// </summary>
|
||||
internal bool ProcessKey(int virtualKey, bool alt, bool ctrl, bool shift)
|
||||
{
|
||||
foreach (var rh in _hotkeys)
|
||||
{
|
||||
var hk = rh.Hotkey;
|
||||
if (hk.VirtualKey == virtualKey &&
|
||||
hk.AltState == alt &&
|
||||
hk.ControlState == ctrl &&
|
||||
hk.ShiftState == shift)
|
||||
{
|
||||
if (FireHotkey(hk.EventTitle))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// IDecalService implementation
|
||||
public void Initialize(DecalCore pDecal)
|
||||
{
|
||||
// DHS doesn't need DecalCore reference directly
|
||||
}
|
||||
|
||||
public void BeforePlugins()
|
||||
{
|
||||
}
|
||||
|
||||
public void AfterPlugins()
|
||||
{
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
_hotkeys.Clear();
|
||||
_connectedPlugins.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue