mirror of
https://github.com/moparisthebest/FireTray
synced 2025-01-08 12:08:05 -05:00
* un-/register windows (begin) => refactoring
* filter icon events (begin)
This commit is contained in:
parent
5eaf647633
commit
d52245cc87
32
src/modules/FiretrayWindow.jsm
Normal file
32
src/modules/FiretrayWindow.jsm
Normal file
@ -0,0 +1,32 @@
|
||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// https://developer.mozilla.org/en/Code_snippets/Preferences
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "FiretrayWindow" ];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
|
||||
let log = firetray.Logging.getLogger("firetray.FiretrayWindow");
|
||||
|
||||
if ("undefined" == typeof(firetray.Handler))
|
||||
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||
|
||||
function FiretrayWindow () {}
|
||||
FiretrayWindow.prototype = {
|
||||
|
||||
updateVisibility: function(winId, visibility) {
|
||||
let win = firetray.Handler.windows[winId];
|
||||
if (win.visible === visibility)
|
||||
log.warn("window (winId="+winId+") was already visible="+win.visible);
|
||||
|
||||
firetray.Handler.visibleWindowsCount = visibility ?
|
||||
firetray.Handler.visibleWindowsCount + 1 :
|
||||
firetray.Handler.visibleWindowsCount - 1 ;
|
||||
|
||||
win.visible = visibility; // nsIBaseWin.visibility always true :-(
|
||||
},
|
||||
|
||||
};
|
@ -74,4 +74,33 @@ var win32 = {
|
||||
ERROR_INVALID_WINDOW_HANDLE: 1400,
|
||||
ERROR_RESOURCE_TYPE_NOT_FOUND: 1813,
|
||||
|
||||
// WinUser.h
|
||||
WM_USER: 0x0400,
|
||||
|
||||
WM_CONTEXTMENU: 0x007B,
|
||||
|
||||
WM_MOUSEFIRST: 0x0200,
|
||||
WM_MOUSEMOVE: 0x0200,
|
||||
WM_LBUTTONDOWN: 0x0201,
|
||||
WM_LBUTTONUP: 0x0202,
|
||||
WM_LBUTTONDBLCLK: 0x0203,
|
||||
WM_RBUTTONDOWN: 0x0204,
|
||||
WM_RBUTTONUP: 0x0205,
|
||||
WM_RBUTTONDBLCLK: 0x0206,
|
||||
WM_MBUTTONDOWN: 0x0207,
|
||||
WM_MBUTTONUP: 0x0208,
|
||||
WM_MBUTTONDBLCLK: 0x0209,
|
||||
WM_MOUSEWHEEL: 0x020A,
|
||||
WM_XBUTTONDOWN: 0x020B,
|
||||
WM_XBUTTONUP: 0x020C,
|
||||
WM_XBUTTONDBLCLK: 0x020D,
|
||||
WM_MOUSELAST: 0x020D,
|
||||
WM_MOUSELAST: 0x020A,
|
||||
|
||||
};
|
||||
|
||||
// ShellAPI.h
|
||||
let nin_select = win32.WM_USER + 0;
|
||||
win32.NIN_SELECT = nin_select;
|
||||
win32.NINF_KEY = 0x1;
|
||||
win32.NIN_KEYSELECT = (win32.NIN_SELECT | win32.NINF_KEY);
|
||||
|
@ -22,6 +22,7 @@ Cu.import("resource://firetray/ctypes/linux/gdk.jsm");
|
||||
Cu.import("resource://firetray/ctypes/linux/gtk.jsm");
|
||||
Cu.import("resource://firetray/ctypes/linux/libc.jsm");
|
||||
Cu.import("resource://firetray/ctypes/linux/x11.jsm");
|
||||
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
firetray.Handler.subscribeLibsForClosing([gobject, gdk, gtk, libc, x11, glib]);
|
||||
|
||||
@ -57,10 +58,11 @@ firetray.Handler.gdkWindows = new ctypesMap(gdk.GdkWindow.ptr),
|
||||
firetray.Handler.gtkPopupMenuWindowItems = new ctypesMap(gtk.GtkImageMenuItem.ptr),
|
||||
|
||||
|
||||
firetray.Window = {
|
||||
signals: {'focus-in': {callback: {}, handler: {}}},
|
||||
firetray.Window = new FiretrayWindow();
|
||||
|
||||
init: function() {
|
||||
firetray.Window.signals = {'focus-in': {callback: {}, handler: {}}};
|
||||
|
||||
firetray.Window.init = function() {
|
||||
let gtkVersionCheck = gtk.gtk_check_version(
|
||||
gtk.FIRETRAY_REQUIRED_GTK_MAJOR_VERSION,
|
||||
gtk.FIRETRAY_REQUIRED_GTK_MINOR_VERSION,
|
||||
@ -75,11 +77,11 @@ firetray.Window = {
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
},
|
||||
};
|
||||
|
||||
shutdown: function() {
|
||||
firetray.Window.shutdown = function() {
|
||||
this.initialized = false;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterate over all Gtk toplevel windows to find a window. We rely on
|
||||
@ -89,7 +91,7 @@ firetray.Window = {
|
||||
* @param window nsIDOMWindow from Services.wm
|
||||
* @return a gtk.GtkWindow.ptr
|
||||
*/
|
||||
getGtkWindowFromChromeWindow: function(window) {
|
||||
firetray.Window.getGtkWindowFromChromeWindow = function(window) {
|
||||
let baseWindow = window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
@ -125,14 +127,14 @@ firetray.Window = {
|
||||
}
|
||||
|
||||
return userData.contents.outWindow;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* compares a GtkWindow's title with a string passed in userData
|
||||
* @param gtkWidget: GtkWidget from gtk_window_list_toplevels()
|
||||
* @param userData: _find_data_t
|
||||
*/
|
||||
_findGtkWindowByTitle: function(gtkWidget, userData) {
|
||||
firetray.Window._findGtkWindowByTitle = function(gtkWidget, userData) {
|
||||
let data = ctypes.cast(userData, _find_data_t.ptr);
|
||||
let inTitle = data.contents.inTitle;
|
||||
|
||||
@ -144,9 +146,9 @@ firetray.Window = {
|
||||
if (libc.strcmp(inTitle, winTitle) == 0)
|
||||
data.contents.outWindow = gtkWin;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
getGdkWindowFromGtkWindow: function(gtkWin) {
|
||||
firetray.Window.getGdkWindowFromGtkWindow = function(gtkWin) {
|
||||
try {
|
||||
let gtkWid = ctypes.cast(gtkWin, gtk.GtkWidget.ptr);
|
||||
return gtk.gtk_widget_get_window(gtkWid);
|
||||
@ -154,39 +156,39 @@ firetray.Window = {
|
||||
log.error(x);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
getXIDFromGdkWindow: function(gdkWin) {
|
||||
firetray.Window.getXIDFromGdkWindow = function(gdkWin) {
|
||||
return gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
|
||||
},
|
||||
};
|
||||
|
||||
getXIDFromGtkWidget: function(gtkWid) {
|
||||
firetray.Window.getXIDFromGtkWidget = function(gtkWid) {
|
||||
let gdkWin = gtk.gtk_widget_get_window(gtkWid);
|
||||
return gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
|
||||
},
|
||||
};
|
||||
|
||||
addrPointedByInHex: function(ptr) {
|
||||
firetray.Window.addrPointedByInHex = function(ptr) {
|
||||
return "0x"+ctypes.cast(ptr, ctypes.uintptr_t.ptr).contents.toString(16);
|
||||
},
|
||||
};
|
||||
|
||||
getGdkWindowFromNativeHandle: function(nativeHandle) {
|
||||
firetray.Window.getGdkWindowFromNativeHandle = function(nativeHandle) {
|
||||
let gdkw = new gdk.GdkWindow.ptr(ctypes.UInt64(nativeHandle)); // a new pointer to the GdkWindow
|
||||
gdkw = gdk.gdk_window_get_toplevel(gdkw);
|
||||
log.debug("gdkw="+gdkw+" *gdkw="+this.addrPointedByInHex(gdkw));
|
||||
return gdkw;
|
||||
},
|
||||
};
|
||||
|
||||
getGtkWindowFromGdkWindow: function(gdkWin) {
|
||||
firetray.Window.getGtkWindowFromGdkWindow = function(gdkWin) {
|
||||
let gptr = new gobject.gpointer;
|
||||
gdk.gdk_window_get_user_data(gdkWin, gptr.address());
|
||||
log.debug("gptr="+gptr+" *gptr="+this.addrPointedByInHex(gptr));
|
||||
let gtkw = ctypes.cast(gptr, gtk.GtkWindow.ptr);
|
||||
log.debug("gtkw="+gtkw+" *gtkw="+this.addrPointedByInHex(gtkw));
|
||||
return gtkw;
|
||||
},
|
||||
};
|
||||
|
||||
/* consider using getXIDFromChromeWindow() if you only need the XID */
|
||||
getWindowsFromChromeWindow: function(win) {
|
||||
firetray.Window.getWindowsFromChromeWindow = function(win) {
|
||||
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
||||
let nativeHandle = baseWin.nativeHandle; // Moz' private pointer to the GdkWindow
|
||||
log.debug("nativeHandle="+nativeHandle);
|
||||
@ -201,16 +203,16 @@ firetray.Window = {
|
||||
let xid = firetray.Window.getXIDFromGdkWindow(gdkWin);
|
||||
log.debug("XID="+xid);
|
||||
return [baseWin, gtkWin, gdkWin, xid];
|
||||
},
|
||||
};
|
||||
|
||||
getXIDFromChromeWindow: function(win) {
|
||||
firetray.Window.getXIDFromChromeWindow = function(win) {
|
||||
for (let xid in firetray.Handler.windows)
|
||||
if (firetray.Handler.windows[xid].chromeWin === win) return xid;
|
||||
log.error("unknown window while lookup");
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
unregisterWindowByXID: function(xid) {
|
||||
firetray.Window.unregisterWindowByXID = function(xid) {
|
||||
if (!firetray.Handler.windows.hasOwnProperty(xid)) {
|
||||
log.error("can't unregister unknown window "+xid);
|
||||
return false;
|
||||
@ -232,9 +234,9 @@ firetray.Window = {
|
||||
|
||||
log.debug("window "+xid+" unregistered");
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
show: function(xid) {
|
||||
firetray.Window.show = function(xid) {
|
||||
log.debug("show xid="+xid);
|
||||
|
||||
// try to restore previous state. TODO: z-order respected ?
|
||||
@ -252,11 +254,11 @@ firetray.Window = {
|
||||
|
||||
firetray.PopupMenu.hideWindowItemAndSeparatorMaybe(xid);
|
||||
firetray.Handler.showHideIcon();
|
||||
},
|
||||
};
|
||||
|
||||
/* FIXME: hiding windows should also hide child windows, like message windows
|
||||
in Thunderbird */
|
||||
hide: function(xid) {
|
||||
firetray.Window.hide = function(xid) {
|
||||
log.debug("hide");
|
||||
|
||||
firetray.Window.savePositionAndSize(xid);
|
||||
@ -267,9 +269,9 @@ firetray.Window = {
|
||||
|
||||
firetray.PopupMenu.showWindowItem(xid);
|
||||
firetray.Handler.showHideIcon();
|
||||
},
|
||||
};
|
||||
|
||||
startupHide: function(xid) {
|
||||
firetray.Window.startupHide = function(xid) {
|
||||
log.debug('startupHide: '+xid);
|
||||
|
||||
// also it seems cleaner, baseWin.visibility=false removes the possibility
|
||||
@ -278,9 +280,9 @@ firetray.Window = {
|
||||
|
||||
firetray.PopupMenu.showWindowItem(xid);
|
||||
firetray.Handler.showHideIcon();
|
||||
},
|
||||
};
|
||||
|
||||
savePositionAndSize: function(xid) {
|
||||
firetray.Window.savePositionAndSize = function(xid) {
|
||||
let gx = {}, gy = {}, gwidth = {}, gheight = {};
|
||||
firetray.Handler.windows[xid].baseWin.getPositionAndSize(gx, gy, gwidth, gheight);
|
||||
firetray.Handler.windows[xid].savedX = gx.value;
|
||||
@ -288,9 +290,9 @@ firetray.Window = {
|
||||
firetray.Handler.windows[xid].savedWidth = gwidth.value;
|
||||
firetray.Handler.windows[xid].savedHeight = gheight.value;
|
||||
log.debug("save: gx="+gx.value+", gy="+gy.value+", gwidth="+gwidth.value+", gheight="+gheight.value);
|
||||
},
|
||||
};
|
||||
|
||||
restorePositionAndSize: function(xid) {
|
||||
firetray.Window.restorePositionAndSize = function(xid) {
|
||||
if ("undefined" === typeof(firetray.Handler.windows[xid].savedX))
|
||||
return; // windows[xid].saved* may not be initialized
|
||||
|
||||
@ -305,17 +307,17 @@ firetray.Window = {
|
||||
['savedX', 'savedX', 'savedWidth', 'savedHeight'].forEach(function(element) {
|
||||
delete firetray.Handler.windows[xid][element];
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
saveStates: function(xid) {
|
||||
firetray.Window.saveStates = function(xid) {
|
||||
let winStates = firetray.Window.getXWindowStates(x11.Window(xid));
|
||||
firetray.Handler.windows[xid].savedStates = winStates;
|
||||
log.debug("save: windowStates="+winStates);
|
||||
},
|
||||
};
|
||||
|
||||
// NOTE: fluxbox bug probably: if hidden and restored iconified, then
|
||||
// switching to desktop de-iconifies it ?!
|
||||
restoreStates: function(xid) {
|
||||
firetray.Window.restoreStates = function(xid) {
|
||||
let winStates = firetray.Handler.windows[xid].savedStates;
|
||||
log.debug("restored WindowStates: " + winStates);
|
||||
|
||||
@ -336,18 +338,18 @@ firetray.Window = {
|
||||
}
|
||||
|
||||
delete firetray.Handler.windows[xid].savedStates;
|
||||
},
|
||||
};
|
||||
|
||||
saveDesktop: function(xid) {
|
||||
firetray.Window.saveDesktop = function(xid) {
|
||||
if (!firetray.Utils.prefService.getBoolPref('remember_desktop'))
|
||||
return;
|
||||
|
||||
let winDesktop = firetray.Window.getXWindowDesktop(x11.Window(xid));
|
||||
firetray.Handler.windows[xid].savedDesktop = winDesktop;
|
||||
log.debug("save: windowDesktop="+winDesktop);
|
||||
},
|
||||
};
|
||||
|
||||
restoreDesktop: function(xid) {
|
||||
firetray.Window.restoreDesktop = function(xid) {
|
||||
if (!firetray.Utils.prefService.getBoolPref('remember_desktop'))
|
||||
return;
|
||||
|
||||
@ -361,9 +363,9 @@ firetray.Window = {
|
||||
|
||||
log.debug("restored to desktop: "+desktopDest);
|
||||
delete firetray.Handler.windows[xid].savedDesktop;
|
||||
},
|
||||
};
|
||||
|
||||
setVisibility: function(xid, visibility) {
|
||||
firetray.Window.setVisibility = function(xid, visibility) {
|
||||
log.debug("setVisibility="+visibility);
|
||||
let gtkWidget = ctypes.cast(firetray.Handler.gtkWindows.get(xid), gtk.GtkWidget.ptr);
|
||||
if (visibility)
|
||||
@ -372,21 +374,10 @@ firetray.Window = {
|
||||
gtk.gtk_widget_hide(gtkWidget);
|
||||
|
||||
this.updateVisibility(xid, visibility);
|
||||
},
|
||||
};
|
||||
// firetray.Window.updateVisibility inherited
|
||||
|
||||
updateVisibility: function(xid, visibility) {
|
||||
let win = firetray.Handler.windows[xid];
|
||||
if (win.visible === visibility)
|
||||
log.warn("window (xid="+xid+") was already visible="+win.visible);
|
||||
|
||||
firetray.Handler.visibleWindowsCount = visibility ?
|
||||
firetray.Handler.visibleWindowsCount + 1 :
|
||||
firetray.Handler.visibleWindowsCount - 1 ;
|
||||
|
||||
win.visible = visibility; // nsIBaseWin.visibility always true :-(
|
||||
},
|
||||
|
||||
xSendClientMessgeEvent: function(xid, atom, data, dataSize) {
|
||||
firetray.Window.xSendClientMessgeEvent = function(xid, atom, data, dataSize) {
|
||||
let xev = new x11.XClientMessageEvent;
|
||||
xev.type = x11.ClientMessage;
|
||||
xev.window = x11.Window(xid);
|
||||
@ -401,27 +392,27 @@ firetray.Window = {
|
||||
// fortunately, it's OK not to cast xev. ctypes.cast to a void_t doesn't work (length pb)
|
||||
let status = x11.XSendEvent(x11.current.Display, rootWin, propagate, mask, xev.address());
|
||||
// always returns 1 (BadRequest as a coincidence)
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* raises window on top and give focus.
|
||||
*/
|
||||
activate: function(xid) {
|
||||
firetray.Window.activate = function(xid) {
|
||||
gtk.gtk_window_present(firetray.Handler.gtkWindows.get(xid));
|
||||
log.debug("window raised");
|
||||
},
|
||||
};
|
||||
|
||||
setUrgency: function(xid, urgent) {
|
||||
firetray.Window.setUrgency = function(xid, urgent) {
|
||||
log.debug("setUrgency: "+urgent);
|
||||
gtk.gtk_window_set_urgency_hint(firetray.Handler.gtkWindows.get(xid), urgent);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* YOU MUST x11.XFree() THE VARIABLE RETURNED BY THIS FUNCTION
|
||||
* @param xwin: a x11.Window
|
||||
* @param prop: a x11.Atom
|
||||
*/
|
||||
getXWindowProperties: function(xwin, prop) {
|
||||
firetray.Window.getXWindowProperties = function(xwin, prop) {
|
||||
// infos returned by XGetWindowProperty() - FIXME: should be freed ?
|
||||
let actual_type = new x11.Atom;
|
||||
let actual_format = new ctypes.int;
|
||||
@ -458,7 +449,7 @@ firetray.Window = {
|
||||
log.debug("props="+props+", size="+props.constructor.size);
|
||||
|
||||
return [props, nitems];
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* check the state of a window by its EWMH window state. This is more
|
||||
@ -466,7 +457,7 @@ firetray.Window = {
|
||||
* based on WM_STATE. For instance, WM_STATE becomes 'Iconic' on virtual
|
||||
* desktop change...
|
||||
*/
|
||||
getXWindowStates: function(xwin) {
|
||||
firetray.Window.getXWindowStates = function(xwin) {
|
||||
let winStates = 0;
|
||||
|
||||
let [propsFound, nitems] =
|
||||
@ -492,9 +483,9 @@ firetray.Window = {
|
||||
x11.XFree(propsFound);
|
||||
|
||||
return winStates;
|
||||
},
|
||||
};
|
||||
|
||||
getXWindowDesktop: function(xwin) {
|
||||
firetray.Window.getXWindowDesktop = function(xwin) {
|
||||
let desktop = null;
|
||||
|
||||
let [propsFound, nitems] =
|
||||
@ -512,9 +503,9 @@ firetray.Window = {
|
||||
x11.XFree(propsFound);
|
||||
|
||||
return desktop;
|
||||
},
|
||||
};
|
||||
|
||||
getWindowTitle: function(xid) {
|
||||
firetray.Window.getWindowTitle = function(xid) {
|
||||
let title = firetray.Handler.windows[xid].baseWin.title;
|
||||
log.debug("|baseWin.title="+title+"|");
|
||||
let tailIndex;
|
||||
@ -528,9 +519,9 @@ firetray.Window = {
|
||||
return title;
|
||||
else
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
checkSubscribedEventMasks: function(xid) {
|
||||
firetray.Window.checkSubscribedEventMasks = function(xid) {
|
||||
let xWindowAttributes = new x11.XWindowAttributes;
|
||||
let status = x11.XGetWindowAttributes(x11.current.Display, xid, xWindowAttributes.address());
|
||||
log.debug("xWindowAttributes: "+xWindowAttributes);
|
||||
@ -541,9 +532,9 @@ firetray.Window = {
|
||||
if ((xEventMask & xEventMaskNeeded) !== xEventMaskNeeded) {
|
||||
log.error("missing mandatory event-masks"); // change with gdk_window_set_events()
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
filterWindow: function(xev, gdkEv, data) {
|
||||
firetray.Window.filterWindow = function(xev, gdkEv, data) {
|
||||
if (!xev)
|
||||
return gdk.GDK_FILTER_CONTINUE;
|
||||
|
||||
@ -592,9 +583,9 @@ firetray.Window = {
|
||||
}
|
||||
|
||||
return gdk.GDK_FILTER_CONTINUE;
|
||||
},
|
||||
};
|
||||
|
||||
startupFilter: function(xev, gdkEv, data) {
|
||||
firetray.Window.startupFilter = function(xev, gdkEv, data) {
|
||||
if (!xev)
|
||||
return gdk.GDK_FILTER_CONTINUE;
|
||||
|
||||
@ -611,9 +602,9 @@ firetray.Window = {
|
||||
}
|
||||
|
||||
return gdk.GDK_FILTER_CONTINUE;
|
||||
},
|
||||
};
|
||||
|
||||
showAllWindowsAndActivate: function() {
|
||||
firetray.Window.showAllWindowsAndActivate = function() {
|
||||
let visibilityRate = firetray.Handler.visibleWindowsCount/firetray.Handler.windowsCount;
|
||||
log.debug("visibilityRate="+visibilityRate);
|
||||
if (visibilityRate < 1)
|
||||
@ -621,9 +612,9 @@ firetray.Window = {
|
||||
|
||||
for(var key in firetray.Handler.windows); // FIXME: this is not the proper way for finding the last registered window !
|
||||
firetray.Window.activate(key);
|
||||
},
|
||||
};
|
||||
|
||||
attachOnFocusInCallback: function(xid) {
|
||||
firetray.Window.attachOnFocusInCallback = function(xid) {
|
||||
log.debug("attachOnFocusInCallback xid="+xid);
|
||||
this.signals['focus-in'].callback[xid] =
|
||||
gtk.GCallbackWidgetFocusEvent_t(firetray.Window.onFocusIn);
|
||||
@ -631,20 +622,20 @@ firetray.Window = {
|
||||
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]);
|
||||
},
|
||||
};
|
||||
|
||||
detachOnFocusInCallback: function(xid) {
|
||||
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]);
|
||||
delete this.signals['focus-in'].callback[xid];
|
||||
delete this.signals['focus-in'].handler[xid];
|
||||
},
|
||||
};
|
||||
|
||||
// NOTE: fluxbox issues a FocusIn event when switching workspace
|
||||
// by hotkey, which means 2 FocusIn events when switching to a moz app :(
|
||||
// (http://sourceforge.net/tracker/index.php?func=detail&aid=3190205&group_id=35398&atid=413960)
|
||||
onFocusIn: function(widget, event, data) {
|
||||
firetray.Window.onFocusIn = function(widget, event, data) {
|
||||
log.debug("onFocusIn");
|
||||
let xid = firetray.Window.getXIDFromGtkWidget(widget);
|
||||
log.debug("xid="+xid);
|
||||
@ -654,9 +645,7 @@ firetray.Window = {
|
||||
if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) {
|
||||
firetray.Chat.stopGetAttentionMaybe(xid);
|
||||
}
|
||||
}
|
||||
|
||||
}; // firetray.Window
|
||||
};
|
||||
|
||||
|
||||
///////////////////////// firetray.Handler overriding /////////////////////////
|
||||
|
@ -1,5 +1,8 @@
|
||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
/* The tray icon for the main app. We need a hidden proxy window as (1) we want
|
||||
a unique icon, (2) the icon sends notifications to a single window. */
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "firetray" ];
|
||||
|
||||
const Cc = Components.classes;
|
||||
@ -17,6 +20,9 @@ Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
firetray.Handler.subscribeLibsForClosing([kernel32, shell32, user32]);
|
||||
|
||||
const kMessageTray = "_FIRETRAY_TrayMessage";
|
||||
const kMessageCallback = "_FIRETRAY_TrayCallback";
|
||||
|
||||
let log = firetray.Logging.getLogger("firetray.StatusIcon");
|
||||
|
||||
if ("undefined" == typeof(firetray.Handler))
|
||||
@ -27,7 +33,8 @@ firetray.StatusIcon = {
|
||||
initialized: false,
|
||||
callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
|
||||
notifyIconData: null,
|
||||
hwndHidden: null,
|
||||
msg: {WM_TASKBARCREATED:null, WM_TRAYMESSAGE:null, WM_TRAYCALLBACK:null},
|
||||
hwndProxy: null,
|
||||
WNDCLASS_NAME: "FireTrayHiddenWindowClass",
|
||||
WNDCLASS_ATOM: null,
|
||||
|
||||
@ -35,6 +42,7 @@ firetray.StatusIcon = {
|
||||
this.FILENAME_BLANK = firetray.Utils.chromeToPath(
|
||||
"chrome://firetray/skin/blank-icon.png");
|
||||
|
||||
this.registerMessages();
|
||||
this.create();
|
||||
|
||||
this.initialized = true;
|
||||
@ -49,8 +57,19 @@ firetray.StatusIcon = {
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
registerMessages: function() {
|
||||
this.msg.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
|
||||
this.msg.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray);
|
||||
this.msg.WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kMessageCallback);
|
||||
log.debug("WM_*="+this.msg.WM_TASKBARCREATED+" "+this.msg.WM_TRAYMESSAGE+" "+this.msg.WM_TRAYCALLBACK);
|
||||
},
|
||||
|
||||
unregisterMessages: function() {
|
||||
// FIXME: TODO:
|
||||
},
|
||||
|
||||
create: function() {
|
||||
let hwnd_hidden = this.createHiddenWindow();
|
||||
let hwnd_hidden = this.createProxyWindow();
|
||||
|
||||
// the Mozilla hidden window has the default Mozilla icon
|
||||
let hwnd_hidden_moz = user32.FindWindowW("MozillaHiddenWindowClass", null);
|
||||
@ -62,7 +81,7 @@ firetray.StatusIcon = {
|
||||
nid.szTip = firetray.Handler.appName;
|
||||
nid.hIcon = this.getIconFromWindow(hwnd_hidden_moz);
|
||||
nid.hWnd = hwnd_hidden;
|
||||
nid.uCallbackMessage = firetray.Win32.WM_TRAYMESSAGE;
|
||||
nid.uCallbackMessage = this.msg.WM_TRAYMESSAGE;
|
||||
nid.uFlags = shell32.NIF_ICON | shell32.NIF_MESSAGE | shell32.NIF_TIP;
|
||||
nid.uVersion = shell32.NOTIFYICON_VERSION_4;
|
||||
|
||||
@ -73,13 +92,13 @@ firetray.StatusIcon = {
|
||||
log.debug("Shell_NotifyIcon SETVERSION="+rv+" winLastError="+ctypes.winLastError);
|
||||
|
||||
this.notifyIconData = nid;
|
||||
this.hwndHidden = hwnd_hidden;
|
||||
this.hwndProxy = hwnd_hidden;
|
||||
},
|
||||
|
||||
createHiddenWindow: function() {
|
||||
createProxyWindow: function() {
|
||||
this.registerWindowClass();
|
||||
|
||||
this.callbacks.hiddenWinProc = user32.WNDPROC(firetray.StatusIcon.hiddenWindowProc);
|
||||
this.callbacks.hiddenWinProc = user32.WNDPROC(firetray.StatusIcon.proxyWindowProc);
|
||||
|
||||
let hwnd_hidden = user32.CreateWindowExW(
|
||||
0, win32.LPCTSTR(this.WNDCLASS_ATOM), // lpClassName can also be _T(WNDCLASS_NAME)
|
||||
@ -107,9 +126,31 @@ firetray.StatusIcon = {
|
||||
log.debug("WNDCLASS_ATOM="+this.WNDCLASS_ATOM);
|
||||
},
|
||||
|
||||
hiddenWindowProc: function(hWnd, uMsg, wParam, lParam) {
|
||||
log.debug("HiddenWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
||||
// ... do something smart with this event!
|
||||
proxyWindowProc: function(hWnd, uMsg, wParam, lParam) {
|
||||
// log.debug("ProxyWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
||||
|
||||
if (uMsg === firetray.StatusIcon.msg.WM_TASKBARCREATED) {
|
||||
log.info("____________TASKBARCREATED");
|
||||
|
||||
} else if (uMsg === firetray.StatusIcon.msg.WM_TRAYMESSAGE) {
|
||||
|
||||
switch (+lParam) {
|
||||
case win32.WM_LBUTTONUP:
|
||||
log.debug("WM_LBUTTONUP");
|
||||
break;
|
||||
case win32.WM_RBUTTONUP:
|
||||
log.debug("WM_RBUTTONUP");
|
||||
break;
|
||||
case win32.WM_CONTEXTMENU:
|
||||
log.debug("WM_CONTEXTMENU");
|
||||
break;
|
||||
case win32.NIN_KEYSELECT:
|
||||
log.debug("NIN_KEYSELECT");
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
},
|
||||
@ -138,8 +179,8 @@ firetray.StatusIcon = {
|
||||
return icon;
|
||||
},
|
||||
|
||||
destroyHiddenWindow: function() {
|
||||
let rv = user32.DestroyWindow(this.hwndHidden);
|
||||
destroyProxyWindow: function() {
|
||||
let rv = user32.DestroyWindow(this.hwndProxy);
|
||||
|
||||
rv = this.unregisterWindowClass();
|
||||
log.debug("Hidden window removed");
|
||||
@ -152,7 +193,7 @@ firetray.StatusIcon = {
|
||||
destroy: function() {
|
||||
let rv = shell32.Shell_NotifyIconW(shell32.NIM_DELETE, this.notifyIconData.address());
|
||||
log.debug("Shell_NotifyIcon DELETE="+rv+" winLastError="+ctypes.winLastError);
|
||||
this.destroyHiddenWindow();
|
||||
this.destroyProxyWindow();
|
||||
}
|
||||
|
||||
}; // firetray.StatusIcon
|
||||
|
@ -18,16 +18,7 @@ let log = firetray.Logging.getLogger("firetray.Win32");
|
||||
if ("undefined" == typeof(firetray.Handler))
|
||||
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||
|
||||
const kMessageTray = "_FIRETRAY_TrayMessage";
|
||||
const kMessageCallback = "_FIRETRAY_TrayCallback";
|
||||
|
||||
function Win32Env() {
|
||||
this.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
|
||||
// We register this as well, as we cannot know which WM_USER values are
|
||||
// already taken
|
||||
this.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray);
|
||||
this.WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kMessageCallback);
|
||||
log.debug("WM_*="+this.WM_TASKBARCREATED+" "+this.WM_TRAYMESSAGE+" "+this.WM_TRAYCALLBACK);
|
||||
|
||||
this.hInstance = kernel32.GetModuleHandleW("xul"); // ordinary windows are created from xul.dll
|
||||
log.debug("hInstance="+this.hInstance);
|
||||
|
@ -13,6 +13,7 @@ Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
||||
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
||||
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
||||
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
firetray.Handler.subscribeLibsForClosing([user32]);
|
||||
|
||||
@ -32,47 +33,42 @@ XPCOMUtils.defineLazyServiceGetter(
|
||||
const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
|
||||
const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
||||
|
||||
// // NOTE: storing ctypes pointers into a JS object doesn't work: pointers are
|
||||
// // "evolving" after a while (maybe due to back and forth conversion). So we
|
||||
// // need to store them into a real ctypes array !
|
||||
// firetray.Handler.gtkWindows = new ctypesMap(gtk.GtkWindow.ptr),
|
||||
|
||||
firetray.Window = new FiretrayWindow();
|
||||
|
||||
firetray.Window = {
|
||||
signals: {'focus-in': {callback: {}, handler: {}}},
|
||||
|
||||
init: function() {
|
||||
firetray.Window.init = function() {
|
||||
this.initialized = true;
|
||||
},
|
||||
};
|
||||
|
||||
shutdown: function() {
|
||||
firetray.Window.shutdown = function() {
|
||||
this.initialized = false;
|
||||
},
|
||||
};
|
||||
|
||||
show: function(xid) {
|
||||
firetray.Window.show = function(xid) {
|
||||
log.debug("show xid="+xid);
|
||||
},
|
||||
};
|
||||
|
||||
hide: function(xid) {
|
||||
firetray.Window.hide = function(xid) {
|
||||
log.debug("hide");
|
||||
},
|
||||
};
|
||||
|
||||
startupHide: function(xid) {
|
||||
firetray.Window.startupHide = function(xid) {
|
||||
log.debug('startupHide: '+xid);
|
||||
},
|
||||
};
|
||||
|
||||
setVisibility: function(xid, visibility) {
|
||||
},
|
||||
|
||||
}; // firetray.Window
|
||||
firetray.Window.setVisibility = function(xid, visibility) {
|
||||
};
|
||||
|
||||
|
||||
///////////////////////// firetray.Handler overriding /////////////////////////
|
||||
|
||||
/** debug facility */
|
||||
firetray.Handler.dumpWindows = function() {
|
||||
log.debug(firetray.Handler.windowsCount);
|
||||
for (let winId in firetray.Handler.windows) log.info(winId+"="+firetray.Handler.gtkWindows.get(winId));
|
||||
let dumpStr = ""+firetray.Handler.windowsCount;
|
||||
for (let wid in firetray.Handler.windows) {
|
||||
dumpStr += " 0x"+wid;
|
||||
}
|
||||
log.info(dumpStr);
|
||||
};
|
||||
|
||||
firetray.Handler.getWindowIdFromChromeWindow = firetray.Window.getXIDFromChromeWindow;
|
||||
@ -85,38 +81,33 @@ firetray.Handler.registerWindow = function(win) {
|
||||
let hwnd = nativeHandle ?
|
||||
new ctypes.voidptr_t(ctypes.UInt64(nativeHandle)) :
|
||||
user32.FindWindowW("MozillaWindowClass", win.document.title);
|
||||
log.debug("=== hwnd="+hwnd);
|
||||
// wid will be used as a string most of the time (through f.Handler.windows mainly)
|
||||
let wid = ctypes.cast(hwnd, ctypes.uintptr_t).value.toString(16);
|
||||
log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title);
|
||||
|
||||
if (this.windows.hasOwnProperty(wid)) {
|
||||
let msg = "Window ("+wid+") already registered.";
|
||||
log.error(msg);
|
||||
Cu.reportError(msg);
|
||||
return false;
|
||||
}
|
||||
this.windows[wid] = {};
|
||||
this.windows[wid].chromeWin = win;
|
||||
this.windows[wid].baseWin = baseWin;
|
||||
|
||||
// SetupWnd(hwnd);
|
||||
// ::SetPropW(hwnd, kIconData, reinterpret_cast<HANDLE>(iconData));
|
||||
// ::SetPropW(hwnd, kIconMouseEventProc, reinterpret_cast<HANDLE>(callback));
|
||||
// ::SetPropW(hwnd, kIcon, reinterpret_cast<HANDLE>(0x1));
|
||||
|
||||
return;
|
||||
|
||||
// register
|
||||
let [whndbaseWin, gtkWin, gdkWin, xid] = firetray.Window.getWindowsFromChromeWindow(win);
|
||||
this.windows[xid] = {};
|
||||
this.windows[xid].chromeWin = win;
|
||||
this.windows[xid].baseWin = baseWin;
|
||||
firetray.Window.checkSubscribedEventMasks(xid);
|
||||
try {
|
||||
this.gtkWindows.insert(xid, gtkWin);
|
||||
this.gdkWindows.insert(xid, gdkWin);
|
||||
firetray.PopupMenu.addWindowItem(xid);
|
||||
} catch (x) {
|
||||
if (x.name === "RangeError") // instanceof not working :-(
|
||||
win.alert(x+"\n\nYou seem to have more than "+FIRETRAY_WINDOW_COUNT_MAX
|
||||
+" windows open. This breaks FireTray and most probably "
|
||||
+firetray.Handler.appName+".");
|
||||
}
|
||||
this.windowsCount += 1;
|
||||
// NOTE: no need to check for window state to set visibility because all
|
||||
// windows *are* shown at startup
|
||||
firetray.Window.updateVisibility(xid, true);
|
||||
log.debug("window "+xid+" registered");
|
||||
firetray.Window.updateVisibility(wid, true);
|
||||
log.debug("window 0x"+wid+" registered");
|
||||
// NOTE: shouldn't be necessary to gtk_widget_add_events(gtkWin, gdk.GDK_ALL_EVENTS_MASK);
|
||||
|
||||
/*
|
||||
try {
|
||||
// NOTE: we could try to catch the "delete-event" here and block
|
||||
// delete_event_cb (in gtk2/nsWindow.cpp), but we prefer to use the
|
||||
@ -139,9 +130,10 @@ firetray.Handler.registerWindow = function(win) {
|
||||
log.error(x);
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
log.debug("AFTER"); firetray.Handler.dumpWindows();
|
||||
return xid;
|
||||
return wid;
|
||||
};
|
||||
|
||||
firetray.Handler.unregisterWindow = function(win) {
|
||||
|
Loading…
Reference in New Issue
Block a user