public void Refresh() { const int len = 256; string wclass = "?", wname = "?"; StringBuilder buf = new StringBuilder(len); if (NativeMethods.GetClassName(Hwnd, buf, len) > 0) { wclass = buf.ToString(); } buf = new StringBuilder(len); if (NativeMethods.GetWindowText(Hwnd, buf, len) > 0) { wname = buf.ToString(); } Log.Debug($"Window {Hwnd} (class: {wclass}) (name: {wname}) got focus"); IsGtk = m_match_gtk.Match(wclass).Success; IsOffice = m_match_office.Match(wclass).Success; IsOtherDesktop = m_match_desktop.Match(wclass).Success; try { var regex = new Regex($"^({Settings.IgnoreRegex})$"); IsOtherDesktop = IsOtherDesktop || regex.Match(wclass).Success || regex.Match(wname).Success; } catch {} }
private static void CheckKeyboardLayout() { // Detect keyboard layout changes by querying the foreground window, // and apply the same layout to WinCompose itself. IntPtr hwnd = NativeMethods.GetForegroundWindow(); uint pid, tid = NativeMethods.GetWindowThreadProcessId(hwnd, out pid); IntPtr active_layout = NativeMethods.GetKeyboardLayout(tid); m_window_is_gtk = false; m_window_is_office = false; m_window_is_other_desktop = false; const int len = 256; StringBuilder buf = new StringBuilder(len); if (NativeMethods.GetClassName(hwnd, buf, len) > 0) { string wclass = buf.ToString(); if (wclass == "gdkWindowToplevel" || wclass == "xchatWindowToplevel" || wclass == "hexchatWindowToplevel") { m_window_is_gtk = true; } if (wclass == "rctrl_renwnd32" || wclass == "OpusApp") { m_window_is_office = true; } if (Regex.Match(wclass, "^(SynergyDesk|cygwin/x.*)$").Success) { m_window_is_other_desktop = true; } } if (active_layout != m_current_layout) { m_current_layout = active_layout; Log.Debug("Active window layout tid:{0} handle:0x{1:X} lang:0x{2:X}", tid, (uint)active_layout >> 16, (uint)active_layout & 0xffff); if (active_layout != (IntPtr)0) { NativeMethods.ActivateKeyboardLayout(active_layout, 0); } tid = NativeMethods.GetCurrentThreadId(); active_layout = NativeMethods.GetKeyboardLayout(tid); Log.Debug("WinCompose process layout tid:{0} handle:0x{1:X} lang:0x{2:X}", tid, (uint)active_layout >> 16, (uint)active_layout & 0xffff); // We need to rebuild the list of dead keys AnalyzeKeyboardLayout(); } }
private static void SendString(string str) { List <VK> modifiers = new List <VK>(); bool use_gtk_hack = false, use_office_hack = false; const int len = 256; StringBuilder buf = new StringBuilder(len); var hwnd = NativeMethods.GetForegroundWindow(); if (NativeMethods.GetClassName(hwnd, buf, len) > 0) { string wclass = buf.ToString(); /* HACK: GTK+ applications behave differently with Unicode, and some * applications such as XChat for Windows rename their own top-level * window, so we parse through the names we know in order to detect * a GTK+ application. */ if (wclass == "gdkWindowToplevel" || wclass == "xchatWindowToplevel") { use_gtk_hack = true; } /* HACK: in MS Office, some symbol insertions change the text font * without returning to the original font. To avoid this, we output * a space character, then go left, insert our actual symbol, then * go right and backspace. */ /* These are the actual window class names for Outlook and Word… * TODO: PowerPoint ("PP(7|97|9|10)FrameClass") */ if (wclass == "rctrl_renwnd32" || wclass == "OpusApp") { use_office_hack = true && Settings.InsertZwsp.Value; } } /* Clear keyboard modifiers if we need one of our custom hacks */ if (use_gtk_hack || use_office_hack) { VK[] all_modifiers = new VK[] { VK.LSHIFT, VK.RSHIFT, VK.LCONTROL, VK.RCONTROL, VK.LMENU, VK.RMENU, }; foreach (VK vk in all_modifiers) { if ((NativeMethods.GetKeyState(vk) & 0x80) == 0x80) { modifiers.Add(vk); } } foreach (VK vk in modifiers) { SendKeyUp(vk); } } if (use_gtk_hack) { /* Wikipedia says Ctrl+Shift+u, release, then type the four hex * digits, and press Enter. * (http://en.wikipedia.org/wiki/Unicode_input). */ SendKeyDown(VK.LCONTROL); SendKeyDown(VK.LSHIFT); SendKeyPress((VK)'U'); SendKeyUp(VK.LSHIFT); SendKeyUp(VK.LCONTROL); foreach (var ch in str) { foreach (var key in String.Format("{0:X04} ", (short)ch)) { SendKeyPress((VK)key); } } } else { InputSequence Seq = new InputSequence(); if (use_office_hack) { Seq.Add((ScanCodeShort)'\u200b'); Seq.Add((VirtualKeyShort)VK.LEFT); } for (int i = 0; i < str.Length; i++) { Seq.Add((ScanCodeShort)str[i]); } if (use_office_hack) { Seq.Add((VirtualKeyShort)VK.RIGHT); } Seq.Send(); } /* Restore keyboard modifiers if we needed one of our custom hacks */ if (use_gtk_hack || use_office_hack) { foreach (VK vk in modifiers) { SendKeyDown(vk); } } }
public static void CheckForChanges() { // Detect keyboard layout changes by querying the foreground window, // and apply the same layout to WinCompose itself. IntPtr hwnd = NativeMethods.GetForegroundWindow(); uint pid, tid = NativeMethods.GetWindowThreadProcessId(hwnd, out pid); IntPtr active_layout = NativeMethods.GetKeyboardLayout(tid); if (hwnd != m_current_hwnd) { Window.IsGtk = false; Window.IsNPPOrLO = false; Window.IsOffice = false; Window.IsOtherDesktop = false; const int len = 256; StringBuilder buf = new StringBuilder(len); if (NativeMethods.GetClassName(hwnd, buf, len) > 0) { string wclass = buf.ToString(); Log.Debug($"Window {hwnd} ({wclass}) got focus"); if (wclass == "gdkWindowToplevel" || wclass == "xchatWindowToplevel" || wclass == "hexchatWindowToplevel") { Window.IsGtk = true; } /* Notepad++ or LibreOffice */ if (wclass == "Notepad++" || wclass == "SALFRAME") { Window.IsNPPOrLO = true; } if (wclass == "rctrl_renwnd32" || wclass == "OpusApp") { Window.IsOffice = true; } if (Regex.Match(wclass, "^(SynergyDesk|cygwin/x.*)$").Success) { Window.IsOtherDesktop = true; } } m_current_hwnd = hwnd; } if (active_layout != m_current_layout) { m_current_layout = active_layout; Log.Debug("Active window layout tid:{0} handle:0x{1:X} lang:0x{2:X}", tid, (uint)active_layout >> 16, (uint)active_layout & 0xffff); if (active_layout != (IntPtr)0) { NativeMethods.ActivateKeyboardLayout(active_layout, 0); } tid = NativeMethods.GetCurrentThreadId(); active_layout = NativeMethods.GetKeyboardLayout(tid); Log.Debug("WinCompose process layout tid:{0} handle:0x{1:X} lang:0x{2:X}", tid, (uint)active_layout >> 16, (uint)active_layout & 0xffff); // We need to rebuild the list of dead keys AnalyzeLayout(); } }