public override bool Initialize(IPluginHost host) { pluginHost = host; // purposely break the winforms tray icon so it is not displayed var mainWindowType = pluginHost.MainWindow.GetType(); var ntfTrayField = mainWindowType.GetField("m_ntfTray", BindingFlags.Instance | BindingFlags.NonPublic); var ntfField = ntfTrayField.FieldType.GetField("m_ntf", BindingFlags.Instance | BindingFlags.NonPublic); ntfField.SetValue(ntfTrayField.GetValue(pluginHost.MainWindow), null); var threadStarted = false; try { DBusBackgroundWorker.Request(); threadStarted = true; DBusBackgroundWorker.InvokeGtkThread((Action)GtkDBusInit).Wait(); } catch (Exception ex) { MessageService.ShowWarning( "KeebuntuStatusNotifier plugin failed to start.", ex.ToString()); if (threadStarted) { Terminate(); } return(false); } return(true); }
public override bool Initialize(IPluginHost host) { pluginHost = host; // mimmic behavior of other ubuntu apps hideMenuInApp = Environment.GetEnvironmentVariable("APPMENU_DISPLAY_BOTH") != "1"; bool threadStarted = false; try { DBusBackgroundWorker.Request(); threadStarted = true; DBusBackgroundWorker.InvokeGtkThread((Action)GtkDBusInit).Wait(); if (hideMenuInApp) { pluginHost.MainWindow.MainMenu.Visible = false; } pluginHost.MainWindow.Activated += MainWindow_Activated; GlobalWindowManager.WindowAdded += GlobalWindowManager_WindowAdded; GlobalWindowManager.WindowRemoved += GlobalWindowManager_WindowRemoved; } catch (Exception ex) { Debug.Fail(ex.ToString()); if (threadStarted) { Terminate(); } return(false); } return(true); }
/// <summary> /// Initalize Gtk and DBus stuff /// </summary> private void GtkDBusInit() { /* setup StatusIcon */ statusIcon = new Gtk.StatusIcon(); statusIcon.IconName = "keepass2-locked"; #if DEBUG statusIcon.File = Path.GetFullPath("Resources/icons/hicolor/16x16/apps/keepass2-locked.png"); #endif statusIcon.Tooltip = PwDefs.ProductName; statusIconMenu = new Gtk.Menu(); var trayContextMenu = pluginHost.MainWindow.TrayContextMenu; // make copy of item list to prevent list changed exception when iterating var menuItems = new System.Windows.Forms.ToolStripItem[trayContextMenu.Items.Count]; trayContextMenu.Items.CopyTo(menuItems, 0); trayContextMenu.ItemAdded += (sender, e) => DBusBackgroundWorker.InvokeGtkThread (() => ConvertAndAddMenuItem(e.Item, statusIconMenu)); foreach (System.Windows.Forms.ToolStripItem item in menuItems) { ConvertAndAddMenuItem(item, statusIconMenu); } statusIcon.PopupMenu += OnPopupMenu; statusIcon.Activate += (sender, e) => { DBusBackgroundWorker.InvokeWinformsThread (() => pluginHost.MainWindow.EnsureVisibleForegroundWindow(true, true)); }; }
public override bool Initialize(IPluginHost host) { pluginHost = host; updateUITimer = new System.Windows.Forms.Timer(); updateUITimer.Interval = 500; updateUITimer.Tick += On_updateUITimer_Tick; finishInitDelaytimer = new System.Windows.Forms.Timer(); var threadStarted = false; try { DBusBackgroundWorker.Request(); threadStarted = true; DBusBackgroundWorker.InvokeGtkThread((Action)GtkDBusInit).Wait(); pluginHost.MainWindow.UIStateUpdated += On_MainWindow_UIStateUpdated; } catch (Exception ex) { Debug.Fail(ex.ToString()); if (threadStarted) { Terminate(); } return(false); } return(true); }
/// <summary> /// Initalize Gtk stuff /// </summary> private void GtkDBusInit() { launcher = LauncherEntry.GetForDesktopId("keepass2.desktop"); var rootMenuItem = new Dbusmenu.Menuitem(); var trayContextMenu = pluginHost.MainWindow.TrayContextMenu; // make copy of item list to prevent list changed exception when iterating var menuItems = new System.Windows.Forms.ToolStripItem[trayContextMenu.Items.Count]; trayContextMenu.Items.CopyTo(menuItems, 0); trayContextMenu.ItemAdded += (sender, e) => DBusBackgroundWorker.InvokeGtkThread(() => ConvertAndAddMenuItem(e.Item, rootMenuItem)); foreach (System.Windows.Forms.ToolStripItem item in menuItems) { if (item.Name == "m_ctxTrayTray" || item.Name == "m_ctxTrayFileExit") { continue; } ConvertAndAddMenuItem(item, rootMenuItem); } // the launcher may not be listening yet, so we delay setting the properties // to give it extra time finishInitDelaytimer.Tick += (sender, e) => { finishInitDelaytimer.Stop(); DBusBackgroundWorker.InvokeGtkThread(() => launcher.Quicklist = rootMenuItem); }; finishInitDelaytimer.Interval = 1000; finishInitDelaytimer.Start(); }
void GlobalWindowManager_WindowAdded(object sender, GwmWindowEventArgs e) { var xid = (uint)GetWindowXid(e.Form); var objectPath = new ObjectPath(string.Format(menuPath, xid)); DBusBackgroundWorker.InvokeGtkThread(() => { Bus.Session.Register(objectPath, emptyDBusMenu); unityPanelServiceBus.RegisterWindow(xid, objectPath); }); }
void MainWindow_Activated(object sender, EventArgs e) { if (hideMenuInApp) { pluginHost.MainWindow.MainMenu.Visible = false; } // have to re-register the window each time the main windows is shown // otherwise we lose the application menu // TODO - sometimes we invoke this unnessasarily. If there is a way to // test that we are still registered, that would proably be better. // For now, it does not seem to hurt anything. DBusBackgroundWorker.InvokeGtkThread( () => unityPanelServiceBus.RegisterWindow((uint)mainFormXid.ToInt32(), mainFormObjectPath)); }
void GlobalWindowManager_WindowRemoved(object sender, GwmWindowEventArgs e) { var xid = (uint)GetWindowXid(e.Form); var objectPath = new ObjectPath(string.Format(menuPath, xid)); DBusBackgroundWorker.InvokeGtkThread(() => { unityPanelServiceBus.UnregisterWindow(xid); Bus.Session.Unregister(objectPath); }); if (GlobalWindowManager.WindowCount <= 1) { DBusBackgroundWorker.InvokeGtkThread( () => unityPanelServiceBus.RegisterWindow((uint)mainFormXid.ToInt32(), mainFormObjectPath)); } }
void ShowErrorMessage() { DBusBackgroundWorker.Request(); DBusBackgroundWorker.InvokeGtkThread(() => { using (var dialog = new Gtk.Dialog()) { dialog.BorderWidth = 6; dialog.Resizable = false; dialog.HasSeparator = false; var message = "<span weight=\"bold\"size=\"larger\">" + "Could not register KeebuntuAppMenu with Unity panel service." + "</span>\n\n" + "This plugin only works with Ubuntu Unity desktop." + " If you do not use Unity, you should uninstall the KeebuntuAppMenu plugin." + "\n"; var label = new Gtk.Label(message); label.UseMarkup = true; label.Wrap = true; label.Yalign = 0; var icon = new Gtk.Image(Gtk.Stock.DialogError, Gtk.IconSize.Dialog); icon.Yalign = 0; var contentBox = new Gtk.HBox(); contentBox.Spacing = 12; contentBox.BorderWidth = 6; contentBox.PackStart(icon); contentBox.PackEnd(label); dialog.VBox.PackStart(contentBox); dialog.AddButton("Don't show this again", Gtk.ResponseType.Accept); dialog.AddButton("OK", Gtk.ResponseType.Ok); dialog.DefaultResponse = Gtk.ResponseType.Ok; dialog.Response += (o, args) => { dialog.Destroy(); if (args.ResponseId == Gtk.ResponseType.Accept) { pluginHost.CustomConfig.SetBool(keebuntuAppMenuWarningSeenId, true); } }; dialog.ShowAll(); dialog.KeepAbove = true; dialog.Run(); } }).Wait(); DBusBackgroundWorker.Release(); }
private void ConvertAndAddMenuItem(System.Windows.Forms.ToolStripItem item, Dbusmenu.Menuitem parent) { if (item is System.Windows.Forms.ToolStripMenuItem) { var winformMenuItem = item as System.Windows.Forms.ToolStripMenuItem; var dbusMenuItem = new Dbusmenu.Menuitem(); dbusMenuItem.PropertySet("label", winformMenuItem.Text.Replace("&", "")); // VisibleChanged does not seem to be firing, so make everything visible for now //dbusMenuItem.PropertySetBool("visible", winformMenuItem.Visible); dbusMenuItem.PropertySetBool("enabled", winformMenuItem.Enabled); dbusMenuItem.ItemActivated += (sender, e) => DBusBackgroundWorker.InvokeWinformsThread((Action)winformMenuItem.PerformClick); winformMenuItem.TextChanged += (sender, e) => DBusBackgroundWorker.InvokeGtkThread(() => dbusMenuItem.PropertySet("label", winformMenuItem.Text.Replace("&", ""))); winformMenuItem.EnabledChanged += (sender, e) => DBusBackgroundWorker.InvokeGtkThread(() => dbusMenuItem.PropertySetBool("enabled", winformMenuItem.Enabled)); winformMenuItem.VisibleChanged += (sender, e) => DBusBackgroundWorker.InvokeGtkThread(() => dbusMenuItem.PropertySetBool("visible", winformMenuItem.Visible)); parent.ChildAppend(dbusMenuItem); } else if (item is System.Windows.Forms.ToolStripSeparator) { // Ignore separator for now because there are too many of them // var dbusMenuItem = new DbusmenuMenuitem(); // dbusMenuItem.PropertySet("type", "separator"); // parent.ChildAppend(dbusMenuItem); } else { Debug.Fail("Unexpected menu item"); } }
public override bool Initialize(IPluginHost host) { pluginHost = host; // purposely break the winforms tray icon so it is not displayed var mainWindowType = pluginHost.MainWindow.GetType(); var ntfTrayField = mainWindowType.GetField("m_ntfTray", BindingFlags.Instance | BindingFlags.NonPublic); var ntfField = ntfTrayField.FieldType.GetField("m_ntf", BindingFlags.Instance | BindingFlags.NonPublic); ntfField.SetValue(ntfTrayField.GetValue(pluginHost.MainWindow), null); activateWorkaroundTimer = new System.Windows.Forms.Timer(); activateWorkaroundTimer.Interval = 100; activateWorkaroundTimer.Tick += OnActivateWorkaroundTimerTick; var threadStarted = false; try { DBusBackgroundWorker.Request(); threadStarted = true; DBusBackgroundWorker.InvokeGtkThread((Action)GtkDBusInit).Wait(); pluginHost.MainWindow.Activated += MainWindow_Activated; pluginHost.MainWindow.Resize += MainWindow_Resize; } catch (Exception ex) { MessageService.ShowWarning( "KeebuntuAppIndicator plugin failed to start.", ex.ToString()); if (threadStarted) { Terminate(); } return(false); } return(true); }
public override bool Initialize(IPluginHost host) { pluginHost = host; // mimmic behavior of other ubuntu apps hideMenuInApp = Environment.GetEnvironmentVariable("APPMENU_DISPLAY_BOTH") != "1"; try { DBusBackgroundWorker.Start(); gtkInitDoneEvent = new AutoResetEvent(false); DBusBackgroundWorker.InvokeGtkThread(() => GtkDBusInit()); if (!gtkInitDoneEvent.WaitOne(1000)) { throw new TimeoutException("Timed out waiting for GTK thread."); } if (!gtkInitOk) { throw new Exception("GTK init failed."); } if (hideMenuInApp) { pluginHost.MainWindow.MainMenu.Visible = false; } pluginHost.MainWindow.Activated += MainWindow_Activated; GlobalWindowManager.WindowAdded += GlobalWindowManager_WindowAdded; GlobalWindowManager.WindowRemoved += GlobalWindowManager_WindowRemoved; } catch (Exception ex) { Debug.Fail(ex.ToString()); if (gtkInitOk) { Terminate(); } return(false); } return(true); }
private void ConvertAndAddMenuItem(System.Windows.Forms.ToolStripItem item, Gtk.MenuShell gtkMenuShell) { if (item is System.Windows.Forms.ToolStripMenuItem) { var winformMenuItem = item as System.Windows.Forms.ToolStripMenuItem; // windows forms use '&' for mneumonic, gtk uses '_' var gtkMenuItem = new Gtk.ImageMenuItem(winformMenuItem.Text.Replace("&", "_")); if (winformMenuItem.Image != null) { MemoryStream memStream; var image = winformMenuItem.Image; if (image.Width != 16 || image.Height != 16) { var newImage = ResizeImage(image, 16, 16); memStream = new MemoryStream(newImage); } else { memStream = new MemoryStream(); image.Save(memStream, ImageFormat.Png); memStream.Position = 0; } gtkMenuItem.Image = new Gtk.Image(memStream); } gtkMenuItem.TooltipText = winformMenuItem.ToolTipText; gtkMenuItem.Visible = winformMenuItem.Visible; gtkMenuItem.Sensitive = winformMenuItem.Enabled; gtkMenuItem.Activated += (sender, e) => DBusBackgroundWorker.InvokeWinformsThread((Action)winformMenuItem.PerformClick); winformMenuItem.TextChanged += (sender, e) => DBusBackgroundWorker.InvokeGtkThread(() => { var label = gtkMenuItem.Child as Gtk.Label; if (label != null) { label.Text = winformMenuItem.Text; } } ); winformMenuItem.EnabledChanged += (sender, e) => DBusBackgroundWorker.InvokeGtkThread (() => gtkMenuItem.Sensitive = winformMenuItem.Enabled); winformMenuItem.VisibleChanged += (sender, e) => DBusBackgroundWorker.InvokeGtkThread (() => gtkMenuItem.Visible = winformMenuItem.Visible); gtkMenuItem.Show(); gtkMenuShell.Insert(gtkMenuItem, winformMenuItem.Owner.Items.IndexOf(winformMenuItem)); if (winformMenuItem.HasDropDownItems) { var subMenu = new Gtk.Menu(); foreach (System.Windows.Forms.ToolStripItem dropDownItem in winformMenuItem.DropDownItems) { ConvertAndAddMenuItem(dropDownItem, subMenu); } gtkMenuItem.Submenu = subMenu; winformMenuItem.DropDown.ItemAdded += (sender, e) => DBusBackgroundWorker.InvokeGtkThread (() => ConvertAndAddMenuItem(e.Item, subMenu)); } } else if (item is System.Windows.Forms.ToolStripSeparator) { var gtkSeparator = new Gtk.SeparatorMenuItem(); gtkSeparator.Show(); gtkMenuShell.Insert(gtkSeparator, item.Owner.Items.IndexOf(item)); } else { Debug.Fail("Unexpected menu item"); } }
/// <summary> /// Initalize Gtk and DBus stuff /// </summary> private void GtkDBusInit() { /* setup ApplicationIndicator */ indicator = new ApplicationIndicator("keepass2-plugin-appindicator" + instanceCount++, "keepass2-locked", AppIndicator.Category.ApplicationStatus); #if DEBUG indicator.IconThemePath = Path.GetFullPath("Resources/icons"); #endif indicator.Title = PwDefs.ProductName; indicator.Status = AppIndicator.Status.Active; appIndicatorMenu = new Gtk.Menu(); var trayContextMenu = pluginHost.MainWindow.TrayContextMenu; // make copy of item list to prevent list changed exception when iterating var menuItems = new System.Windows.Forms.ToolStripItem[trayContextMenu.Items.Count]; trayContextMenu.Items.CopyTo(menuItems, 0); trayContextMenu.ItemAdded += (sender, e) => DBusBackgroundWorker.InvokeGtkThread (() => ConvertAndAddMenuItem(e.Item, appIndicatorMenu)); foreach (System.Windows.Forms.ToolStripItem item in menuItems) { ConvertAndAddMenuItem(item, appIndicatorMenu); } indicator.Menu = appIndicatorMenu; try { // This is a hack to get the about-to-show event from the dbusmenu // that is created by the appindicator. var getPropertyMethod = typeof(GLib.Object).GetMethod("GetProperty", BindingFlags.NonPublic | BindingFlags.Instance); var dbusMenuServer = (GLib.Value)getPropertyMethod.Invoke(indicator, new object[] { "dbus-menu-server" }); var rootNode = (GLib.Value)getPropertyMethod.Invoke(dbusMenuServer.Val, new object[] { "root-node" }); aboutToShowSignal = GLib.Signal.Lookup((GLib.Object)rootNode.Val, "about-to-show"); aboutToShowSignal.AddDelegate((EventHandler)OnAppIndicatorMenuShown); } catch (Exception ex) { Debug.Fail(ex.Message); // On desktops that don't support application indicators, libappinidicator // creates a fallback GtkStatusIcon. This event only fires in that case. appIndicatorMenu.Shown += OnAppIndicatorMenuShown; } // when mouse cursor is over application indicator, scroll up will untray // and scroll down will tray KeePass indicator.ScrollEvent += (o, args) => { /* Workaround for bug in mono/appindicator-sharp. * * args.Direction throws InvalidCastException * Can't cast args.Arg[1] to Gdk.ScrollDirection for some reason, so we * have to cast to uint first (that is the underlying data type) and * then cast to Gdk.ScrollDirection */ var scrollDirectionUint = (uint)args.Args[1]; var scrollDirection = (Gdk.ScrollDirection)scrollDirectionUint; var trayMenuItem = trayContextMenu.Items["m_ctxTrayTray"]; if (trayMenuItem.Enabled && (scrollDirection == Gdk.ScrollDirection.Up ^ pluginHost.MainWindow.Visible)) { DBusBackgroundWorker.InvokeWinformsThread (() => trayMenuItem.PerformClick()); } }; }