[Pkg-mozext-commits] [firetray] 29/399: add popup menu to tray icon (work in progress)

David Prévot taffit at alioth.debian.org
Tue Oct 29 18:23:08 UTC 2013


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch dfsg-clean
in repository firetray.

commit b3835a7c8bee5ef5b704919f0e73bd4a2b2898e7
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Mon Aug 29 02:40:14 2011 +0200

    add popup menu to tray icon (work in progress)
---
 README.md                        |    2 +-
 TODO                             |    6 ++-
 src/modules/LibGObject.jsm       |    4 ++
 src/modules/LibGtkStatusIcon.jsm |  108 +++++++++++++++++++++++++++++---------
 src/modules/MoztHandler.jsm      |   70 ++++++++++++++++++++----
 5 files changed, 151 insertions(+), 39 deletions(-)

diff --git a/README.md b/README.md
index dfffa09..85b965a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Moztray
 Overview
 --------
 
-Rewrite attempt of **Firetray** with js-ctypes, with focus on message count display.
+Rewrite attempt of **Firetray** with js-ctypes, with focus on unread message count display.
 
 Notes
 -----
diff --git a/TODO b/TODO
index fdec45b..9adb41b 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,7 @@
-* add 'quit' to icon menu + add option UI for close_all_tabs
-
 * make multi-platform. At least have js-ctypes library call dependant on OS detection. (best would be to have the OS-dependant modules loaded at startup) 
 
 * convert to a https://developer.mozilla.org/en/Extensions/Bootstrapped_extensions
+
+WONTFIX:
+
+* ability to hide windows individually/globally
diff --git a/src/modules/LibGObject.jsm b/src/modules/LibGObject.jsm
index 6c93f86..106cf3a 100644
--- a/src/modules/LibGObject.jsm
+++ b/src/modules/LibGObject.jsm
@@ -87,6 +87,10 @@ XPCOMUtils.defineLazyGetter(this, "gboolean", function() {
   return gint;
 });
 
+XPCOMUtils.defineLazyGetter(this, "gfloat", function() {
+  return ctypes.float;
+});
+
 XPCOMUtils.defineLazyGetter(this, "GConnectFlags", function() {
   return guint;
 });
diff --git a/src/modules/LibGtkStatusIcon.jsm b/src/modules/LibGtkStatusIcon.jsm
index 1941c1d..85881da 100644
--- a/src/modules/LibGtkStatusIcon.jsm
+++ b/src/modules/LibGtkStatusIcon.jsm
@@ -48,12 +48,10 @@ var LibGtkStatusIcon = {
 
   _declare: function() {
     // Types
+
     this.GtkStatusIcon = ctypes.StructType("GtkStatusIcon");
-    this.GtkStatusIconRef = ctypes.PointerType(this.GtkStatusIcon);
 
-    this.GtkWindow = ctypes.StructType(
-      "GtkWindow", [
-      ]);
+    // this.GtkWindow = ctypes.StructType("GtkWindow", []); // not implemented yet
 
     this.GtkStyle = ctypes.StructType("GtkStyle");
     this.GtkRequisition = ctypes.StructType(
@@ -68,6 +66,7 @@ var LibGtkStatusIcon = {
         { width: LibGObject.gint },
         { height: LibGObject.gint }
       ]);
+
     /* NOTE: recursive struct needs define() and included structs MUST be
      * defined ! */
     this.GtkWidget = ctypes.StructType("GtkWidget");
@@ -79,49 +78,106 @@ var LibGtkStatusIcon = {
         { "parent": this.GtkWidget.ptr }
       ]);
 
+    this.GtkAccelGroup = ctypes.StructType(
+      "GtkAccelGroup", [
+        { "isLocked": LibGObject.gboolean },
+        { "modifierMask": ctypes.int } // GdkModifierType = enum
+      ]);
+    this.GtkArrowPlacement = ctypes.int; // enum
+
+    this.GtkMenu = ctypes.StructType("GtkMenu");
+    this.GtkMenu.define(
+      [{ "accelGroup": this.GtkAccelGroup.ptr },
+       { "accelPath": LibGObject.gchar.ptr },
+       { "active": LibGObject.gint },
+       { "attachWidget": this.GtkWidget.ptr },
+       { "monitor": LibGObject.gint },
+       { "reserveToggleSize": LibGObject.gboolean },
+       { "tearoffState": LibGObject.gboolean },
+       { "tearoffTitle": LibGObject.gchar.ptr },
+       { "bottomAttach": LibGObject.gint },
+       { "leftAttach": LibGObject.gint },
+       { "rightAttach": LibGObject.gint },
+       { "topAttach": LibGObject.gint },
+       { "arrowPlacement": this.GtkArrowPlacement },
+       { "arrowScaling": ctypes.float }, // LibGObject.gfloat doesn't work ??
+       { "doubleArrows": LibGObject.gboolean },
+       { "horizontalOffset": LibGObject.gint },
+       { "horizontalPadding": LibGObject.gint },
+       { "verticalOffset": LibGObject.gint },
+       { "verticalPadding": LibGObject.gint }
+      ]);
+
+    this.GtkMenuShell = ctypes.StructType("GtkMenuShell");
+    // use ctypes.cast(menu, LibGtkStatusIcon.GtkMenuShell.ptr);
+
+    this.GtkMenuPositionFunc = ctypes.FunctionType(
+      ctypes.default_abi, ctypes.void_t,
+      [this.GtkMenu.ptr, LibGObject.gint.ptr, LibGObject.gint.ptr,
+       LibGObject.gboolean.ptr, LibGObject.gpointer]).ptr;
+
+    this.GCallbackMenuPopup_t = ctypes.FunctionType(
+      ctypes.default_abi, ctypes.void_t,
+      [this.GtkStatusIcon.ptr, LibGObject.guint, LibGObject.guint,
+       LibGObject.gpointer]).ptr;
+
     // Consts
     // this.INDICATOR_MESSAGES_SERVER_TYPE = "message";
 
     // Functions
 
     this.gtk_status_icon_new = this._lib.declare(
-      "gtk_status_icon_new",
-      ctypes.default_abi,
-      this.GtkStatusIconRef
-    );
+      "gtk_status_icon_new", ctypes.default_abi, this.GtkStatusIcon.ptr);
 
     this.gtk_status_icon_set_from_file = this._lib.declare(
-      "gtk_status_icon_set_from_file",
-      ctypes.default_abi,
-      ctypes.void_t,
-      this.GtkStatusIconRef,
-      ctypes.char.ptr
-    );
+      "gtk_status_icon_set_from_file", ctypes.default_abi, ctypes.void_t,
+      this.GtkStatusIcon.ptr, ctypes.char.ptr);
 
     this.gtk_status_icon_set_tooltip_text = this._lib.declare(
-      "gtk_status_icon_set_tooltip_text",
-      ctypes.default_abi,
-      ctypes.void_t,
-      this.GtkStatusIconRef,
-      ctypes.char.ptr
-    );
+      "gtk_status_icon_set_tooltip_text", ctypes.default_abi, ctypes.void_t,
+      this.GtkStatusIcon.ptr, ctypes.char.ptr);
 
 /*
     this.gtk_window_list_toplevels = this._lib.declare(
-      "gtk_window_list_toplevels", ctypes.default_abi, LibGObject.GList.ptr
-    );
+      "gtk_window_list_toplevels", ctypes.default_abi, LibGObject.GList.ptr);
 
     this.gtk_widget_show = this._lib.declare(
       "gtk_widget_show", ctypes.default_abi, ctypes.void_t,
-      this.GtkWidget.ptr
-    );
+      this.GtkWidget.ptr);
 
     this.gtk_widget_hide = this._lib.declare(
       "gtk_widget_hide", ctypes.default_abi, ctypes.void_t,
-      this.GtkWidget.ptr
-    );
+      this.GtkWidget.ptr);
 */
 
+    this.gtk_menu_new = this._lib.declare(
+      "gtk_menu_new", ctypes.default_abi, this.GtkMenu.ptr);
+
+    this.gtk_image_menu_item_new_with_label = this._lib.declare(
+      "gtk_image_menu_item_new_with_label", ctypes.default_abi, this.GtkWidget.ptr,
+      LibGObject.gchar.ptr);
+
+    this.gtk_menu_shell_append = this._lib.declare(
+      "gtk_menu_shell_append", ctypes.default_abi, ctypes.void_t,
+      this.GtkMenuShell.ptr, this.GtkWidget.ptr);
+
+    this.gtk_widget_show_all = this._lib.declare(
+      "gtk_widget_show_all", ctypes.default_abi, ctypes.void_t,
+      this.GtkWidget.ptr);
+
+// static void trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popUpMenu)
+//     gtk_menu_popup(GTK_MENU(popUpMenu), NULL, NULL, gtk_status_icon_position_menu, status_icon, button, activate_time);
+    this.gtk_menu_popup = this._lib.declare(
+      "gtk_menu_popup", ctypes.default_abi, ctypes.void_t,
+      this.GtkMenu.ptr, this.GtkWidget.ptr, this.GtkWidget.ptr,
+      this.GtkMenuPositionFunc, LibGObject.gpointer, LibGObject.guint,
+      LibGObject.guint);
+
+    this.gtk_status_icon_position_menu = this._lib.declare(
+      "gtk_status_icon_position_menu", ctypes.default_abi, ctypes.void_t,
+      this.GtkMenu.ptr, LibGObject.gint.ptr, LibGObject.gint.ptr,
+      LibGObject.gboolean.ptr, LibGObject.gpointer);
+
   }
 
 };
diff --git a/src/modules/MoztHandler.jsm b/src/modules/MoztHandler.jsm
index 9791e6f..046fd82 100644
--- a/src/modules/MoztHandler.jsm
+++ b/src/modules/MoztHandler.jsm
@@ -23,9 +23,11 @@ if ("undefined" == typeof(mozt)) {
   var mozt = {};
 };
 
-var mozt_activateCb;            // pointer to JS function. should not be eaten
-                                // by GC ("Running global cleanup code from
-                                // study base classes" ?)
+// pointer to JS functions. should not be eaten by GC ("Running global cleanup
+// code from study base classes" ?)
+var mozt_activateCb;
+var mozt_popupMenuCb;
+
 /**
  * Singleton object for tray icon management
  */
@@ -56,7 +58,7 @@ mozt.Handler = {
     if (winType == "BaseWindow")
       winOut = winInterface.getInterface(Ci.nsIBaseWindow);
     else if (winType == "XUL")
-      winOut = winInterface.getInterface(Ci.nsIXULWindow);
+    winOut = winInterface.getInterface(Ci.nsIXULWindow);
     else {
       Components.utils.reportError("MOZTRAY: unknown winType '" + winType + "'");
       return null;
@@ -141,13 +143,32 @@ mozt.Handler = {
       this._windowsHidden = true;
     }
 
+  }, // showHideToTray
+
+  popupMenu: function(icon, button, activateTime, menu) {
+    // GtkStatusIcon *status_icon, guint button, guint activate_time,  gpointer  user_data
+    mozt.Debug.debug("MENU POPUP");
+    mozt.Debug.debug("ARGS="+icon+", "+button+", "+activateTime+", "+menu);
+
+    try {
+      LibGtkStatusIcon.init(); // before anything !!!
+      var gtkMenuPtr = ctypes.cast(menu, LibGtkStatusIcon.GtkMenu.ptr);
+      var iconGpointer = ctypes.cast(icon, LibGObject.gpointer);
+      LibGtkStatusIcon.gtk_menu_popup(
+        gtkMenuPtr, null, null, LibGtkStatusIcon.gtk_status_icon_position_menu,
+        iconGpointer, button, activateTime);
+      LibGtkStatusIcon.shutdown();
+    } catch (x) {
+      mozt.Debug.debug(x);
+    }
   },
 
   init: function() {            // creates icon
 
     // platform checks
     let runtimeOS = Services.appinfo.OS; // "WINNT", "Linux", "Darwin"
-    let xulVer = Services.appinfo.platformVersion; // Services.vc.compare(xulVer,"2.0a")>=0 will be checked ing install, so we shouldn't need to care
+    // version checked during install, so we shouldn't need to care
+    let xulVer = Services.appinfo.platformVersion; // Services.vc.compare(xulVer,"2.0a")>=0
     mozt.Debug.debug("OS=" + runtimeOS + ", XULrunner=" + xulVer);
     if (runtimeOS != "Linux") {
       Components.utils.reportError("MOZTRAY: only Linux platform supported at this time. Moztray not loaded");
@@ -162,26 +183,55 @@ mozt.Handler = {
 
       // instanciate tray icon
       LibGtkStatusIcon.init();
-      this.tray_icon  = LibGtkStatusIcon.gtk_status_icon_new();
+      this.trayIcon  = LibGtkStatusIcon.gtk_status_icon_new();
       var mozApp = Services.appinfo.name.toLowerCase();
       var iconFilename = MOZT_ICON_DIR + mozApp + MOZT_ICON_SUFFIX;
-      LibGtkStatusIcon.gtk_status_icon_set_from_file(this.tray_icon,
+      LibGtkStatusIcon.gtk_status_icon_set_from_file(this.trayIcon,
                                                      iconFilename);
 
+      // build icon popup menu
+      this.menu = LibGtkStatusIcon.gtk_menu_new();
+      // TODO: intl labels,
+      // gtk_image_menu_item_new_with_label ?
+      var menuItemView = LibGtkStatusIcon.gtk_image_menu_item_new_with_label("View");
+/*
+      let image = gtk_image_new_from_file("");
+      LibGtkStatusIcon.gtk_image_set_pixel_size( GTK_IMAGE ( image ), GTK_ICON_SIZE_MENU );
+      LibGtkStatusIcon.gtk_image_menu_item_set_image ( GTK_IMAGE_MENU_ITEM ( menu_item ), image );
+*/
+      var menuItemExit = LibGtkStatusIcon.gtk_image_menu_item_new_with_label("Exit");
+      var menuShell = ctypes.cast(this.menu, LibGtkStatusIcon.GtkMenuShell.ptr);
+      LibGtkStatusIcon.gtk_menu_shell_append(menuShell, menuItemView);
+      LibGtkStatusIcon.gtk_menu_shell_append(menuShell, menuItemExit);
+      var menuWidget = ctypes.cast(this.menu, LibGtkStatusIcon.GtkWidget.ptr);
+      LibGtkStatusIcon.gtk_widget_show_all(menuWidget);
+
+      // here we do use a function handler because we need the args passed to
+      // it ! But we need to abandon 'this' in popupMenu()
+      mozt_popupMenuCb =
+        LibGtkStatusIcon.GCallbackMenuPopup_t(mozt.Handler.popupMenu);
+      LibGObject.g_signal_connect(this.trayIcon, "popup-menu",
+                                  mozt_popupMenuCb, this.menu);
+
+/*
+    g_signal_connect (G_OBJECT (menuItemView), "activate", G_CALLBACK (trayView), window);
+    g_signal_connect (G_OBJECT (menuItemExit), "activate", G_CALLBACK (trayExit), NULL);
+*/
       // set tooltip.
       // GTK bug:
       // (firefox-bin:5302): Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
       // (thunderbird-bin:5380): Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
-      LibGtkStatusIcon.gtk_status_icon_set_tooltip_text(this.tray_icon,
+      LibGtkStatusIcon.gtk_status_icon_set_tooltip_text(this.trayIcon,
                                                         mozApp);
 
       // close lib
       LibGtkStatusIcon.shutdown();
 
-      // watch out for binding problems !
+      // watch out for binding problems ! here we prefer to keep 'this' in
+      // showHideToTray() and abandon the args.
       mozt_activateCb = LibGObject.GCallback_t(
         function(){mozt.Handler.showHideToTray();});
-      LibGObject.g_signal_connect(this.tray_icon, "activate",
+      LibGObject.g_signal_connect(this.trayIcon, "activate",
                                   mozt_activateCb, null);
 
     } catch (x) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list