diff --git a/DD2Switcher/KeyboardHook.cs b/DD2Switcher/KeyboardHook.cs index b2a2258..aeed6d1 100644 --- a/DD2Switcher/KeyboardHook.cs +++ b/DD2Switcher/KeyboardHook.cs @@ -37,13 +37,15 @@ class KeyboardHook { int pero = (int)wParam * 1000 + vkCode; if (pero != previousEvent) { if (wParam == (IntPtr)WM_KEYDOWN) { + Console.WriteLine($"KeyboardHook: KeyDown event for key {vkCode}"); KeyDown?.Invoke(null, vkCode); } else if (wParam == (IntPtr)WM_KEYUP) { + Console.WriteLine($"KeyboardHook: KeyUp event for key {vkCode}"); KeyUp?.Invoke(null, vkCode); } previousEvent = pero; } else { - Console.WriteLine("Same event"); + Console.WriteLine($"KeyboardHook: Same event filtered out - vkCode: {vkCode}, wParam: {wParam}"); } } return CallNextHookEx(_hookID, nCode, wParam, lParam); diff --git a/DD2Switcher/Program.cs b/DD2Switcher/Program.cs index f369034..907459c 100644 --- a/DD2Switcher/Program.cs +++ b/DD2Switcher/Program.cs @@ -36,48 +36,75 @@ namespace DD2Switcher { } public static void StartSequenceMode() { + Console.WriteLine($"StartSequenceMode called. FirstIndex: {FirstIndex}, LastIndex: {LastIndex}"); if (FirstIndex >= 0 && LastIndex >= 0 && FirstIndex <= LastIndex) { - SequenceMode = true; + CurrentState = SequenceState.PROCESSING; CurrentSequenceIndex = FirstIndex; + Console.WriteLine($"Starting sequence mode, tabbing to index {CurrentSequenceIndex + 1}"); TabTo(CurrentSequenceIndex + 1); // Tab to first window + CurrentState = SequenceState.WAITING; + Console.WriteLine($"State changed to: {CurrentState}"); + } else { + Console.WriteLine("Cannot start sequence mode - invalid first/last indices"); } } public static void NextSequenceStep() { - if (!SequenceMode) + Console.WriteLine( + $"NextSequenceStep called. State: {CurrentState}, CurrentIndex: {CurrentSequenceIndex}, LastIndex: {LastIndex}"); + if (CurrentState == SequenceState.INACTIVE) return; + CurrentState = SequenceState.PROCESSING; CurrentSequenceIndex++; + Console.WriteLine($"Advanced to index {CurrentSequenceIndex}"); if (CurrentSequenceIndex > LastIndex) { // End of sequence + Console.WriteLine("End of sequence reached, exiting sequence mode"); ExitSequenceMode(); } else { + Console.WriteLine($"Tabbing to index {CurrentSequenceIndex + 1}"); TabTo(CurrentSequenceIndex + 1); + CurrentState = SequenceState.WAITING; + Console.WriteLine($"State changed to: {CurrentState}"); } } public static void ExitSequenceMode() { - SequenceMode = false; + CurrentState = SequenceState.INACTIVE; CurrentSequenceIndex = -1; + Console.WriteLine($"State changed to: {CurrentState}"); + } + + public static bool IsInSequenceMode() { + return CurrentState != SequenceState.INACTIVE; } public static void UpdateSequenceHotkey(Keys newKey) { + Console.WriteLine($"UpdateSequenceHotkey called with new key: {newKey} (code: {(int)newKey})"); + Console.WriteLine($"Old SequenceKeybind before update: {SequenceKeybind} (code: {(int)SequenceKeybind})"); + // Unregister old hotkey if (sequenceHotkeyId != -1) { + Console.WriteLine($"Unregistering old hotkey ID: {sequenceHotkeyId}"); HotKeyManager.UnregisterHotKey(sequenceHotkeyId); } // Register new hotkey sequenceHotkeyId = HotKeyManager.RegisterHotKey(newKey, KeyModifiers.NoRepeat); + Console.WriteLine($"Registered new hotkey ID: {sequenceHotkeyId} for key: {newKey}"); SequenceKeybind = newKey; + Console.WriteLine($"New SequenceKeybind after update: {SequenceKeybind} (code: {(int)SequenceKeybind})"); } // Static properties for first/last selection persistence public static int FirstIndex { get; set; } = -1; public static int LastIndex { get; set; } = -1; - // Sequence mode state - public static bool SequenceMode { get; set; } = false; + // Sequence mode state engine + public enum SequenceState { INACTIVE, WAITING, PROCESSING } + + public static SequenceState CurrentState { get; set; } = SequenceState.INACTIVE; public static int CurrentSequenceIndex { get; set; } = -1; public static Keys SequenceKeybind { get; set; } = Keys.F1; private static int sequenceHotkeyId = -1; @@ -107,6 +134,48 @@ namespace DD2Switcher { [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo); + [DllImport("user32.dll")] + private static extern IntPtr SetWindowsHookEx(int idHook, IntPtr lpfn, IntPtr hMod, uint dwThreadId); + + [DllImport("user32.dll")] + private static extern bool UnhookWindowsHookEx(IntPtr hhk); + + [DllImport("user32.dll")] + private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); + + [DllImport("kernel32.dll")] + private static extern IntPtr GetModuleHandle(string lpModuleName); + + private const int WH_MOUSE_LL = 14; + private const int WM_LBUTTONDOWN = 0x0201; + private const int WM_RBUTTONDOWN = 0x0204; + private const int WM_MBUTTONDOWN = 0x0207; + private static IntPtr mouseHookId = IntPtr.Zero; + private static IntPtr mouseHookProc = IntPtr.Zero; + private static MouseHookProc mouseHookDelegate; // Keep reference to prevent GC + + private delegate IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam); + + private static void HandleSequenceEvent() { + if (CurrentState == SequenceState.WAITING) { + Console.WriteLine($"Event detected in state: {CurrentState}, advancing to next step"); + NextSequenceStep(); + } + } + + private static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam) { + if (nCode >= 0) { + int wParamInt = (int)wParam; + if (wParamInt == WM_LBUTTONDOWN || wParamInt == WM_RBUTTONDOWN || wParamInt == WM_MBUTTONDOWN) { + if (CurrentState == SequenceState.WAITING) { + Console.WriteLine($"Mouse click detected in state: {CurrentState}"); + HandleSequenceEvent(); + } + } + } + return CallNextHookEx(mouseHookId, nCode, wParam, lParam); + } + private static void CleanWindows() { for (int i = 0; i < NumProc; i++) { var window = windows[i]; @@ -293,6 +362,7 @@ namespace DD2Switcher { } private static void TabTo(int index) { + Console.WriteLine($"TabTo called with index: {index}"); index = (index - 1) % NumProc; if (index < 0) index = NumProc - 1; @@ -302,6 +372,9 @@ namespace DD2Switcher { Console.WriteLine($"Tab to window at index {index}"); var window = windows[index]; + Console.WriteLine( + $"Window at index {index}: {(window == null ? "NULL" : window.ProcessName + " PID:" + window.Id)}"); + if (window == null || window.MainWindowHandle == IntPtr.Zero) { Console.WriteLine($"Window at index {index} does not exist, removing from tracked windows"); windows[index] = null; @@ -309,10 +382,27 @@ namespace DD2Switcher { if (ActiveIndex != -1) PushHistory(ActiveIndex); - SetForegroundWindow(window.MainWindowHandle); + Console.WriteLine($"Setting foreground window to: {window.ProcessName} PID:{window.Id}"); + bool result = SetForegroundWindow(window.MainWindowHandle); + Console.WriteLine($"SetForegroundWindow result: {result}"); + + // Force window to front with additional methods + if (result) { + // Bring window to front and activate it + SetForegroundWindow(window.MainWindowHandle); + System.Threading.Thread.Sleep(50); // Small delay + + // Check if it actually worked + var currentForeground = GetForegroundWindow(); + bool actuallySwitched = (currentForeground == window.MainWindowHandle); + Console.WriteLine( + $"Actually switched: {actuallySwitched} (Current: {currentForeground}, Target: {window.MainWindowHandle})"); + } + ActiveIndex = index; AdjustAffinities(); AdjustPriorities(); + Console.WriteLine($"Successfully switched to window at index {index}"); } } @@ -360,6 +450,7 @@ namespace DD2Switcher { [STAThread] private static void Main() { + // AllocConsole(); // Enable console for debug output Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); @@ -374,6 +465,12 @@ namespace DD2Switcher { bool onlyAlt = false; KeyboardHook.Start(); + + // Set up mouse hook for sequence mode + mouseHookDelegate = new MouseHookProc(MouseHookCallback); + mouseHookProc = Marshal.GetFunctionPointerForDelegate(mouseHookDelegate); + mouseHookId = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProc, + GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); KeyboardHook.KeyDown += (sender, e) => { Console.WriteLine($"Key down: {e}"); if (e == 164 && !onlyAlt) { @@ -391,6 +488,17 @@ namespace DD2Switcher { onlyAlt = false; TabToPrevious(); } + + // Handle sequence mode event detection with KeyUp + if (CurrentState == SequenceState.WAITING) { + // Ignore the sequence keybind itself + if (e != (int)SequenceKeybind) { + Console.WriteLine($"Key up detected in state: {CurrentState} - Key: {e}"); + HandleSequenceEvent(); + } else { + Console.WriteLine($"Ignoring sequence keybind release: {e}"); + } + } }; HotKeyManager.RegisterHotKey(Keys.Capital, KeyModifiers.NoRepeat); @@ -402,21 +510,37 @@ namespace DD2Switcher { HotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Alt); sequenceHotkeyId = HotKeyManager.RegisterHotKey(SequenceKeybind, KeyModifiers.NoRepeat); + Console.WriteLine( + $"Initial sequence hotkey registration - ID: {sequenceHotkeyId}, Key: {SequenceKeybind} (code: {(int)SequenceKeybind})"); HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed; void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e) { + Console.WriteLine($"Hotkey pressed: {e.Key} with modifiers {e.Modifiers}"); + Console.WriteLine($"Current sequence keybind: {SequenceKeybind}"); + Console.WriteLine($"Key codes - Pressed: {(int)e.Key}, Expected: {(int)SequenceKeybind}"); + // Check for sequence mode keybind - if (e.Key == SequenceKeybind && e.Modifiers == KeyModifiers.NoRepeat) { - if (SequenceMode) { + Console.WriteLine( + $"Checking sequence keybind - Key: {e.Key} == {SequenceKeybind} = {e.Key == SequenceKeybind}"); + Console.WriteLine($"Checking modifiers - Received: {e.Modifiers}, Expected: {KeyModifiers.NoRepeat}"); + if (e.Key == SequenceKeybind) { + Console.WriteLine("Sequence keybind detected!"); + if (CurrentState != SequenceState.INACTIVE) { + Console.WriteLine("Advancing sequence step"); NextSequenceStep(); } else { + Console.WriteLine("Starting sequence mode"); StartSequenceMode(); } return; + } else { + Console.WriteLine( + $"Sequence keybind check failed - Key match: {e.Key == SequenceKeybind}, Modifiers match: {e.Modifiers == KeyModifiers.NoRepeat}"); } // Cancel sequence mode on any manual window switching - if (SequenceMode && e.Modifiers == KeyModifiers.Alt) { + if (CurrentState != SequenceState.INACTIVE && e.Modifiers == KeyModifiers.Alt) { + Console.WriteLine("Manual window switching detected, cancelling sequence mode"); ExitSequenceMode(); } @@ -448,6 +572,11 @@ namespace DD2Switcher { // Run the WinForms application with Form1 as the main form Application.Run(new Form1()); KeyboardHook.Stop(); + + // Clean up mouse hook + if (mouseHookId != IntPtr.Zero) { + UnhookWindowsHookEx(mouseHookId); + } } } } diff --git a/DD2Switcher/SettingsForm.cs b/DD2Switcher/SettingsForm.cs index 8ed5ca8..dc6ed57 100644 --- a/DD2Switcher/SettingsForm.cs +++ b/DD2Switcher/SettingsForm.cs @@ -13,7 +13,6 @@ namespace DD2Switcher { private FlowLayoutPanel windowsPanel; private Label sequenceKeybindLabel; private TextBox sequenceKeybindTextBox; - private Timer statusTimer; public SettingsForm() { InitializeComponent(); @@ -107,6 +106,7 @@ namespace DD2Switcher { this.Name = "SettingsForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "DD2Switcher Settings"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SettingsForm_FormClosing); this.tabControl.ResumeLayout(false); this.windowsTab.ResumeLayout(false); this.sequenceTab.ResumeLayout(false); @@ -236,13 +236,29 @@ namespace DD2Switcher { } private void sequenceKeybindTextBox_Leave(object sender, EventArgs e) { + Console.WriteLine($"sequenceKeybindTextBox_Leave called with text: {sequenceKeybindTextBox.Text}"); try { KeysConverter converter = new KeysConverter(); Keys newKey = (Keys)converter.ConvertFromString(sequenceKeybindTextBox.Text); + Console.WriteLine($"Converted key: {newKey} (code: {(int)newKey})"); Program.UpdateSequenceHotkey(newKey); - } catch { + Console.WriteLine("Keybind updated successfully!"); + } catch (Exception ex) { + Console.WriteLine($"Error converting key: {ex.Message}"); sequenceKeybindTextBox.Text = Program.SequenceKeybind.ToString(); } } + + private void SettingsForm_FormClosing(object sender, FormClosingEventArgs e) { + Console.WriteLine("SettingsForm closing - saving keybind"); + try { + KeysConverter converter = new KeysConverter(); + Keys newKey = (Keys)converter.ConvertFromString(sequenceKeybindTextBox.Text); + Console.WriteLine($"Saving keybind on close: {newKey}"); + Program.UpdateSequenceHotkey(newKey); + } catch (Exception ex) { + Console.WriteLine($"Error saving keybind on close: {ex.Message}"); + } + } } } \ No newline at end of file