2011-12-16 22:15:02 -05:00
|
|
|
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
|
|
|
|
/* GdkWindow and GtkWindow are totally different things. A GtkWindow is a
|
|
|
|
"standalone" window. A GdkWindow is just a region on the screen that can
|
|
|
|
capture events and has certain attributes (such as a cursor, and a coordinate
|
|
|
|
system). Basically a GdkWindow is an X window, in the Xlib sense, and
|
|
|
|
GtkWindow is a widget used for a particular UI effect.
|
|
|
|
(http://mail.gnome.org/archives/gtk-app-devel-list/1999-January/msg00138.html) */
|
|
|
|
|
|
|
|
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");
|
2012-01-02 12:35:02 -05:00
|
|
|
Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
2012-02-09 09:39:33 -05:00
|
|
|
Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
|
|
|
|
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");
|
2011-12-16 22:15:02 -05:00
|
|
|
Cu.import("resource://firetray/commons.js");
|
2012-08-07 17:37:32 -04:00
|
|
|
firetray.Handler.subscribeLibsForClosing([gobject, gdk, gtk, libc, x11, glib]);
|
2011-12-16 22:15:02 -05:00
|
|
|
|
2012-01-07 10:06:10 -05:00
|
|
|
if ("undefined" == typeof(firetray.Handler))
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR("This module MUST be imported from/after FiretrayHandler !");
|
2012-01-07 10:06:10 -05:00
|
|
|
|
2011-12-16 22:15:02 -05:00
|
|
|
const Services2 = {};
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(
|
|
|
|
Services2,
|
|
|
|
"uuid",
|
|
|
|
"@mozilla.org/uuid-generator;1",
|
|
|
|
"nsIUUIDGenerator"
|
|
|
|
);
|
|
|
|
|
2012-01-07 10:06:10 -05:00
|
|
|
const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
|
|
|
|
const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
2011-12-16 22:15:02 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* custum type used to pass data in to and out of findGtkWindowByTitleCb
|
|
|
|
*/
|
|
|
|
var _find_data_t = ctypes.StructType("_find_data_t", [
|
|
|
|
{ inTitle: ctypes.char.ptr },
|
|
|
|
{ outWindow: gtk.GtkWindow.ptr }
|
|
|
|
]);
|
|
|
|
|
2012-01-22 22:04:05 -05:00
|
|
|
// 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.Handler.gdkWindows = new ctypesMap(gdk.GdkWindow.ptr),
|
|
|
|
firetray.Handler.gtkPopupMenuWindowItems = new ctypesMap(gtk.GtkImageMenuItem.ptr),
|
|
|
|
|
2011-12-16 22:15:02 -05:00
|
|
|
|
|
|
|
firetray.Window = {
|
|
|
|
|
2012-01-15 14:47:47 -05:00
|
|
|
init: function() {
|
|
|
|
this.initialized = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
shutdown: function() {
|
|
|
|
this.initialized = false;
|
|
|
|
},
|
|
|
|
|
2011-12-16 22:15:02 -05:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
* @param window nsIDOMWindow from Services.wm
|
|
|
|
* @return a gtk.GtkWindow.ptr
|
|
|
|
*/
|
2012-07-26 20:12:20 -04:00
|
|
|
getGtkWindowFromChromeWindow: function(window) {
|
2011-12-16 22:15:02 -05:00
|
|
|
let baseWindow = window
|
2011-12-31 19:45:48 -05:00
|
|
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Ci.nsIWebNavigation)
|
|
|
|
.QueryInterface(Ci.nsIBaseWindow);
|
2011-12-16 22:15:02 -05:00
|
|
|
|
|
|
|
// Tag the base window
|
|
|
|
let oldTitle = baseWindow.title;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("oldTitle="+oldTitle);
|
2011-12-16 22:15:02 -05:00
|
|
|
baseWindow.title = Services2.uuid.generateUUID().toString();
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Search the window by the *temporary* title
|
|
|
|
let widgets = gtk.gtk_window_list_toplevels();
|
|
|
|
let that = this;
|
|
|
|
let findGtkWindowByTitleCb = gobject.GFunc_t(that._findGtkWindowByTitle);
|
|
|
|
var userData = new _find_data_t(
|
|
|
|
ctypes.char.array()(baseWindow.title),
|
|
|
|
null
|
|
|
|
).address();
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("userData="+userData);
|
2011-12-16 22:15:02 -05:00
|
|
|
gobject.g_list_foreach(widgets, findGtkWindowByTitleCb, userData);
|
|
|
|
gobject.g_list_free(widgets);
|
|
|
|
|
2012-06-13 16:24:07 -04:00
|
|
|
if (userData.contents.outWindow.isNull())
|
2011-12-16 22:15:02 -05:00
|
|
|
throw new Error("Window not found!");
|
2012-06-13 16:24:07 -04:00
|
|
|
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("found window: "+userData.contents.outWindow);
|
2011-12-16 22:15:02 -05:00
|
|
|
} catch (x) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR(x);
|
2011-12-16 22:15:02 -05:00
|
|
|
} finally {
|
|
|
|
// Restore
|
|
|
|
baseWindow.title = oldTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
let data = ctypes.cast(userData, _find_data_t.ptr);
|
|
|
|
let inTitle = data.contents.inTitle;
|
|
|
|
|
|
|
|
let gtkWin = ctypes.cast(gtkWidget, gtk.GtkWindow.ptr);
|
|
|
|
let winTitle = gtk.gtk_window_get_title(gtkWin);
|
|
|
|
|
2011-12-31 19:45:48 -05:00
|
|
|
if (!winTitle.isNull()) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG(inTitle+" = "+winTitle);
|
2011-12-31 19:45:48 -05:00
|
|
|
if (libc.strcmp(inTitle, winTitle) == 0)
|
|
|
|
data.contents.outWindow = gtkWin;
|
2011-12-16 22:15:02 -05:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
getGdkWindowFromGtkWindow: function(gtkWin) {
|
|
|
|
try {
|
|
|
|
let gtkWid = ctypes.cast(gtkWin, gtk.GtkWidget.ptr);
|
2011-12-18 13:39:56 -05:00
|
|
|
return gtk.gtk_widget_get_window(gtkWid);
|
2011-12-16 22:15:02 -05:00
|
|
|
} catch (x) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR(x);
|
2011-12-16 22:15:02 -05:00
|
|
|
}
|
2011-12-18 13:39:56 -05:00
|
|
|
return null;
|
2011-12-16 22:15:02 -05:00
|
|
|
},
|
|
|
|
|
2011-12-18 13:39:56 -05:00
|
|
|
getXIDFromGdkWindow: function(gdkWin) {
|
|
|
|
return gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
|
|
|
|
},
|
|
|
|
|
2011-12-22 11:19:59 -05:00
|
|
|
getXIDFromGtkWidget: function(gtkWid) {
|
|
|
|
try {
|
|
|
|
let gdkWin = gtk.gtk_widget_get_window(gtkWid);
|
|
|
|
return gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
|
|
|
|
} catch (x) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR(x);
|
2011-12-22 11:19:59 -05:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
2012-07-26 20:12:20 -04:00
|
|
|
addrPointedByInHex: function(ptr) {
|
|
|
|
return "0x"+ctypes.cast(ptr, ctypes.uintptr_t.ptr).contents.toString(16);
|
|
|
|
},
|
|
|
|
|
|
|
|
getGdkWindowFromNativeHandle: function(nativeHandle) {
|
|
|
|
let gdkw = new gdk.GdkWindow.ptr(ctypes.UInt64(nativeHandle)); // a new pointer to the GdkWindow
|
|
|
|
F.LOG("gdkw="+gdkw+" *gdkw="+this.addrPointedByInHex(gdkw));
|
|
|
|
return gdkw;
|
|
|
|
},
|
|
|
|
|
|
|
|
getGtkWindowFromGdkWindow: function(gdkWin) {
|
|
|
|
let gptr = new gobject.gpointer;
|
|
|
|
gdk.gdk_window_get_user_data(gdkWin, gptr.address());
|
|
|
|
F.LOG("gptr="+gptr+" *gptr="+this.addrPointedByInHex(gptr));
|
|
|
|
let gtkw = ctypes.cast(gptr, gtk.GtkWindow.ptr);
|
|
|
|
let gtkw_voidp = ctypes.cast(gtkw, ctypes.void_t.ptr);
|
|
|
|
let gtkwid_top = gtk.gtk_widget_get_toplevel(ctypes.cast(gtkw, gtk.GtkWidget.ptr));
|
|
|
|
gtkw = ctypes.cast(gtkwid_top, gtk.GtkWindow.ptr);
|
|
|
|
F.LOG("gtkw="+gtkw+" *gtkw="+this.addrPointedByInHex(gtkw));
|
|
|
|
return gtkw;
|
|
|
|
},
|
|
|
|
|
2012-06-13 16:24:07 -04:00
|
|
|
/* consider using getXIDFromChromeWindow() if you only need the XID */
|
2011-12-18 13:39:56 -05:00
|
|
|
getWindowsFromChromeWindow: function(win) {
|
2012-07-26 20:12:20 -04:00
|
|
|
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
|
|
|
let nativeHandle = baseWin.nativeHandle; // Moz' private pointer to the GdkWindow
|
|
|
|
F.LOG("nativeHandle="+nativeHandle);
|
|
|
|
let gtkWin, gdkWin;
|
|
|
|
if (nativeHandle) { // Gecko 17+
|
|
|
|
gdkWin = firetray.Window.getGdkWindowFromNativeHandle(nativeHandle);
|
|
|
|
gtkWin = firetray.Window.getGtkWindowFromGdkWindow(gdkWin);
|
|
|
|
} else {
|
|
|
|
gtkWin = firetray.Window.getGtkWindowFromChromeWindow(win);
|
|
|
|
gdkWin = firetray.Window.getGdkWindowFromGtkWindow(gtkWin);
|
|
|
|
}
|
2011-12-18 13:39:56 -05:00
|
|
|
let xid = firetray.Window.getXIDFromGdkWindow(gdkWin);
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("XID="+xid);
|
2012-07-26 20:12:20 -04:00
|
|
|
return [baseWin, gtkWin, gdkWin, xid];
|
2011-12-16 22:15:02 -05:00
|
|
|
},
|
|
|
|
|
2011-12-23 10:44:09 -05:00
|
|
|
getXIDFromChromeWindow: function(win) {
|
|
|
|
for (let xid in firetray.Handler.windows)
|
2012-01-01 11:30:51 -05:00
|
|
|
if (firetray.Handler.windows[xid].chromeWin === win)
|
2011-12-23 10:44:09 -05:00
|
|
|
return xid;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR("unknown window while lookup");
|
2011-12-23 10:44:09 -05:00
|
|
|
return null;
|
|
|
|
},
|
2011-12-22 11:19:59 -05:00
|
|
|
|
2012-01-21 03:14:03 -05:00
|
|
|
unregisterWindowByXID: function(xid) {
|
|
|
|
firetray.Handler.windowsCount -= 1;
|
2012-04-11 07:45:45 -04:00
|
|
|
if (firetray.Handler.windows[xid].visible) firetray.Handler.visibleWindowsCount -= 1;
|
2012-01-21 03:14:03 -05:00
|
|
|
if (firetray.Handler.windows.hasOwnProperty(xid)) {
|
|
|
|
if (!delete firetray.Handler.windows[xid])
|
|
|
|
throw new DeleteError();
|
|
|
|
firetray.Handler.gtkWindows.remove(xid);
|
|
|
|
firetray.Handler.gdkWindows.remove(xid);
|
2012-01-22 22:04:05 -05:00
|
|
|
firetray.PopupMenu.removeWindowItem(xid);
|
2012-01-21 03:14:03 -05:00
|
|
|
} else {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR("can't unregister unknown window "+xid);
|
2012-01-21 03:14:03 -05:00
|
|
|
return false;
|
|
|
|
}
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("window "+xid+" unregistered");
|
2012-01-21 03:14:03 -05:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
2012-05-12 09:24:14 -04:00
|
|
|
show: function(xid) {
|
|
|
|
F.LOG("show xid="+xid);
|
2012-02-13 17:55:01 -05:00
|
|
|
|
|
|
|
// try to restore previous state. TODO: z-order respected ?
|
|
|
|
firetray.Window.restorePositionAndSize(xid);
|
|
|
|
firetray.Window.restoreStates(xid);
|
2012-02-20 09:34:51 -05:00
|
|
|
|
2012-05-12 09:42:55 -04:00
|
|
|
// better visual effect if visibility set after restorePosition, but some
|
|
|
|
// WMs like compiz seem not to honor position setting if window not visible
|
2012-02-20 09:34:51 -05:00
|
|
|
firetray.Window.setVisibility(xid, true);
|
|
|
|
|
2012-03-06 17:28:52 -05:00
|
|
|
// after show
|
|
|
|
firetray.Window.restoreDesktop(xid);
|
2012-05-12 10:36:51 -04:00
|
|
|
if (firetray.Utils.prefService.getBoolPref('show_activates'))
|
|
|
|
firetray.Window.activate(xid);
|
2012-02-13 17:55:01 -05:00
|
|
|
|
2012-07-23 20:00:44 -04:00
|
|
|
firetray.PopupMenu.hideWindowItemAndSeparatorMaybe(xid);
|
2012-02-13 17:55:01 -05:00
|
|
|
firetray.Handler.showHideIcon();
|
|
|
|
},
|
|
|
|
|
|
|
|
/* FIXME: hiding windows should also hide child windows */
|
2012-05-12 09:24:14 -04:00
|
|
|
hide: function(xid) {
|
|
|
|
F.LOG("hide");
|
2012-02-13 17:55:01 -05:00
|
|
|
|
|
|
|
firetray.Window.savePositionAndSize(xid);
|
|
|
|
firetray.Window.saveStates(xid);
|
|
|
|
firetray.Window.saveDesktop(xid);
|
|
|
|
|
2012-02-19 09:36:16 -05:00
|
|
|
firetray.Window.setVisibility(xid, false);
|
2012-02-13 17:55:01 -05:00
|
|
|
|
2012-07-23 20:00:44 -04:00
|
|
|
firetray.PopupMenu.showWindowItem(xid);
|
|
|
|
firetray.Handler.showHideIcon();
|
|
|
|
},
|
|
|
|
|
|
|
|
startupHide: function(xid) {
|
|
|
|
F.LOG('startupHide: '+xid);
|
|
|
|
|
|
|
|
firetray.Handler.windows[xid].baseWin.visibility = false;
|
|
|
|
firetray.Handler.windows[xid].visible = false;
|
|
|
|
firetray.Handler.visibleWindowsCount -= 1;
|
|
|
|
|
|
|
|
firetray.PopupMenu.showWindowItem(xid);
|
2012-02-13 17:55:01 -05:00
|
|
|
firetray.Handler.showHideIcon();
|
|
|
|
},
|
|
|
|
|
|
|
|
savePositionAndSize: function(xid) {
|
2012-01-01 11:30:51 -05:00
|
|
|
let gx = {}, gy = {}, gwidth = {}, gheight = {};
|
|
|
|
firetray.Handler.windows[xid].baseWin.getPositionAndSize(gx, gy, gwidth, gheight);
|
|
|
|
firetray.Handler.windows[xid].savedX = gx.value;
|
|
|
|
firetray.Handler.windows[xid].savedY = gy.value;
|
|
|
|
firetray.Handler.windows[xid].savedWidth = gwidth.value;
|
|
|
|
firetray.Handler.windows[xid].savedHeight = gheight.value;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("save: gx="+gx.value+", gy="+gy.value+", gwidth="+gwidth.value+", gheight="+gheight.value);
|
2011-12-22 11:19:59 -05:00
|
|
|
},
|
|
|
|
|
2012-02-13 17:55:01 -05:00
|
|
|
restorePositionAndSize: function(xid) {
|
2012-02-04 08:18:20 -05:00
|
|
|
if ("undefined" === typeof(firetray.Handler.windows[xid].savedX))
|
2011-12-22 11:19:59 -05:00
|
|
|
return; // windows[xid].saved* may not be initialized
|
|
|
|
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("restore: x="+firetray.Handler.windows[xid].savedX+", y="+firetray.Handler.windows[xid].savedY+", w="+firetray.Handler.windows[xid].savedWidth+", h="+firetray.Handler.windows[xid].savedHeight);
|
2012-01-01 11:30:51 -05:00
|
|
|
firetray.Handler.windows[xid].baseWin.setPositionAndSize(
|
|
|
|
firetray.Handler.windows[xid].savedX,
|
|
|
|
firetray.Handler.windows[xid].savedY,
|
|
|
|
firetray.Handler.windows[xid].savedWidth,
|
|
|
|
firetray.Handler.windows[xid].savedHeight,
|
|
|
|
false); // repaint
|
2012-01-09 16:13:27 -05:00
|
|
|
|
|
|
|
['savedX', 'savedX', 'savedWidth', 'savedHeight'].forEach(function(element, index, array) {
|
|
|
|
delete firetray.Handler.windows[xid][element];
|
|
|
|
});
|
2012-01-01 11:30:51 -05:00
|
|
|
},
|
|
|
|
|
2012-02-13 17:55:01 -05:00
|
|
|
saveStates: function(xid) {
|
2012-01-07 10:06:10 -05:00
|
|
|
let winStates = firetray.Window.getXWindowStates(x11.Window(xid));
|
2012-01-09 16:13:27 -05:00
|
|
|
firetray.Handler.windows[xid].savedStates = winStates;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("save: windowStates="+winStates);
|
2012-01-01 11:30:51 -05:00
|
|
|
},
|
|
|
|
|
2012-02-13 17:55:01 -05:00
|
|
|
restoreStates: function(xid) {
|
2012-01-09 16:13:27 -05:00
|
|
|
let winStates = firetray.Handler.windows[xid].savedStates;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("restored WindowStates: " + winStates);
|
2012-01-07 10:06:10 -05:00
|
|
|
if (winStates & FIRETRAY_XWINDOW_MAXIMIZED) {
|
2012-01-01 11:30:51 -05:00
|
|
|
firetray.Handler.windows[xid].chromeWin.maximize();
|
2012-04-17 18:51:50 -04:00
|
|
|
F.LOG("restored maximized");
|
2012-01-07 10:06:10 -05:00
|
|
|
}
|
|
|
|
let hides_on_minimize = firetray.Utils.prefService.getBoolPref('hides_on_minimize');
|
|
|
|
if (!hides_on_minimize && (winStates & FIRETRAY_XWINDOW_HIDDEN)) {
|
2012-01-01 11:30:51 -05:00
|
|
|
firetray.Handler.windows[xid].chromeWin.minimize();
|
2012-04-17 18:51:50 -04:00
|
|
|
F.LOG("restored minimized");
|
2012-01-01 11:30:51 -05:00
|
|
|
}
|
2012-01-09 16:13:27 -05:00
|
|
|
|
|
|
|
delete firetray.Handler.windows[xid].savedStates;
|
|
|
|
},
|
|
|
|
|
2012-02-13 17:55:01 -05:00
|
|
|
saveDesktop: function(xid) {
|
2012-03-04 17:41:01 -05:00
|
|
|
if (!firetray.Utils.prefService.getBoolPref('remember_desktop'))
|
|
|
|
return;
|
|
|
|
|
2012-01-09 16:13:27 -05:00
|
|
|
let winDesktop = firetray.Window.getXWindowDesktop(x11.Window(xid));
|
|
|
|
firetray.Handler.windows[xid].savedDesktop = winDesktop;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("save: windowDesktop="+winDesktop);
|
2012-01-09 16:13:27 -05:00
|
|
|
},
|
|
|
|
|
2012-02-13 17:55:01 -05:00
|
|
|
restoreDesktop: function(xid) {
|
2012-03-04 17:41:01 -05:00
|
|
|
if (!firetray.Utils.prefService.getBoolPref('remember_desktop'))
|
|
|
|
return;
|
|
|
|
|
2012-01-09 16:13:27 -05:00
|
|
|
let desktopDest = firetray.Handler.windows[xid].savedDesktop;
|
2012-02-13 17:55:01 -05:00
|
|
|
if (desktopDest === null || "undefined" === typeof(desktopDest)) return;
|
2012-01-09 16:13:27 -05:00
|
|
|
|
2012-02-03 19:15:36 -05:00
|
|
|
let dataSize = 1;
|
|
|
|
let data = ctypes.long(dataSize);
|
|
|
|
data[0] = desktopDest;
|
|
|
|
this.xSendClientMessgeEvent(xid, x11.current.Atoms._NET_WM_DESKTOP, data, dataSize);
|
|
|
|
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("restored to desktop: "+desktopDest);
|
2012-02-03 19:15:36 -05:00
|
|
|
delete firetray.Handler.windows[xid].savedDesktop;
|
|
|
|
},
|
|
|
|
|
2012-02-19 09:36:16 -05:00
|
|
|
setVisibility: function(xid, visibility) {
|
2012-05-12 09:24:14 -04:00
|
|
|
F.LOG("setVisibility="+visibility);
|
2012-04-22 18:32:01 -04:00
|
|
|
let gtkWidget = ctypes.cast(firetray.Handler.gtkWindows.get(xid), gtk.GtkWidget.ptr);
|
|
|
|
if (visibility)
|
|
|
|
gtk.gtk_widget_show_all(gtkWidget);
|
|
|
|
else
|
|
|
|
gtk.gtk_widget_hide(gtkWidget);
|
|
|
|
|
2012-04-11 07:45:45 -04:00
|
|
|
firetray.Handler.windows[xid].visible = visibility;
|
2012-02-19 09:36:16 -05:00
|
|
|
firetray.Handler.visibleWindowsCount = visibility ?
|
|
|
|
firetray.Handler.visibleWindowsCount + 1 :
|
|
|
|
firetray.Handler.visibleWindowsCount - 1 ;
|
|
|
|
},
|
|
|
|
|
2012-02-03 19:15:36 -05:00
|
|
|
xSendClientMessgeEvent: function(xid, atom, data, dataSize) {
|
2012-01-09 16:13:27 -05:00
|
|
|
let xev = new x11.XClientMessageEvent;
|
|
|
|
xev.type = x11.ClientMessage;
|
|
|
|
xev.window = x11.Window(xid);
|
2012-02-03 19:15:36 -05:00
|
|
|
xev.message_type = atom;
|
2012-01-09 16:13:27 -05:00
|
|
|
xev.format = 32;
|
2012-02-03 19:15:36 -05:00
|
|
|
for (let i=0; i<dataSize; ++i)
|
|
|
|
xev.data[i] = data[i];
|
2012-01-09 16:13:27 -05:00
|
|
|
|
|
|
|
let rootWin = x11.XDefaultRootWindow(x11.current.Display);
|
|
|
|
let propagate = false;
|
|
|
|
let mask = ctypes.long(x11.SubstructureNotifyMask|x11.SubstructureRedirectMask);
|
|
|
|
// 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)
|
2011-12-22 11:19:59 -05:00
|
|
|
},
|
|
|
|
|
2012-02-03 19:15:36 -05:00
|
|
|
/**
|
|
|
|
* raises window on top and give focus.
|
|
|
|
*/
|
|
|
|
activate: function(xid) {
|
2012-03-07 08:41:05 -05:00
|
|
|
gtk.gtk_window_present(firetray.Handler.gtkWindows.get(xid));
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("window raised");
|
2012-01-01 16:31:16 -05:00
|
|
|
},
|
|
|
|
|
2012-01-07 10:06:10 -05:00
|
|
|
/**
|
2012-01-09 16:13:27 -05:00
|
|
|
* YOU MUST x11.XFree() THE VARIABLE RETURNED BY THIS FUNCTION
|
2012-01-07 10:06:10 -05:00
|
|
|
* @param xwin: a x11.Window
|
|
|
|
* @param prop: a x11.Atom
|
|
|
|
*/
|
|
|
|
getXWindowProperties: function(xwin, prop) {
|
2012-01-09 16:13:27 -05:00
|
|
|
// infos returned by XGetWindowProperty() - FIXME: should be freed ?
|
2012-01-01 16:31:16 -05:00
|
|
|
let actual_type = new x11.Atom;
|
|
|
|
let actual_format = new ctypes.int;
|
|
|
|
let nitems = new ctypes.unsigned_long;
|
|
|
|
let bytes_after = new ctypes.unsigned_long;
|
|
|
|
let prop_value = new ctypes.unsigned_char.ptr;
|
|
|
|
|
|
|
|
let bufSize = XATOMS_EWMH_WM_STATES.length*ctypes.unsigned_long.size;
|
|
|
|
let offset = 0;
|
|
|
|
let res = x11.XGetWindowProperty(
|
2012-01-07 10:06:10 -05:00
|
|
|
x11.current.Display, xwin, prop, offset, bufSize, 0, x11.AnyPropertyType,
|
2012-01-09 16:13:27 -05:00
|
|
|
actual_type.address(), actual_format.address(), nitems.address(),
|
|
|
|
bytes_after.address(), prop_value.address());
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("XGetWindowProperty res="+res+", actual_type="+actual_type.value+", actual_format="+actual_format.value+", bytes_after="+bytes_after.value+", nitems="+nitems.value);
|
2012-01-01 16:31:16 -05:00
|
|
|
|
2012-03-08 16:04:16 -05:00
|
|
|
if (!firetray.js.strEquals(res, x11.Success)) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR("XGetWindowProperty failed");
|
2012-01-07 10:06:10 -05:00
|
|
|
return [null, null];
|
2012-01-01 16:31:16 -05:00
|
|
|
}
|
2012-03-08 16:04:16 -05:00
|
|
|
if (firetray.js.strEquals(actual_type.value, x11.None)) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("property not found");
|
2012-01-07 10:06:10 -05:00
|
|
|
return [null, null];
|
2012-01-01 16:31:16 -05:00
|
|
|
}
|
|
|
|
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("prop_value="+prop_value+", size="+prop_value.constructor.size);
|
2012-01-01 16:31:16 -05:00
|
|
|
/* If the returned format is 32, the property data will be stored as an
|
|
|
|
array of longs (which in a 64-bit application will be 64-bit values
|
|
|
|
that are padded in the upper 4 bytes). [man XGetWindowProperty] */
|
|
|
|
if (actual_format.value !== 32) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR("unsupported format: "+actual_format.value);
|
2012-01-01 16:31:16 -05:00
|
|
|
}
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("format OK");
|
2012-01-01 16:31:16 -05:00
|
|
|
var props = ctypes.cast(prop_value, ctypes.unsigned_long.array(nitems.value).ptr);
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("props="+props+", size="+props.constructor.size);
|
2012-01-01 16:31:16 -05:00
|
|
|
|
2012-01-07 10:06:10 -05:00
|
|
|
return [props, nitems];
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* check the state of a window by its EWMH window state. This is more
|
|
|
|
* accurate than the chromeWin.windowState or the GdkWindowState which are
|
|
|
|
* based on WM_STATE. For instance, WM_STATE becomes 'Iconic' on virtual
|
|
|
|
* desktop change...
|
|
|
|
*/
|
|
|
|
getXWindowStates: function(xwin) {
|
|
|
|
let winStates = 0;
|
|
|
|
|
2012-01-09 16:13:27 -05:00
|
|
|
let [propsFound, nitems] =
|
|
|
|
firetray.Window.getXWindowProperties(xwin, x11.current.Atoms._NET_WM_STATE);
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("propsFound, nitems="+propsFound+", "+nitems);
|
2012-01-07 10:06:10 -05:00
|
|
|
if (!propsFound) return 0;
|
|
|
|
|
|
|
|
let maximizedHorz = maximizedVert = false;
|
2012-01-07 16:16:17 -05:00
|
|
|
for (let i=0, len=nitems.value; i<len; ++i) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("i: "+propsFound.contents[i]);
|
2012-01-09 16:13:27 -05:00
|
|
|
let currentProp = propsFound.contents[i];
|
2012-03-08 16:04:16 -05:00
|
|
|
if (firetray.js.strEquals(currentProp, x11.current.Atoms['_NET_WM_STATE_HIDDEN']))
|
2012-01-07 10:06:10 -05:00
|
|
|
winStates |= FIRETRAY_XWINDOW_HIDDEN;
|
2012-03-08 16:04:16 -05:00
|
|
|
else if (firetray.js.strEquals(currentProp, x11.current.Atoms['_NET_WM_STATE_MAXIMIZED_HORZ']))
|
2012-01-07 10:06:10 -05:00
|
|
|
maximizedHorz = true;
|
2012-03-08 16:04:16 -05:00
|
|
|
else if (firetray.js.strEquals(currentProp, x11.current.Atoms['_NET_WM_STATE_MAXIMIZED_VERT']))
|
2012-01-07 10:06:10 -05:00
|
|
|
maximizedVert = true;
|
2012-01-01 16:31:16 -05:00
|
|
|
}
|
|
|
|
|
2012-01-07 10:06:10 -05:00
|
|
|
if (maximizedHorz && maximizedVert)
|
|
|
|
winStates |= FIRETRAY_XWINDOW_MAXIMIZED;
|
2012-01-01 16:31:16 -05:00
|
|
|
|
2012-01-07 10:06:10 -05:00
|
|
|
x11.XFree(propsFound);
|
|
|
|
|
|
|
|
return winStates;
|
2012-01-01 16:31:16 -05:00
|
|
|
},
|
|
|
|
|
2012-01-09 16:13:27 -05:00
|
|
|
getXWindowDesktop: function(xwin) {
|
|
|
|
let desktop = null;
|
|
|
|
|
|
|
|
let [propsFound, nitems] =
|
|
|
|
firetray.Window.getXWindowProperties(xwin, x11.current.Atoms._NET_WM_DESKTOP);
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("DESKTOP propsFound, nitems="+propsFound+", "+nitems);
|
2012-01-14 19:02:00 -05:00
|
|
|
if (!propsFound) return null;
|
2012-01-09 16:13:27 -05:00
|
|
|
|
2012-03-08 16:04:16 -05:00
|
|
|
if (firetray.js.strEquals(nitems.value, 0))
|
2012-03-30 17:20:47 -04:00
|
|
|
F.WARN("desktop number not found");
|
2012-03-08 16:04:16 -05:00
|
|
|
else if (firetray.js.strEquals(nitems.value, 1))
|
2012-01-09 16:13:27 -05:00
|
|
|
desktop = propsFound.contents[0];
|
|
|
|
else
|
|
|
|
throw new RangeError("more than one desktop found");
|
|
|
|
|
|
|
|
x11.XFree(propsFound);
|
|
|
|
|
|
|
|
return desktop;
|
|
|
|
},
|
|
|
|
|
2012-01-22 22:04:05 -05:00
|
|
|
getWindowTitle: function(xid) {
|
|
|
|
let title = firetray.Handler.windows[xid].baseWin.title;
|
2012-07-26 20:12:20 -04:00
|
|
|
F.LOG("|baseWin.title="+title+"|");
|
2012-03-09 07:27:49 -05:00
|
|
|
let tailIndex = title.indexOf(" - Mozilla "+firetray.Handler.appName);
|
2012-01-22 22:04:05 -05:00
|
|
|
if (tailIndex !== -1)
|
2012-02-20 09:34:51 -05:00
|
|
|
return title.substring(0, tailIndex);
|
2012-03-09 07:27:49 -05:00
|
|
|
else if (title === "Mozilla "+firetray.Handler.appName)
|
2012-02-20 09:34:51 -05:00
|
|
|
return title;
|
2012-01-22 22:04:05 -05:00
|
|
|
else
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
2012-04-21 09:27:36 -04:00
|
|
|
checkSubscribedEventMasks: function(xid) {
|
|
|
|
let xWindowAttributes = new x11.XWindowAttributes;
|
|
|
|
let status = x11.XGetWindowAttributes(x11.current.Display, xid, xWindowAttributes.address());
|
|
|
|
F.LOG("xWindowAttributes: "+xWindowAttributes);
|
|
|
|
let xEventMask = xWindowAttributes.your_event_mask;
|
|
|
|
let xEventMaskNeeded = x11.VisibilityChangeMask|x11.StructureNotifyMask|x11.PropertyChangeMask;
|
|
|
|
F.LOG("xEventMask="+xEventMask+" xEventMaskNeeded="+xEventMaskNeeded);
|
|
|
|
if ((xEventMask & xEventMaskNeeded) !== xEventMaskNeeded) {
|
|
|
|
F.WARN("missing mandatory event-masks");
|
|
|
|
// could try to subscribe here with XChangeWindowAttributes()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-01-01 16:31:16 -05:00
|
|
|
filterWindow: function(xev, gdkEv, data) {
|
|
|
|
if (!xev)
|
|
|
|
return gdk.GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
try {
|
|
|
|
let xany = ctypes.cast(xev, x11.XAnyEvent.ptr);
|
|
|
|
let xwin = xany.contents.window;
|
|
|
|
|
2012-04-10 16:42:06 -04:00
|
|
|
let winStates, isHidden;
|
2012-01-01 16:31:16 -05:00
|
|
|
switch (xany.contents.type) {
|
|
|
|
|
2012-04-10 16:42:06 -04:00
|
|
|
case x11.PropertyNotify:
|
|
|
|
let xprop = ctypes.cast(xev, x11.XPropertyEvent.ptr);
|
2012-04-11 07:45:45 -04:00
|
|
|
if (firetray.Handler.windows[xwin].visible &&
|
|
|
|
firetray.js.strEquals(xprop.contents.atom, x11.current.Atoms.WM_STATE) &&
|
2012-04-10 16:42:06 -04:00
|
|
|
firetray.js.strEquals(xprop.contents.state, x11.PropertyNewValue)) {
|
2012-08-21 16:10:56 -04:00
|
|
|
F.LOG("xid="+xwin+" PropertyNotify: WM_STATE, send_event: "+xprop.contents.send_event+", state: "+xprop.contents.state);
|
2012-04-10 16:42:06 -04:00
|
|
|
winStates = firetray.Window.getXWindowStates(xwin);
|
|
|
|
isHidden = winStates & FIRETRAY_XWINDOW_HIDDEN;
|
|
|
|
}
|
2012-01-01 16:31:16 -05:00
|
|
|
break;
|
2012-04-10 16:42:06 -04:00
|
|
|
|
|
|
|
// default:
|
|
|
|
// F.LOG("xany.type="+xany.contents.type);
|
|
|
|
// break;
|
2012-01-01 16:31:16 -05:00
|
|
|
}
|
2012-04-10 16:42:06 -04:00
|
|
|
|
2012-05-12 09:24:14 -04:00
|
|
|
// NOTE: Gecko 8.0 provides the 'sizemodechange' event
|
2012-04-11 07:45:45 -04:00
|
|
|
if (isHidden) { // minimized
|
|
|
|
F.LOG("winStates="+winStates+", isHidden="+isHidden);
|
|
|
|
let hides_on_minimize = firetray.Utils.prefService.getBoolPref('hides_on_minimize');
|
|
|
|
let hides_single_window = firetray.Utils.prefService.getBoolPref('hides_single_window');
|
|
|
|
if (hides_on_minimize) {
|
|
|
|
if (hides_single_window) {
|
2012-07-23 20:00:44 -04:00
|
|
|
firetray.Handler.hideWindow(xwin);
|
2012-04-11 07:45:45 -04:00
|
|
|
} else
|
2012-08-21 16:10:56 -04:00
|
|
|
firetray.Handler.hideAllWindows();
|
2012-04-11 07:45:45 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-01 16:31:16 -05:00
|
|
|
} catch(x) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR(x);
|
2012-01-01 16:31:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return gdk.GDK_FILTER_CONTINUE;
|
2011-12-16 22:15:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}; // firetray.Window
|
2011-12-31 19:45:48 -05:00
|
|
|
|
|
|
|
|
|
|
|
///////////////////////// firetray.Handler overriding /////////////////////////
|
|
|
|
|
|
|
|
/** debug facility */
|
|
|
|
firetray.Handler.dumpWindows = function() {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG(firetray.Handler.windowsCount);
|
|
|
|
for (let winId in firetray.Handler.windows) F.LOG(winId+"="+firetray.Handler.gtkWindows.get(winId));
|
2011-12-31 19:45:48 -05:00
|
|
|
};
|
|
|
|
|
2012-01-21 03:14:03 -05:00
|
|
|
firetray.Handler.getWindowIdFromChromeWindow = firetray.Window.getXIDFromChromeWindow;
|
|
|
|
|
2011-12-31 19:45:48 -05:00
|
|
|
firetray.Handler.registerWindow = function(win) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("register window");
|
2011-12-31 19:45:48 -05:00
|
|
|
|
|
|
|
// register
|
2012-07-26 20:12:20 -04:00
|
|
|
let [baseWin, gtkWin, gdkWin, xid] = firetray.Window.getWindowsFromChromeWindow(win);
|
2011-12-31 19:45:48 -05:00
|
|
|
this.windows[xid] = {};
|
2012-01-01 11:30:51 -05:00
|
|
|
this.windows[xid].chromeWin = win;
|
2012-07-26 20:12:20 -04:00
|
|
|
this.windows[xid].baseWin = baseWin;
|
|
|
|
firetray.Window.checkSubscribedEventMasks(xid);
|
2012-01-01 07:30:42 -05:00
|
|
|
try {
|
|
|
|
this.gtkWindows.insert(xid, gtkWin);
|
|
|
|
this.gdkWindows.insert(xid, gdkWin);
|
2012-01-22 22:04:05 -05:00
|
|
|
firetray.PopupMenu.addWindowItem(xid);
|
2012-01-01 07:30:42 -05:00
|
|
|
} 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 "
|
2012-03-09 07:27:49 -05:00
|
|
|
+firetray.Handler.appName+".");
|
2012-01-01 07:30:42 -05:00
|
|
|
}
|
2011-12-31 19:45:48 -05:00
|
|
|
this.windowsCount += 1;
|
2012-01-01 11:30:51 -05:00
|
|
|
// NOTE: no need to check for window state to set visibility because all
|
|
|
|
// windows *are* shown at startup
|
2012-04-11 07:45:45 -04:00
|
|
|
this.windows[xid].visible = true; // this.windows[xid].baseWin.visibility always true :-(
|
2011-12-31 19:45:48 -05:00
|
|
|
this.visibleWindowsCount += 1;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("window "+xid+" registered");
|
2012-01-01 11:30:51 -05:00
|
|
|
// NOTE: shouldn't be necessary to gtk_widget_add_events(gtkWin, gdk.GDK_ALL_EVENTS_MASK);
|
2011-12-31 19:45:48 -05:00
|
|
|
|
|
|
|
try {
|
2012-01-01 11:30:51 -05:00
|
|
|
// 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
|
2011-12-31 19:45:48 -05:00
|
|
|
|
2012-01-01 16:31:16 -05:00
|
|
|
this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t(firetray.Window.filterWindow);
|
|
|
|
gdk.gdk_window_add_filter(gdkWin, this.windows[xid].filterWindowCb, null);
|
2011-12-31 19:45:48 -05:00
|
|
|
|
2012-08-21 16:10:56 -04:00
|
|
|
// FIXME: isn't it (c)leaner to do it in x11 window filter ?
|
|
|
|
if (firetray.Handler.isIMEnabled) {
|
|
|
|
Cu.import("resource://firetray/linux/FiretrayIMStatusIcon.jsm");
|
|
|
|
firetray.IMStatusIcon.attachOnFocusInCallback(xid);
|
|
|
|
}
|
|
|
|
|
2011-12-31 19:45:48 -05:00
|
|
|
} catch (x) {
|
2012-01-21 03:14:03 -05:00
|
|
|
firetray.Window.unregisterWindowByXID(xid);
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR(x);
|
2012-02-20 09:34:51 -05:00
|
|
|
return null;
|
2011-12-31 19:45:48 -05:00
|
|
|
}
|
|
|
|
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("AFTER"); firetray.Handler.dumpWindows();
|
2012-02-20 09:34:51 -05:00
|
|
|
return xid;
|
2011-12-31 19:45:48 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
firetray.Handler.unregisterWindow = function(win) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("unregister window");
|
2012-01-01 13:25:56 -05:00
|
|
|
let xid = firetray.Window.getXIDFromChromeWindow(win);
|
2012-01-21 03:14:03 -05:00
|
|
|
return firetray.Window.unregisterWindowByXID(xid);
|
2011-12-31 19:45:48 -05:00
|
|
|
};
|
|
|
|
|
2012-07-23 20:00:44 -04:00
|
|
|
firetray.Handler.showWindow = firetray.Window.show;
|
|
|
|
firetray.Handler.hideWindow = firetray.Window.hide;
|
|
|
|
firetray.Handler.startupHideWindow = firetray.Window.startupHide;
|
2012-02-20 09:34:51 -05:00
|
|
|
|
2011-12-31 19:45:48 -05:00
|
|
|
firetray.Handler.showHideAllWindows = function(gtkStatusIcon, userData) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("showHideAllWindows: "+userData);
|
2011-12-31 19:45:48 -05:00
|
|
|
// NOTE: showHideAllWindows being a callback, we need to use
|
|
|
|
// 'firetray.Handler' explicitely instead of 'this'
|
|
|
|
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("visibleWindowsCount="+firetray.Handler.visibleWindowsCount);
|
|
|
|
F.LOG("windowsCount="+firetray.Handler.windowsCount);
|
2011-12-31 19:45:48 -05:00
|
|
|
let visibilityRate = firetray.Handler.visibleWindowsCount/firetray.Handler.windowsCount;
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("visibilityRate="+visibilityRate);
|
2012-05-13 10:01:41 -04:00
|
|
|
if ((0.5 < visibilityRate) && (visibilityRate < 1)
|
|
|
|
|| visibilityRate === 0) { // TODO: should be configurable
|
2011-12-31 19:45:48 -05:00
|
|
|
firetray.Handler.showAllWindows();
|
2012-05-12 10:45:04 -04:00
|
|
|
} else {
|
2012-01-22 22:04:05 -05:00
|
|
|
firetray.Handler.hideAllWindows();
|
2012-05-12 10:45:04 -04:00
|
|
|
}
|
2011-12-31 19:45:48 -05:00
|
|
|
|
|
|
|
let stopPropagation = true;
|
|
|
|
return stopPropagation;
|
|
|
|
};
|
2012-01-01 16:31:16 -05:00
|
|
|
|
2012-05-13 10:01:41 -04:00
|
|
|
firetray.Handler.activateLastWindow = function(gtkStatusIcon, gdkEvent, userData) {
|
|
|
|
F.LOG("activateLastWindow");
|
|
|
|
|
|
|
|
let gdkEventButton = ctypes.cast(gdkEvent, gdk.GdkEventButton.ptr);
|
|
|
|
if (gdkEventButton.contents.button === 2 && gdkEventButton.contents.type === gdk.GDK_BUTTON_PRESS) {
|
|
|
|
F.LOG("MIDDLE CLICK");
|
|
|
|
|
|
|
|
let visibilityRate = firetray.Handler.visibleWindowsCount/firetray.Handler.windowsCount;
|
|
|
|
F.LOG("visibilityRate="+visibilityRate);
|
|
|
|
if (visibilityRate === 1) {
|
|
|
|
for(var key in firetray.Handler.windows);
|
|
|
|
firetray.Window.activate(key);
|
|
|
|
} else {
|
|
|
|
firetray.Handler.showAllWindows();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let stopPropagation = false;
|
|
|
|
return stopPropagation;
|
|
|
|
};
|
|
|
|
|
2012-08-21 16:10:56 -04:00
|
|
|
firetray.Handler.findActiveWindow = function() {
|
|
|
|
let activeWin = null;
|
|
|
|
for (let xid in firetray.Handler.windows) {
|
|
|
|
let gtkWin = firetray.Handler.gtkWindows.get(xid);
|
|
|
|
let isActive = gtk.gtk_window_is_active(gtkWin);
|
|
|
|
F.LOG(xid+" is active="+isActive);
|
|
|
|
if (isActive) {
|
|
|
|
activeWin = xid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return activeWin;
|
|
|
|
};
|
|
|
|
|
2012-01-01 16:31:16 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* init X11 Display and handled XAtoms.
|
2012-01-09 16:13:27 -05:00
|
|
|
* Needs to be defined and called outside x11.jsm because: 1. gdk already
|
|
|
|
* imports x11, 2. there is no means to get the default Display solely with
|
|
|
|
* Xlib without opening one... :-(
|
2012-01-01 16:31:16 -05:00
|
|
|
*/
|
|
|
|
x11.init = function() {
|
2012-03-08 16:04:16 -05:00
|
|
|
if (!firetray.js.isEmpty(this.current))
|
2012-01-01 16:31:16 -05:00
|
|
|
return true; // init only once
|
|
|
|
|
|
|
|
this.current = {};
|
|
|
|
try {
|
|
|
|
let gdkDisplay = gdk.gdk_display_get_default();
|
|
|
|
this.current.Display = gdk.gdk_x11_display_get_xdisplay(gdkDisplay);
|
|
|
|
this.current.Atoms = {};
|
|
|
|
XATOMS.forEach(function(atomName, index, array) {
|
|
|
|
this.current.Atoms[atomName] = x11.XInternAtom(this.current.Display, atomName, 0);
|
2012-03-30 17:20:47 -04:00
|
|
|
F.LOG("x11.current.Atoms."+atomName+"="+this.current.Atoms[atomName]);
|
2012-01-01 16:31:16 -05:00
|
|
|
}, this);
|
|
|
|
return true;
|
|
|
|
} catch (x) {
|
2012-03-30 17:20:47 -04:00
|
|
|
F.ERROR(x);
|
2012-01-01 16:31:16 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
x11.init();
|