private static void ComposerStateChanged(object sender, EventArgs e) { m_tray_icon.Icon = Composer.IsDisabled() ? Properties.Resources.IconDisabled : Composer.IsComposing() ? Properties.Resources.IconActive : Properties.Resources.IconNormal; m_tray_icon.Text = Composer.IsDisabled() ? i18n.Text.DisabledToolTip : String.Format(i18n.Text.TrayToolTip, Settings.ComposeKey.Value.FriendlyName, Settings.GetSequenceCount(), Program.Version); m_disable_item.Checked = Composer.IsDisabled(); }
private static int OnKey(HC nCode, WM wParam, IntPtr lParam) { bool is_key = (wParam == WM.KEYDOWN || wParam == WM.SYSKEYDOWN || wParam == WM.KEYUP || wParam == WM.SYSKEYUP); if (m_duplicate != 0) { // Do nothing. We can only get here if a key is pressed during // the very short time where we have two hooks installed, i.e. // practically never, but it’s better to handle this properly. } else if (nCode == HC.ACTION && is_key) { // Retrieve key event data from native structure var data = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); bool is_injected = (data.flags & LLKHF.INJECTED) != 0; bool accept = !is_injected || (Settings.AllowInjected.Value && m_recursive == 0); Logger.Debug("{0}{1}: OnKey(HC.{2}, WM.{3}, [vk:0x{4:X02} ({7}) sc:0x{5:X02} flags:{6}])", accept ? "" : "Ignored ", is_injected ? "Injected Event" : "Event", nCode, wParam, (int)data.vk, (int)data.sc, data.flags, new Key(data.vk)); if (accept) { ++m_recursive; bool processed = Composer.OnKey(wParam, data.vk, data.sc, data.flags); --m_recursive; if (processed) { return(-1); // Do not process further: that key was for us. } } } else { Logger.Debug("Ignored Event: OnKey({0}, {1})", nCode, wParam); } // Call next hook but guard against re-doing our own work in case we // were installed twice. ++m_duplicate; int ret = NativeMethods.CallNextHookEx(m_hook, nCode, wParam, lParam); --m_duplicate; return(ret); }
static void Main(string[] args) { // Some commandline flags just trigger a message broadcast var command_flags = new Dictionary <string, MenuCommand>() { { "-sequences", MenuCommand.ShowSequences }, { "-settings", MenuCommand.ShowOptions }, }; foreach (var arg in args) { if (command_flags.TryGetValue(arg, out var cmd)) { NativeMethods.PostMessage(HWND.BROADCAST, WM_WINCOMPOSE.OPEN, (int)cmd, 0); return; } } // Do this before Composer.Init() because of the Disabled setting Settings.LoadConfig(); Composer.Init(); Settings.LoadSequences(); Metadata.LoadDB(); KeyboardHook.Init(); Updater.Init(); Settings.StartWatchConfigFile(); try { var app = new Application(); var icon = new SysTrayIcon(); app.Exit += (o, e) => icon.Dispose(); app.Run(); } finally { Settings.StopWatchConfigFile(); Updater.Fini(); KeyboardHook.Fini(); Settings.SaveConfig(); Metadata.SaveDB(); Composer.Fini(); Updater.Fini(); } }
private static string GetCurrentToolTip() { string ret = i18n.Text.DisabledToolTip; if (!Composer.IsDisabled()) { ret = string.Format(i18n.Text.TrayToolTip, Settings.ComposeKeys.Value.FriendlyName, Settings.SequenceCount, Settings.Version); } if (Updater.HasNewerVersion()) { ret += "\n" + i18n.Text.UpdatesToolTip; } return(ret); }
private static void SysTrayUpdateCallback(object sender, EventArgs e) { m_tray_icon.Icon = GetCurrentIcon(); // XXX: we cannot directly set m_tray_icon.Text because it has an // erroneous 64-character limitation (the underlying framework has // the correct 128-char limitation). So instead we use this hack, // taken from http://stackoverflow.com/a/580264/111461 Type t = typeof(WinForms.NotifyIcon); BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance; t.GetField("text", hidden).SetValue(m_tray_icon, GetCurrentToolTip()); if ((bool)t.GetField("added", hidden).GetValue(m_tray_icon)) { t.GetMethod("UpdateIcon", hidden).Invoke(m_tray_icon, new object[] { true }); } m_disable_item.Checked = Composer.IsDisabled(); }
static void Main() { // Do this before Composer.Init() because of the Disabled setting Settings.LoadConfig(); Composer.Init(); Settings.LoadSequences(); Updater.Init(); Settings.StartWatchConfigFile(); try { WinForms.Application.EnableVisualStyles(); WinForms.Application.SetCompatibleTextRenderingDefault(false); // Must call this after SetCompatibleTextRenderingDefault() // because it uses a WinForms timer which seems to open a // hidden window. The reason we use a WinForms timer is so that // the hook is installed from the main thread. KeyboardHook.Init(); using (SysTrayIcon icon = new SysTrayIcon()) { WinForms.Application.Run(); } } finally { Settings.StopWatchConfigFile(); Updater.Fini(); KeyboardHook.Fini(); Settings.SaveConfig(); Composer.Fini(); Updater.Fini(); } }
private static int OnKey(HC nCode, WM wParam, IntPtr lParam) { if (nCode == HC.ACTION) { // Retrieve event data from native structure var data = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); bool is_key = (wParam == WM.KEYDOWN || wParam == WM.SYSKEYDOWN || wParam == WM.KEYUP || wParam == WM.SYSKEYUP); bool is_injected = (data.flags & LLKHF.INJECTED) != 0; if (is_key && !is_injected) { if (Composer.OnKey(wParam, data.vk, data.sc, data.flags)) { // Do not process further: that key was for us. return(-1); } } } return(NativeMethods.CallNextHookEx(m_hook, nCode, wParam, lParam)); }
private void OnMenuItemClicked(object parameter) { switch (parameter as MenuCommand?) { case MenuCommand.ShowSequences: if (m_sequencewindow == null) { m_sequencewindow = new SequenceWindow(); WinForms.Integration.ElementHost.EnableModelessKeyboardInterop(m_sequencewindow); } m_sequencewindow.Show(); m_sequencewindow.Activate(); break; case MenuCommand.ShowOptions: if (m_optionswindow == null) { m_optionswindow = new SettingsWindow(); WinForms.Integration.ElementHost.EnableModelessKeyboardInterop(m_optionswindow); } m_optionswindow.Show(); m_optionswindow.Activate(); break; case MenuCommand.DebugWindow: if (m_debugwindow == null) { m_debugwindow = new DebugWindow(); } m_debugwindow.Show(); m_debugwindow.Activate(); break; case MenuCommand.About: var about_box = new AboutBox(); about_box.ShowDialog(); break; case MenuCommand.Download: var url = Settings.IsInstalled() ? Updater.Get("Installer") : Updater.Get("Portable"); System.Diagnostics.Process.Start(url); break; case MenuCommand.VisitWebsite: System.Diagnostics.Process.Start("http://wincompose.info/"); break; case MenuCommand.Disable: if (Composer.IsDisabled) { m_control.TriggerDisableEvent(); } Composer.ToggleDisabled(); SysTrayUpdateCallback(null, new EventArgs()); break; case MenuCommand.Restart: // FIXME: there might be more cleanup to do here; but it’s probably // not worth it, because restarting the app is a hack and whatever // reason the user may have, it’s because of a bug or a limitation // in WinCompose that we need to fix. m_icon.Visible = false; WinForms.Application.Restart(); Environment.Exit(0); break; case MenuCommand.Exit: WinForms.Application.Exit(); break; } }
private void OnMenuItemClicked(object parameter) { switch (parameter as MenuCommand?) { case MenuCommand.ShowSequences: m_sequencewindow = m_sequencewindow ?? new SequenceWindow(); m_sequencewindow.Show(); m_sequencewindow.Activate(); break; case MenuCommand.ShowOptions: m_optionswindow = m_optionswindow ?? new SettingsWindow(); m_optionswindow.Show(); m_optionswindow.Activate(); break; case MenuCommand.DebugWindow: m_debugwindow = m_debugwindow ?? new DebugWindow(); m_debugwindow.Show(); m_debugwindow.Activate(); break; case MenuCommand.About: m_about_box = m_about_box ?? new AboutBox(); m_about_box.Show(); m_about_box.Activate(); break; case MenuCommand.Download: var url = Settings.IsInstalled() ? Updater.Get("Installer") : Updater.Get("Portable"); System.Diagnostics.Process.Start(url); break; case MenuCommand.VisitWebsite: System.Diagnostics.Process.Start("http://wincompose.info/"); break; case MenuCommand.DonationPage: System.Diagnostics.Process.Start("http://wincompose.info/donate/"); break; case MenuCommand.Disable: if (Composer.IsDisabled) { Application.RemoteControl.BroadcastDisableEvent(); } Composer.ToggleDisabled(); break; case MenuCommand.Restart: // FIXME: there might be more cleanup to do here; but it’s probably // not worth it, because restarting the app is a hack and whatever // reason the user may have, it’s because of a bug or a limitation // in WinCompose that we need to fix. m_icon.Visible = false; Application.Current.Shutdown(); WinForms.Application.Restart(); Environment.Exit(0); break; case MenuCommand.Exit: Application.Current.Shutdown(); break; } }
private System.Drawing.Icon GetCurrentIcon() { return(GetIcon((Composer.IsDisabled() ? 0x1 : 0x0) | (Composer.IsComposing() ? 0x2 : 0x0) | (Updater.HasNewerVersion() ? 0x4 : 0x0))); }
static void Main() { // Do this before Composer.Init() because of the Disabled setting Settings.LoadConfig(); Composer.Init(); Settings.LoadSequences(); KeyboardHook.Init(); Updater.Init(); Settings.StartWatchConfigFile(); try { WinForms.Application.EnableVisualStyles(); WinForms.Application.SetCompatibleTextRenderingDefault(false); m_control = new RemoteControl(); m_control.DisableEvent += OnDisableEvent; m_control.DisableEvent += SysTrayUpdateCallback; m_control.ExitEvent += OnExitEvent; m_control.TriggerDisableEvent(); m_tray_icon = new WinForms.NotifyIcon { Visible = true, //Icon = GetCurrentIcon(), //Text = GetCurrentToolTip(), ContextMenu = new WinForms.ContextMenu(new[] { new TitleMenuItem(), new WinForms.MenuItem("-"), new WinForms.MenuItem(i18n.Text.ShowSequences, ShowSequencesClicked), new WinForms.MenuItem(i18n.Text.ShowOptions, ShowOptionsClicked), m_help_item = /* Keep a reference on this entry */ new WinForms.MenuItem(i18n.Text.Help, new[] { new WinForms.MenuItem(i18n.Text.About, AboutClicked), new WinForms.MenuItem(i18n.Text.VisitWebsite, delegate(object o, EventArgs e) { System.Diagnostics.Process.Start("http://wincompose.info/"); }), m_download_item = /* Keep a reference on this entry */ new WinForms.MenuItem("", DownloadClicked) { Visible = false }, }), new WinForms.MenuItem("-"), m_disable_item = /* Keep a reference on this entry */ new WinForms.MenuItem(i18n.Text.Disable, DisableClicked), new WinForms.MenuItem(i18n.Text.Restart, RestartClicked), new WinForms.MenuItem(i18n.Text.Exit, OnExitEvent), }) }; m_tray_icon.DoubleClick += NotifyiconDoubleclicked; Composer.Changed += SysTrayUpdateCallback; Updater.Changed += SysTrayUpdateCallback; SysTrayUpdateCallback(null, new EventArgs()); Updater.Changed += UpdaterStateChanged; UpdaterStateChanged(null, new EventArgs()); WinForms.Application.Run(); m_tray_icon.Dispose(); } finally { Composer.Changed -= SysTrayUpdateCallback; Updater.Changed -= SysTrayUpdateCallback; Updater.Changed -= UpdaterStateChanged; m_control.DisableEvent -= OnDisableEvent; m_control.ExitEvent -= OnExitEvent; Settings.StopWatchConfigFile(); Updater.Fini(); KeyboardHook.Fini(); Settings.SaveConfig(); Composer.Fini(); Updater.Fini(); } }
private void OnCommand(object o) { switch (o as MenuCommand?) { case MenuCommand.ShowSequences: m_sequencewindow = m_sequencewindow ?? new SequenceWindow(); m_sequencewindow.Show(); m_sequencewindow.Activate(); break; case MenuCommand.ShowOptions: m_optionswindow = m_optionswindow ?? new SettingsWindow(); m_optionswindow.Show(); m_optionswindow.Activate(); break; case MenuCommand.DebugWindow: m_debugwindow = m_debugwindow ?? new DebugWindow(); m_debugwindow.Show(); m_debugwindow.Activate(); break; case MenuCommand.About: m_about_box = m_about_box ?? new AboutBox(); m_about_box.Show(); m_about_box.Activate(); break; case MenuCommand.Download: var url = Utils.IsInstalled ? Updater.Get("Installer") : Updater.Get("Portable"); Process.Start(url); break; case MenuCommand.VisitWebsite: Process.Start("http://wincompose.info/"); break; case MenuCommand.DonationPage: Process.Start("http://wincompose.info/donate/"); break; case MenuCommand.Disable: if (Composer.IsDisabled) { Application.RemoteControl.BroadcastDisableEvent(); } Composer.ToggleDisabled(); break; case MenuCommand.Restart: // FIXME: there might be more cleanup to do here; but it’s probably // not worth it, because restarting the app is a hack and whatever // reason the user may have, it’s because of a bug or a limitation // in WinCompose that we need to fix. Visibility = Visibility.Collapsed; Application.Current.Exit += (s, e) => Process.Start(Application.ResourceAssembly.Location); Application.Current.Shutdown(); break; case MenuCommand.Exit: Application.Current.Shutdown(); break; } }