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);
        }
예제 #2
0
        void OnPopupMenu(object sender, Gtk.PopupMenuArgs e)
        {
            try {
                var mainWindowType = pluginHost.MainWindow.GetType();
                var cxtTrayField   = mainWindowType.GetField("m_ctxTray",
                                                             BindingFlags.Instance | BindingFlags.NonPublic);
                var ctxTray = cxtTrayField.GetValue(pluginHost.MainWindow);

                // Synthesize menu open events. These are expected by KeePass and
                // other plugins

                var onOpening = ctxTray.GetType().GetMethod("OnOpening",
                                                            BindingFlags.Instance | BindingFlags.NonPublic);
                DBusBackgroundWorker.InvokeWinformsThread(() =>
                                                          onOpening.Invoke(ctxTray, new[] { new CancelEventArgs() }));

                statusIconMenu.Popup(null, null, null, (uint)e.Args[0], (uint)e.Args[1]);

                var onOpened = ctxTray.GetType().GetMethod("OnOpened",
                                                           BindingFlags.Instance | BindingFlags.NonPublic);
                DBusBackgroundWorker.InvokeWinformsThread(() =>
                                                          onOpened.Invoke(ctxTray, new[] { new CancelEventArgs() }));
            } catch (Exception ex) {
                Debug.Fail(ex.ToString());
            }
        }
예제 #3
0
        /// <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();
        }
예제 #4
0
        void On_updateUITimer_Tick(object sender, System.EventArgs e)
        {
            try {
                var mainWindowType = pluginHost.MainWindow.GetType();
                var cxtTrayField   = mainWindowType.GetField("m_ctxTray",
                                                             BindingFlags.Instance | BindingFlags.NonPublic);
                var ctxTray = cxtTrayField.GetValue(pluginHost.MainWindow);

                // Synthesize menu open events. These are expected by KeePass and
                // other plugins

                var onOpening = ctxTray.GetType().GetMethod("OnOpening",
                                                            BindingFlags.Instance | BindingFlags.NonPublic);
                DBusBackgroundWorker.InvokeWinformsThread(() =>
                                                          onOpening.Invoke(ctxTray, new[] { new CancelEventArgs() }));

                var onOpened = ctxTray.GetType().GetMethod("OnOpened",
                                                           BindingFlags.Instance | BindingFlags.NonPublic);
                DBusBackgroundWorker.InvokeWinformsThread(() =>
                                                          onOpened.Invoke(ctxTray, new[] { new CancelEventArgs() }));
            } catch (Exception ex) {
                Debug.Fail(ex.ToString());
            } finally {
                updateUITimer.Stop();
            }
        }
예제 #5
0
 private void OnAppIndicatorMenuShown(object sender, EventArgs e)
 {
     try {
         var mainWindowType             = pluginHost.MainWindow.GetType();
         var onCtxTrayOpeningMethodInfo =
             mainWindowType.GetMethod("OnCtxTrayOpening",
                                      System.Reflection.BindingFlags.Instance |
                                      System.Reflection.BindingFlags.NonPublic,
                                      null,
                                      new[] {
             typeof(object),
             typeof(CancelEventArgs)
         },
                                      null);
         if (onCtxTrayOpeningMethodInfo != null)
         {
             DBusBackgroundWorker.InvokeWinformsThread
                 (() => onCtxTrayOpeningMethodInfo.Invoke(pluginHost.MainWindow,
                                                          new[] {
                 sender,
                 new CancelEventArgs()
             }
                                                          )
                 );
         }
     } catch (Exception ex) {
         Debug.Fail(ex.ToString());
     }
 }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        /// <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 void Terminate()
 {
     try {
         DBusBackgroundWorker.Release();
     } catch (Exception ex) {
         Debug.Fail(ex.ToString());
     }
 }
예제 #10
0
 public override void Terminate()
 {
     pluginHost.MainWindow.UIStateUpdated -= On_MainWindow_UIStateUpdated;
     try {
         DBusBackgroundWorker.Release();
     } catch (Exception ex) {
         Debug.Fail(ex.ToString());
     }
 }
예제 #11
0
        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);
            });
        }
예제 #12
0
 public override void Terminate()
 {
     pluginHost.MainWindow.Activated += MainWindow_Activated;
     pluginHost.MainWindow.Resize    -= MainWindow_Resize;
     statusIcon.PopupMenu            -= OnPopupMenu;
     try {
         DBusBackgroundWorker.Release();
     } catch (Exception ex) {
         Debug.Fail(ex.ToString());
     }
 }
예제 #13
0
        private void OnActivateWorkaroundTimerTick(object sender, EventArgs e)
        {
            // There seems to be a bug? in Mono where if you change Visible from
            // false to true and WindowState from Minimized to !Minimized and then call
            // Activate() all in the same method call, then the icon in the launcher
            // is resored, but the window is not shown. To work around this, we use a
            // timer to invoke Activate() a second time to get the window to show.

            activateWorkaroundTimer.Stop();
            DBusBackgroundWorker.InvokeWinformsThread
                ((Action)pluginHost.MainWindow.Activate);
        }
예제 #14
0
 public override void Terminate()
 {
     pluginHost.MainWindow.Activated += MainWindow_Activated;
     pluginHost.MainWindow.Resize    -= MainWindow_Resize;
     aboutToShowSignal.RemoveDelegate((EventHandler)OnAppIndicatorMenuShown);
     appIndicatorMenu.Shown -= OnAppIndicatorMenuShown;
     try {
         DBusBackgroundWorker.Stop();
     } catch (Exception ex) {
         Debug.Fail(ex.ToString());
     }
 }
예제 #15
0
 public void Activate(int x, int y)
 {
     DBusBackgroundWorker.InvokeWinformsThread(() => {
         if (pluginHost.MainWindow.Visible)
         {
             pluginHost.MainWindow.Hide();
         }
         else
         {
             pluginHost.MainWindow.EnsureVisibleForegroundWindow(true, true);
         }
     });
 }
예제 #16
0
 public override void Terminate()
 {
     try {
         pluginHost.MainWindow.Activated   -= MainWindow_Activated;
         GlobalWindowManager.WindowAdded   -= GlobalWindowManager_WindowAdded;
         GlobalWindowManager.WindowRemoved -= GlobalWindowManager_WindowRemoved;
         DBusBackgroundWorker.InvokeWinformsThread(() => {
             pluginHost.MainWindow.MainMenu.Visible = true;
         });
         DBusBackgroundWorker.Release();
     } catch (Exception ex) {
         Debug.Fail(ex.ToString());
     }
 }
예제 #17
0
 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));
 }
예제 #18
0
        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));
            }
        }
예제 #19
0
 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();
 }
        /// <summary>
        /// Initalize Gtk and DBus stuff
        /// </summary>
        private void GtkDBusInit()
        {
            /* setup StatusNotifierItem */

            const string sniWatcherServiceName   = "org.kde.StatusNotifierWatcher";
            const string sniWatcherPath          = "/StatusNotifierWatcher";
            const string applicationPathTemplate = "/org/keepass/KeePass{0}";

            var watcher = Bus.Session.GetObject <IStatusNotifierWatcher>(
                sniWatcherServiceName, new ObjectPath(sniWatcherPath));

#if DEBUG
            watcher.StatusNotifierItemRegistered += (obj) =>
                                                    Console.WriteLine(obj);
#endif

            var mainWindowType = pluginHost.MainWindow.GetType();
            var cxtTrayField   = mainWindowType.GetField("m_ctxTray",
                                                         BindingFlags.Instance | BindingFlags.NonPublic);
            var ctxTray   = cxtTrayField.GetValue(pluginHost.MainWindow);
            var onOpening = ctxTray.GetType().GetMethod("OnOpening",
                                                        BindingFlags.Instance | BindingFlags.NonPublic);
            var onOpened = ctxTray.GetType().GetMethod("OnOpened",
                                                       BindingFlags.Instance | BindingFlags.NonPublic);

            var applicationPath = new ObjectPath(string.Format(applicationPathTemplate,
                                                               pluginHost.MainWindow.Handle));
            statusNotifier = new KeePassStatusNotifierItem(pluginHost, applicationPath);

            // Synthesize menu open events. These are expected by KeePass and
            // other plugins
            statusNotifier.Showing += (sender, e) => {
                DBusBackgroundWorker.InvokeWinformsThread(() =>
                                                          onOpening.Invoke(ctxTray, new[] { new CancelEventArgs() }));
            };
            statusNotifier.Shown += (sender, e) => {
                DBusBackgroundWorker.InvokeWinformsThread(() =>
                                                          onOpened.Invoke(ctxTray, new[] { new CancelEventArgs() }));
            };

            Bus.Session.Register(applicationPath, statusNotifier);
            watcher.RegisterStatusNotifierItem(applicationPath.ToString());
        }
예제 #21
0
        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");
            }
        }
예제 #22
0
        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);
        }
예제 #23
0
        void GtkDBusInit()
        {
            /* setup ApplicationMenu */

            dbusMenu      = new MenuStripDBusMenu(pluginHost.MainWindow.MainMenu);
            emptyDBusMenu = new MenuStripDBusMenu(new MenuStrip());

            var sessionBus = Bus.Session;

#if DEBUG
            const string dbusBusPath    = "/org/freedesktop/DBus";
            const string dbusBusName    = "org.freedesktop.DBus";
            var          dbusObjectPath = new ObjectPath(dbusBusPath);
            var          dbusService    =
                sessionBus.GetObject <org.freedesktop.DBus.IBus>(dbusBusName, dbusObjectPath);
            dbusService.NameAcquired += (name) => Console.WriteLine("NameAcquired: " + name);
#endif
            const string registrarBusPath    = "/com/canonical/AppMenu/Registrar";
            const string registratBusName    = "com.canonical.AppMenu.Registrar";
            var          registrarObjectPath = new ObjectPath(registrarBusPath);
            unityPanelServiceBus =
                sessionBus.GetObject <com.canonical.AppMenu.Registrar.IRegistrar>(registratBusName,
                                                                                  registrarObjectPath);
            mainFormXid        = GetWindowXid(pluginHost.MainWindow);
            mainFormObjectPath = new ObjectPath(string.Format(menuPath,
                                                              mainFormXid));
            sessionBus.Register(mainFormObjectPath, dbusMenu);
            try {
                unityPanelServiceBus.RegisterWindow((uint)mainFormXid.ToInt32(),
                                                    mainFormObjectPath);
            } catch (Exception) {
                if (!pluginHost.CustomConfig.GetBool(keebuntuAppMenuWarningSeenId, false))
                {
                    Task.Run((Action)ShowErrorMessage);
                }
                DBusBackgroundWorker.InvokeWinformsThread(() => Terminate());
            }
        }
예제 #24
0
        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);
        }
예제 #25
0
        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");
            }
        }
예제 #26
0
        /// <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());
                }
            };
        }
예제 #27
0
        void GtkDBusInit()
        {
            /* setup ApplicationMenu */

            dbusMenu      = new MenuStripDBusMenu(pluginHost.MainWindow.MainMenu);
            emptyDBusMenu = new MenuStripDBusMenu(new MenuStrip());

            var sessionBus = Bus.Session;

#if DEBUG
            const string dbusBusPath    = "/org/freedesktop/DBus";
            const string dbusBusName    = "org.freedesktop.DBus";
            var          dbusObjectPath = new ObjectPath(dbusBusPath);
            var          dbusService    =
                sessionBus.GetObject <org.freedesktop.DBus.IBus>(dbusBusName, dbusObjectPath);
            dbusService.NameAcquired += (name) => Console.WriteLine("NameAcquired: " + name);
#endif
            const string registrarBusPath    = "/com/canonical/AppMenu/Registrar";
            const string registratBusName    = "com.canonical.AppMenu.Registrar";
            var          registrarObjectPath = new ObjectPath(registrarBusPath);
            unityPanelServiceBus =
                sessionBus.GetObject <com.canonical.AppMenu.Registrar.IRegistrar>(registratBusName,
                                                                                  registrarObjectPath);
            mainFormXid        = GetWindowXid(pluginHost.MainWindow);
            mainFormObjectPath = new ObjectPath(string.Format(menuPath,
                                                              mainFormXid));
            sessionBus.Register(mainFormObjectPath, dbusMenu);
            try {
                unityPanelServiceBus.RegisterWindow((uint)mainFormXid.ToInt32(),
                                                    mainFormObjectPath);
                gtkInitOk = true;
                gtkInitDoneEvent.Set();
            } catch (Exception) {
                gtkInitDoneEvent.Set();
                if (!pluginHost.CustomConfig.GetBool(keebuntuAppMenuWarningSeenId, false))
                {
                    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();
                    }
                    DBusBackgroundWorker.Stop();
                }
            }
        }