2013-11-16 09:39:57 -05:00
|
|
|
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
|
|
|
|
var EXPORTED_SYMBOLS = [ "firetray" ];
|
|
|
|
|
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cu = Components.utils;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
|
|
|
Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
2013-11-17 17:11:17 -05:00
|
|
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
2013-11-16 09:39:57 -05:00
|
|
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
2013-11-22 17:05:43 -05:00
|
|
|
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
2013-11-16 09:39:57 -05:00
|
|
|
Cu.import("resource://firetray/commons.js");
|
2013-11-22 17:05:43 -05:00
|
|
|
firetray.Handler.subscribeLibsForClosing([user32]);
|
2013-11-16 09:39:57 -05:00
|
|
|
|
|
|
|
let log = firetray.Logging.getLogger("firetray.Window");
|
|
|
|
|
|
|
|
if ("undefined" == typeof(firetray.Handler))
|
|
|
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
|
|
|
|
|
|
|
const Services2 = {};
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(
|
|
|
|
Services2,
|
|
|
|
"uuid",
|
|
|
|
"@mozilla.org/uuid-generator;1",
|
|
|
|
"nsIUUIDGenerator"
|
|
|
|
);
|
|
|
|
|
|
|
|
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 = {
|
|
|
|
signals: {'focus-in': {callback: {}, handler: {}}},
|
|
|
|
|
|
|
|
init: function() {
|
|
|
|
this.initialized = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
shutdown: function() {
|
|
|
|
this.initialized = false;
|
|
|
|
},
|
|
|
|
|
|
|
|
show: function(xid) {
|
|
|
|
log.debug("show xid="+xid);
|
|
|
|
},
|
|
|
|
|
|
|
|
hide: function(xid) {
|
|
|
|
log.debug("hide");
|
|
|
|
},
|
|
|
|
|
|
|
|
startupHide: function(xid) {
|
|
|
|
log.debug('startupHide: '+xid);
|
|
|
|
},
|
|
|
|
|
|
|
|
setVisibility: function(xid, visibility) {
|
|
|
|
},
|
|
|
|
|
|
|
|
}; // firetray.Window
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////// 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));
|
|
|
|
};
|
|
|
|
|
|
|
|
firetray.Handler.getWindowIdFromChromeWindow = firetray.Window.getXIDFromChromeWindow;
|
|
|
|
|
|
|
|
firetray.Handler.registerWindow = function(win) {
|
|
|
|
log.debug("register window");
|
|
|
|
|
|
|
|
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
2013-11-17 17:11:17 -05:00
|
|
|
let nativeHandle = baseWin.nativeHandle;
|
|
|
|
let hwnd = nativeHandle ?
|
|
|
|
new ctypes.voidptr_t(ctypes.UInt64(nativeHandle)) :
|
|
|
|
user32.FindWindowW("MozillaWindowClass", win.document.title);
|
|
|
|
log.debug("=== hwnd="+hwnd);
|
|
|
|
|
2013-11-16 09:39:57 -05:00
|
|
|
// 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");
|
|
|
|
// 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
|
|
|
|
// provided 'close' JS event
|
|
|
|
|
|
|
|
this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t(firetray.Window.filterWindow);
|
|
|
|
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);
|
|
|
|
gdk.gdk_window_add_filter(gdkWin, this.windows[xid].startupFilterCb, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
firetray.Window.attachOnFocusInCallback(xid);
|
|
|
|
if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) {
|
|
|
|
firetray.Chat.attachSelectListeners(win);
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (x) {
|
|
|
|
firetray.Window.unregisterWindowByXID(xid);
|
|
|
|
log.error(x);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
log.debug("AFTER"); firetray.Handler.dumpWindows();
|
|
|
|
return xid;
|
|
|
|
};
|
|
|
|
|
|
|
|
firetray.Handler.unregisterWindow = function(win) {
|
|
|
|
log.debug("unregister window");
|
|
|
|
let xid = firetray.Window.getXIDFromChromeWindow(win);
|
|
|
|
return firetray.Window.unregisterWindowByXID(xid);
|
|
|
|
};
|
|
|
|
|
|
|
|
firetray.Handler.showWindow = firetray.Window.show;
|
|
|
|
firetray.Handler.hideWindow = firetray.Window.hide;
|
|
|
|
|
|
|
|
firetray.Handler.showHideAllWindows = function(gtkStatusIcon, userData) {
|
|
|
|
log.debug("showHideAllWindows: "+userData);
|
|
|
|
// NOTE: showHideAllWindows being a callback, we need to use
|
|
|
|
// 'firetray.Handler' explicitely instead of 'this'
|
|
|
|
|
|
|
|
log.debug("visibleWindowsCount="+firetray.Handler.visibleWindowsCount);
|
|
|
|
log.debug("windowsCount="+firetray.Handler.windowsCount);
|
|
|
|
let visibilityRate = firetray.Handler.visibleWindowsCount/firetray.Handler.windowsCount;
|
|
|
|
log.debug("visibilityRate="+visibilityRate);
|
|
|
|
if ((0.5 < visibilityRate) && (visibilityRate < 1)
|
|
|
|
|| visibilityRate === 0) { // TODO: should be configurable
|
|
|
|
firetray.Handler.showAllWindows();
|
|
|
|
} else {
|
|
|
|
firetray.Handler.hideAllWindows();
|
|
|
|
}
|
|
|
|
|
|
|
|
let stopPropagation = true;
|
|
|
|
return stopPropagation;
|
|
|
|
};
|