From 0cfe58e41065225de3589c40458236675de332af Mon Sep 17 00:00:00 2001 From: foudfou Date: Wed, 8 Oct 2014 23:19:19 +0200 Subject: [PATCH] * Linux: fix return value according to return type definitions for some ctypes callbacks, thus avoiding "expected type int, got (void 0)". * Cleaning. --- src/modules/commons.js | 25 ++++++++++- src/modules/linux/FiretrayPopupMenu.jsm | 53 ++++++++++++++---------- src/modules/linux/FiretrayStatusIcon.jsm | 14 ++++--- src/modules/linux/FiretrayWindow.jsm | 33 +++++++++------ 4 files changed, 86 insertions(+), 39 deletions(-) diff --git a/src/modules/commons.js b/src/modules/commons.js index 9fa622f..55fb2ce 100644 --- a/src/modules/commons.js +++ b/src/modules/commons.js @@ -16,7 +16,8 @@ var EXPORTED_SYMBOLS = "FIRETRAY_DELAY_NOWAIT_MILLISECONDS", "FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD", "FIRETRAY_MESSAGE_COUNT_TYPE_NEW", "FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL", "FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE", "FIRETRAY_APP_DB", - "FIRETRAY_XUL_ATTRIBUTE_COMMAND", "FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND" ]; + "FIRETRAY_XUL_ATTRIBUTE_COMMAND", "FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND", + "FIRETRAY_CB_SENTINEL" ]; const Cc = Components.classes; const Ci = Components.interfaces; @@ -91,6 +92,28 @@ const FIRETRAY_APP_DB = { }; +/* + * Debugging purpose: if a callback fails (like "expected type int, got (void + * 0)"), there is no easy way to find out which (for ex. when called through + * g_signal_connect()). A possible way is to remove the sentinel definition on + * each callback definition one-by-one. For ex: + * + * let callback = gtk.GCallbackWidgetFocusEvent_t( + * firetray.Window.onFocusIn, null, FIRETRAY_CB_SENTINEL); + * + * becomes + * + * let callback = gtk.GCallbackWidgetFocusEvent_t( + * firetray.Window.onFocusIn); + * + * and see if the the message "JavaScript callback failed, and an error + * sentinel was not specified" appears in the console. + * + * Note: it's not possible to define a sentinel when the return type is void. + * Note: almost all return types end up as int's (even gboolean). + */ +const FIRETRAY_CB_SENTINEL = -1; + /** * firetray namespace. */ diff --git a/src/modules/linux/FiretrayPopupMenu.jsm b/src/modules/linux/FiretrayPopupMenu.jsm index 79da00f..f79e1a3 100644 --- a/src/modules/linux/FiretrayPopupMenu.jsm +++ b/src/modules/linux/FiretrayPopupMenu.jsm @@ -33,33 +33,41 @@ firetray.PopupMenu = { var addMenuSeparator = false; if (firetray.Handler.inMailApp) { - this.addItem("ResetIcon", "gtk-apply", "activate", firetray.Handler.setIconImageDefault); - this.addItem("NewMessage", "gtk-edit", "activate", firetray.Handler.openMailMessage); + this.addItem("ResetIcon", "gtk-apply", "activate", + firetray.Handler.setIconImageDefault); + this.addItem("NewMessage", "gtk-edit", "activate", + firetray.Handler.openMailMessage); addMenuSeparator = true; } if (firetray.Handler.inBrowserApp) { - this.addItem("NewWindow", "gtk-new", "activate", firetray.Handler.openBrowserWindow); + this.addItem("NewWindow", "gtk-new", "activate", + firetray.Handler.openBrowserWindow); addMenuSeparator = true; } var menuSeparator; if (addMenuSeparator) { menuSeparator = gtk.gtk_separator_menu_item_new(); - gtk.gtk_menu_shell_append(this.menuShell, ctypes.cast(menuSeparator, gtk.GtkWidget.ptr)); + gtk.gtk_menu_shell_append(this.menuShell, ctypes.cast(menuSeparator, + gtk.GtkWidget.ptr)); } - this.addItem("Preferences", "gtk-preferences", "activate", firetray.Handler.openPrefWindow); + this.addItem("Preferences", "gtk-preferences", "activate", + firetray.Handler.openPrefWindow); menuSeparator = gtk.gtk_separator_menu_item_new(); - gtk.gtk_menu_shell_append(this.menuShell, ctypes.cast(menuSeparator, gtk.GtkWidget.ptr)); + gtk.gtk_menu_shell_append(this.menuShell, ctypes.cast(menuSeparator, + gtk.GtkWidget.ptr)); - this.addItem("Quit", "gtk-quit", "activate", firetray.Handler.quitApplication); + this.addItem("Quit", "gtk-quit", "activate", + firetray.Handler.quitApplication); var menuWidget = ctypes.cast(this.menu, gtk.GtkWidget.ptr); gtk.gtk_widget_show_all(menuWidget); var menuSeparatorWindows = gtk.gtk_separator_menu_item_new(); - gtk.gtk_menu_shell_prepend(this.menuShell, ctypes.cast(menuSeparatorWindows, gtk.GtkWidget.ptr)); + gtk.gtk_menu_shell_prepend(this.menuShell, ctypes.cast(menuSeparatorWindows, + gtk.GtkWidget.ptr)); this.menuSeparatorWindows = menuSeparatorWindows; this.initialized = true; @@ -84,7 +92,7 @@ firetray.PopupMenu = { let cbName = "menuItem"+capitalizeFirst(itemName)+capitalizeFirst(action); log.debug("cbName="+cbName); - this.callbacks[cbName] = gobject.GCallback_t(callback); + this.callbacks[cbName] = gobject.GCallback_t(callback); // void return, no sentinel gobject.g_signal_connect(menuItem, action, firetray.PopupMenu.callbacks[cbName], null); }, @@ -93,34 +101,37 @@ firetray.PopupMenu = { log.debug("menu-popup"); log.debug("ARGS="+icon+", "+button+", "+activateTime+", "+menu); - try { - var gtkMenuPtr = ctypes.cast(menu, gtk.GtkMenu.ptr); - var iconGpointer = ctypes.cast(icon, gobject.gpointer); - gtk.gtk_menu_popup( - gtkMenuPtr, null, null, gtk.gtk_status_icon_position_menu, - iconGpointer, button, activateTime); - } catch (x) { log.error(x); } + var gtkMenuPtr = ctypes.cast(menu, gtk.GtkMenu.ptr); + var iconGpointer = ctypes.cast(icon, gobject.gpointer); + gtk.gtk_menu_popup( + gtkMenuPtr, null, null, gtk.gtk_status_icon_position_menu, + iconGpointer, button, activateTime); + + let stopPropagation = false; + return stopPropagation; }, // we'll be creating menuItems for windows (and not showing them) even if // hides_single_window is false, because if hides_single_window becomes true, // we'll just have to show the menuItems addWindowItem: function(xid) { // on registerWindow + log.warn("addWindowItem"); var menuItemWindow = this.createAndAddItemToMenu(); firetray.Handler.gtkPopupMenuWindowItems.insert(xid, menuItemWindow); this.setWindowItemLabel(menuItemWindow, xid.toString()); // default to xid - this.callbacks.menuItemWindowActivate[xid] = gobject.GCallback_t( - function(){firetray.Handler.showWindow(xid);}); - gobject.g_signal_connect(menuItemWindow, "activate", - firetray.PopupMenu.callbacks.menuItemWindowActivate[xid], null); + let callback = gobject.GCallback_t( + function(){firetray.Handler.showWindow(xid);}, null, FIRETRAY_CB_SENTINEL); // void return, no sentinel + this.callbacks.menuItemWindowActivate[xid] = callback, + gobject.g_signal_connect(menuItemWindow, "activate", callback, null); log.debug("added gtkPopupMenuWindowItems: "+firetray.Handler.gtkPopupMenuWindowItems.count); }, createAndAddItemToMenu: function() { var menuItem = gtk.gtk_image_menu_item_new(); - gtk.gtk_menu_shell_prepend(this.menuShell, ctypes.cast(menuItem, gtk.GtkWidget.ptr)); + gtk.gtk_menu_shell_prepend(this.menuShell, ctypes.cast(menuItem, + gtk.GtkWidget.ptr)); return menuItem; }, diff --git a/src/modules/linux/FiretrayStatusIcon.jsm b/src/modules/linux/FiretrayStatusIcon.jsm index 1b1b54f..9882572 100644 --- a/src/modules/linux/FiretrayStatusIcon.jsm +++ b/src/modules/linux/FiretrayStatusIcon.jsm @@ -128,22 +128,23 @@ firetray.StatusIcon = { /* NOTE: here we do use a function handler (instead of a function definition) because we need the args passed to it ! As a consequence, we need to abandon 'this' in PopupMenu.popup() */ - this.callbacks.menuPopup = gtk.GCallbackMenuPopup_t(firetray.PopupMenu.popup); + this.callbacks.menuPopup = gtk.GCallbackMenuPopup_t(firetray.PopupMenu.popup); // void return, no sentinel gobject.g_signal_connect(this.trayIcon, "popup-menu", firetray.StatusIcon.callbacks.menuPopup, firetray.PopupMenu.menu); - this.callbacks.onScroll = gtk.GCallbackOnScroll_t(firetray.StatusIcon.onScroll); + this.callbacks.onScroll = gtk.GCallbackOnScroll_t( + firetray.StatusIcon.onScroll, null, FIRETRAY_CB_SENTINEL); gobject.g_signal_connect(this.trayIcon, "scroll-event", firetray.StatusIcon.callbacks.onScroll, null); log.debug("showHideAllWindows: "+firetray.Handler.hasOwnProperty("showHideAllWindows")); this.callbacks.iconActivate = gtk.GCallbackStatusIconActivate_t( - firetray.StatusIcon.onClick); + firetray.StatusIcon.onClick, null, FIRETRAY_CB_SENTINEL); let handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon, "activate", firetray.StatusIcon.callbacks.iconActivate, null); log.debug("g_connect activate="+handlerId); this.callbacks.iconMiddleClick = gtk.GCallbackStatusIconMiddleClick_t( - firetray.Handler.activateLastWindowCb); + firetray.Handler.activateLastWindowCb, null, FIRETRAY_CB_SENTINEL); handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon, "button-press-event", firetray.StatusIcon.callbacks.iconMiddleClick, null); log.debug("g_connect middleClick="+handlerId); @@ -151,7 +152,7 @@ firetray.StatusIcon = { onScroll: function(icon, event, data) { if (!firetray.Utils.prefService.getBoolPref("scroll_hides")) - return; + return false; let iconGpointer = ctypes.cast(icon, gobject.gpointer); let gdkEventScroll = ctypes.cast(event, gdk.GdkEventScroll.ptr); @@ -176,6 +177,9 @@ firetray.StatusIcon = { default: log.error("SCROLL UNKNOWN"); } + + let stopPropagation = false; + return stopPropagation; }, onClick: function(gtkStatusIcon, userData) { diff --git a/src/modules/linux/FiretrayWindow.jsm b/src/modules/linux/FiretrayWindow.jsm index 796ca8f..814188f 100644 --- a/src/modules/linux/FiretrayWindow.jsm +++ b/src/modules/linux/FiretrayWindow.jsm @@ -86,7 +86,7 @@ firetray.Window.shutdown = function() { * Iterate over all Gtk toplevel windows to find a window. We rely on * Service.wm to watch windows correctly: we should find only one window. * - * @author Nils Maier (stolen from MiniTrayR) + * @author Nils Maier (stolen from MiniTrayR), himself inspired by Windows docs * @param window nsIDOMWindow from Services.wm * @return a gtk.GtkWindow.ptr */ @@ -105,7 +105,7 @@ firetray.Window.getGtkWindowFromChromeWindow = function(window) { // Search the window by the *temporary* title let widgets = gtk.gtk_window_list_toplevels(); let that = this; - let findGtkWindowByTitleCb = gobject.GFunc_t(that._findGtkWindowByTitle); + let findGtkWindowByTitleCb = gobject.GFunc_t(that._findGtkWindowByTitle); // void return, no sentinel var userData = new _find_data_t( ctypes.char.array()(baseWindow.title), null @@ -590,18 +590,22 @@ firetray.Window.showAllWindowsAndActivate = function() { firetray.Window.attachOnFocusInCallback = function(xid) { log.debug("attachOnFocusInCallback xid="+xid); - this.signals['focus-in'].callback[xid] = - gtk.GCallbackWidgetFocusEvent_t(firetray.Window.onFocusIn); - this.signals['focus-in'].handler[xid] = gobject.g_signal_connect( - firetray.Handler.gtkWindows.get(xid), "focus-in-event", - firetray.Window.signals['focus-in'].callback[xid], null); - log.debug("focus-in handler="+this.signals['focus-in'].handler[xid]); + let callback = gtk.GCallbackWidgetFocusEvent_t( + firetray.Window.onFocusIn, null, FIRETRAY_CB_SENTINEL); + this.signals['focus-in'].callback[xid] = callback; + let rv = gobject.g_signal_connect( + firetray.Handler.gtkWindows.get(xid), "focus-in-event", callback, null); + log.debug("focus-in handler="+rv); + this.signals['focus-in'].handler[xid] = rv; }; firetray.Window.detachOnFocusInCallback = function(xid) { log.debug("detachOnFocusInCallback xid="+xid); let gtkWin = firetray.Handler.gtkWindows.get(xid); - gobject.g_signal_handler_disconnect(gtkWin, this.signals['focus-in'].handler[xid]); + gobject.g_signal_handler_disconnect( + gtkWin, + gobject.gulong(this.signals['focus-in'].handler[xid]) + ); delete this.signals['focus-in'].callback[xid]; delete this.signals['focus-in'].handler[xid]; }; @@ -619,6 +623,9 @@ firetray.Window.onFocusIn = function(widget, event, data) { if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) { firetray.Chat.stopGetAttentionMaybe(xid); } + + let stopPropagation = false; + return stopPropagation; }; @@ -660,10 +667,12 @@ firetray.Handler.registerWindow = function(win) { // delete_event_cb (in gtk2/nsWindow.cpp), but we prefer to use the // provided 'close' JS event - this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t(firetray.Window.filterWindow); + this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t( + firetray.Window.filterWindow, null, FIRETRAY_CB_SENTINEL); gdk.gdk_window_add_filter(gdkWin, this.windows[xid].filterWindowCb, null); if (!firetray.Handler.appStarted) { - this.windows[xid].startupFilterCb = gdk.GdkFilterFunc_t(firetray.Window.startupFilter); + this.windows[xid].startupFilterCb = gdk.GdkFilterFunc_t( + firetray.Window.startupFilter, null, FIRETRAY_CB_SENTINEL); gdk.gdk_window_add_filter(gdkWin, this.windows[xid].startupFilterCb, null); } @@ -673,8 +682,8 @@ firetray.Handler.registerWindow = function(win) { } } catch (x) { - firetray.Window.unregisterWindowByXID(xid); log.error(x); + firetray.Window.unregisterWindowByXID(xid); return null; }