mirror of
https://github.com/moparisthebest/FireTray
synced 2024-11-15 13:25:04 -05:00
* extract FiretrayWindow.jsm out of FiretrayStatusIcon.jsm
* new windows get registered (onLoad) * basic show/hide fonctionality WORK IN PROGRESS
This commit is contained in:
parent
6bf568bcc7
commit
88bf1451e0
@ -32,6 +32,7 @@ firetray.Main = {
|
||||
}
|
||||
|
||||
let init = firetray.Handler.initialized || firetray.Handler.init();
|
||||
firetray.Handler.registerWindow(window);
|
||||
|
||||
// update unread messages count
|
||||
if (firetray.Handler.inMailApp && firetray.Messaging.initialized)
|
||||
|
@ -35,11 +35,9 @@ firetray.Handler = {
|
||||
FILENAME_NEWMAIL: null,
|
||||
runtimeOS: null,
|
||||
inMailApp: false,
|
||||
windows: [],
|
||||
|
||||
_windowsHidden: false,
|
||||
_handledDOMWindows: [],
|
||||
|
||||
init: function() { // creates icon
|
||||
init: function() { // does creates icon
|
||||
this.appName = Services.appinfo.name.toLowerCase();
|
||||
this.FILENAME_DEFAULT = firetray.Utils.chromeToPath(
|
||||
"chrome://firetray/skin/" + this.appName + this.FILENAME_SUFFIX);
|
||||
@ -48,8 +46,10 @@ firetray.Handler = {
|
||||
this.FILENAME_NEWMAIL = firetray.Utils.chromeToPath(
|
||||
"chrome://firetray/skin/message-mail-new.png");
|
||||
|
||||
/* GTK TEST
|
||||
// init all handled windows
|
||||
this._updateHandledDOMWindows();
|
||||
*/
|
||||
|
||||
// OS/platform checks
|
||||
this.runtimeABI = Services.appinfo.XPCOMABI;
|
||||
@ -61,6 +61,8 @@ firetray.Handler = {
|
||||
case "Linux":
|
||||
Cu.import("resource://firetray/gtk2/FiretrayStatusIcon.jsm");
|
||||
LOG('FiretrayStatusIcon imported');
|
||||
Cu.import("resource://firetray/gtk2/FiretrayWindow.jsm");
|
||||
LOG('FiretrayWindow imported');
|
||||
|
||||
// instanciate tray icon
|
||||
firetray.StatusIcon.init();
|
||||
@ -116,6 +118,9 @@ firetray.Handler = {
|
||||
setText: function(text, color) {},
|
||||
setTooltip: function(localizedMessage) {},
|
||||
setTooltipDefault: function() {},
|
||||
showHideToTray: function() {},
|
||||
registerWindow: function(win) {},
|
||||
unregisterWindow: function(win) {},
|
||||
|
||||
_getBaseOrXULWindowFromDOMWindow: function(win, winType) {
|
||||
let winInterface, winOut;
|
||||
@ -143,24 +148,26 @@ firetray.Handler = {
|
||||
return winOut;
|
||||
},
|
||||
|
||||
/*
|
||||
* DAMN IT ! getZOrderDOMWindowEnumerator doesn't work on Linux :-(
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=156333, and all windows
|
||||
* seem to have the same zlevel ("normalZ") which is different from the
|
||||
* z-order. There seems to be no means to get/set the z-order at this
|
||||
* time...
|
||||
*/
|
||||
_updateHandledDOMWindows: function() {
|
||||
LOG("_updateHandledDOMWindows");
|
||||
this._handledDOMWindows = [];
|
||||
var windowsEnumerator = Services.wm.getEnumerator(null); // returns a nsIDOMWindow
|
||||
while (windowsEnumerator.hasMoreElements()) {
|
||||
this._handledDOMWindows[this._handledDOMWindows.length] =
|
||||
windowsEnumerator.getNext();
|
||||
}
|
||||
},
|
||||
|
||||
/* GTK TEST */
|
||||
|
||||
// /*
|
||||
// * DAMN IT ! getZOrderDOMWindowEnumerator doesn't work on Linux :-(
|
||||
// * https://bugzilla.mozilla.org/show_bug.cgi?id=156333, and all windows
|
||||
// * seem to have the same zlevel ("normalZ") which is different from the
|
||||
// * z-order. There seems to be no means to get/set the z-order at this
|
||||
// * time...
|
||||
// */
|
||||
// _updateHandledDOMWindows: function() {
|
||||
// LOG("_updateHandledDOMWindows");
|
||||
// this._handledDOMWindows = [];
|
||||
// var windowsEnumerator = Services.wm.getEnumerator(null); // returns a nsIDOMWindow
|
||||
// while (windowsEnumerator.hasMoreElements()) {
|
||||
// this._handledDOMWindows[this._handledDOMWindows.length] =
|
||||
// windowsEnumerator.getNext();
|
||||
// }
|
||||
// },
|
||||
|
||||
// showHideToTray: function(a1) { // unused param
|
||||
// LOG("showHideToTray");
|
||||
|
||||
|
@ -129,6 +129,7 @@ function gdk_defines(lib) {
|
||||
ctypes.default_abi, this.GdkFilterReturn,
|
||||
[this.GdkXEvent.ptr, this.GdkEvent.ptr, gobject.gpointer]).ptr;
|
||||
|
||||
lib.lazy_bind("gdk_x11_drawable_get_xid", x11.XID, this.GdkDrawable.ptr);
|
||||
lib.lazy_bind("gdk_window_new", this.GdkWindow.ptr, this.GdkWindow.ptr, this.GdkWindowAttributes.ptr, gobject.gint);
|
||||
lib.lazy_bind("gdk_window_destroy", ctypes.void_t, this.GdkWindow.ptr);
|
||||
lib.lazy_bind("gdk_x11_window_set_user_time", ctypes.void_t, this.GdkWindow.ptr, gobject.guint32);
|
||||
|
@ -17,36 +17,17 @@ Cu.import("resource://firetray/libc.jsm");
|
||||
Cu.import("resource://firetray/pango.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
|
||||
const Services2 = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
Services2,
|
||||
"uuid",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator"
|
||||
);
|
||||
|
||||
if ("undefined" == typeof(firetray.Handler))
|
||||
ERROR("FiretrayIcon*.jsm MUST be imported from/after FiretrayHandler !");
|
||||
ERROR("This module MUST be imported from/after FiretrayHandler !");
|
||||
|
||||
// pointers to JS functions. should *not* be eaten by GC ("Running global
|
||||
// cleanup code from study base classes" ?)
|
||||
// pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
|
||||
var firetray_iconActivateCb;
|
||||
var firetray_popupMenuCb;
|
||||
var firetray_menuItemQuitActivateCb;
|
||||
var firetray_findGtkWindowByTitleCb;
|
||||
var firetray_windowDeleteCb;
|
||||
var firetray_windowStateCb;
|
||||
|
||||
/**
|
||||
* custum type used to pass data in to and out of firetray_findGtkWindowByTitleCb
|
||||
*/
|
||||
var _find_data_t = ctypes.StructType("_find_data_t", [
|
||||
{ inTitle: ctypes.char.ptr },
|
||||
{ outWindow: gtk.GtkWindow.ptr }
|
||||
]);
|
||||
|
||||
|
||||
firetray.StatusIcon = {
|
||||
initialized: false,
|
||||
trayIcon: null,
|
||||
menu: null,
|
||||
MIN_FONT_SIZE: 4,
|
||||
@ -66,60 +47,23 @@ firetray.StatusIcon = {
|
||||
|
||||
firetray.Handler.setTooltipDefault();
|
||||
|
||||
// attach popupMenu to trayIcon
|
||||
try {
|
||||
|
||||
/* GTK TEST. initWindow should be done somewhere else
|
||||
(Firetray.WindowLinux ?) */
|
||||
let win = Services.wm.getMostRecentWindow(null);
|
||||
/* NOTE: it should not be necessary to cast gtkWin to a GtkWidget, nor
|
||||
gtk_widget_add_events(gtkWin, gdk.GDK_ALL_EVENTS_MASK); */
|
||||
let gtkWin = this.getGtkWindowHandle(win);
|
||||
LOG("gtkWin="+gtkWin);
|
||||
let gdkWin = gtk.gtk_widget_get_window(
|
||||
ctypes.cast(gtkWin, gtk.GtkWidget.ptr));
|
||||
LOG("gdkWin="+gdkWin);
|
||||
|
||||
firetray_iconActivateCb = gtk.GCallbackStatusIconActivate_t(firetray.StatusIcon.showHideToTray);
|
||||
// gobject.g_signal_connect(this.trayIcon, "activate", firetray_iconActivateCb, null);
|
||||
gobject.g_signal_connect(this.trayIcon, "activate", firetray_iconActivateCb, gdkWin); // TEST
|
||||
|
||||
/* delete_event_cb (in gtk2/nsWindow.cpp) prevents us from catching
|
||||
"delete-event" */
|
||||
|
||||
let deleteEventId = gobject.g_signal_lookup("delete-event", gtk.gtk_window_get_type());
|
||||
LOG("deleteEventId="+deleteEventId);
|
||||
let deleteEventHandler = gobject.g_signal_handler_find(gtkWin, gobject.G_SIGNAL_MATCH_ID, deleteEventId, 0, null, null, null);
|
||||
LOG("deleteEventHandler="+deleteEventHandler);
|
||||
gobject.g_signal_handler_block(gtkWin, deleteEventHandler); // not _disconnect
|
||||
|
||||
firetray_windowDeleteCb = gtk.GCallbackGenericEvent_t(firetray.StatusIcon.windowDelete);
|
||||
// let res = gobject.g_signal_connect(gtkWin, "delete_event", firetray_windowDeleteCb, null);
|
||||
let res = gobject.g_signal_connect(gtkWin, "delete_event", firetray_windowDeleteCb, null);
|
||||
LOG("g_connect delete-event="+res);
|
||||
|
||||
|
||||
/* we'll catch minimize events with Gtk:
|
||||
http://stackoverflow.com/questions/8018328/what-is-the-gtk-event-called-when-a-window-minimizes */
|
||||
firetray_windowStateCb = gtk.GCallbackGenericEvent_t(firetray.StatusIcon.windowState);
|
||||
res = gobject.g_signal_connect(gtkWin, "window-state-event", firetray_windowStateCb, null);
|
||||
LOG("g_connect window-state-event="+res);
|
||||
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
return false;
|
||||
}
|
||||
LOG("showHideToTray: "+firetray.Handler.hasOwnProperty("showHideToTray"));
|
||||
firetray_iconActivateCb = gtk.GCallbackStatusIconActivate_t(firetray.Handler.showHideToTray);
|
||||
let res = gobject.g_signal_connect(firetray.StatusIcon.trayIcon, "activate", firetray_iconActivateCb, null);
|
||||
LOG("g_connect activate="+res);
|
||||
|
||||
this.initialized = true;
|
||||
return true;
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
cairo.close();
|
||||
// glib.close();
|
||||
gobject.close();
|
||||
gdk.close();
|
||||
gtk.close();
|
||||
pango.close();
|
||||
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
_buildPopupMenu: function() {
|
||||
@ -146,8 +90,7 @@ firetray.StatusIcon = {
|
||||
definition) because we need the args passed to it ! As a consequence, we
|
||||
need to abandon 'this' in popupMenu() */
|
||||
let that = this;
|
||||
firetray_popupMenuCb =
|
||||
gtk.GCallbackMenuPopup_t(that.popupMenu);
|
||||
firetray_popupMenuCb = gtk.GCallbackMenuPopup_t(that.popupMenu);
|
||||
gobject.g_signal_connect(this.trayIcon, "popup-menu",
|
||||
firetray_popupMenuCb, this.menu);
|
||||
},
|
||||
@ -165,135 +108,6 @@ firetray.StatusIcon = {
|
||||
} catch (x) {
|
||||
LOG(x);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
getGtkWindowHandle: function(window) {
|
||||
let baseWindow = window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIBaseWindow);
|
||||
|
||||
// Tag the base window
|
||||
let oldTitle = baseWindow.title;
|
||||
baseWindow.title = Services2.uuid.generateUUID().toString();
|
||||
|
||||
try {
|
||||
// Search the window by the *temporary* title
|
||||
let widgets = gtk.gtk_window_list_toplevels();
|
||||
let that = this;
|
||||
firetray_findGtkWindowByTitleCb = gobject.GFunc_t(that._findGtkWindowByTitle);
|
||||
var userData = new _find_data_t(
|
||||
ctypes.char.array()(baseWindow.title),
|
||||
null
|
||||
).address();
|
||||
LOG("userData="+userData);
|
||||
gobject.g_list_foreach(widgets, firetray_findGtkWindowByTitleCb, userData);
|
||||
gobject.g_list_free(widgets);
|
||||
|
||||
if (userData.contents.outWindow.isNull()) {
|
||||
throw new Error("Window not found!");
|
||||
}
|
||||
LOG("found window: "+userData.contents.outWindow);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
} 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) {
|
||||
LOG("GTK Window: "+gtkWidget+", "+userData);
|
||||
|
||||
let data = ctypes.cast(userData, _find_data_t.ptr);
|
||||
let inTitle = data.contents.inTitle;
|
||||
LOG("inTitle="+inTitle.readString());
|
||||
|
||||
let gtkWin = ctypes.cast(gtkWidget, gtk.GtkWindow.ptr);
|
||||
let winTitle = gtk.gtk_window_get_title(gtkWin);
|
||||
|
||||
try {
|
||||
if (!winTitle.isNull()) {
|
||||
LOG(inTitle+" = "+winTitle);
|
||||
if (libc.strcmp(inTitle, winTitle) == 0)
|
||||
data.contents.outWindow = gtkWin;
|
||||
}
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
},
|
||||
|
||||
// FIXME: it may not be worth wrapping gtk_widget_get_window...
|
||||
getGdkWindowFromGtkWindow: function(gtkWin) {
|
||||
try {
|
||||
let gtkWid = ctypes.cast(gtkWin, gtk.GtkWidget.ptr);
|
||||
var gdkWin = gtk.gtk_widget_get_window(gtkWid);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
return gdkWin;
|
||||
},
|
||||
|
||||
getGdkWindowHandle: function(win) {
|
||||
try {
|
||||
let gtkWin = firetray.StatusIcon.getGtkWindowHandle(win);
|
||||
LOG("FOUND: "+gtk.gtk_window_get_title(gtkWin).readString());
|
||||
let gdkWin = this.getGdkWindowFromGtkWindow(gtkWin);
|
||||
if (!gdkWin.isNull()) {
|
||||
LOG("has window");
|
||||
return gdkWin;
|
||||
}
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
showHideToTray: function(gtkStatusIcon, userData){
|
||||
LOG("showHideToTray: "+userData);
|
||||
try {
|
||||
let gdkWin = ctypes.cast(userData, gdk.GdkWindow.ptr);
|
||||
gdk.gdk_window_show(gdkWin);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
|
||||
let stopPropagation = true;
|
||||
return stopPropagation;
|
||||
},
|
||||
|
||||
windowDelete: function(gtkWidget, gdkEv, userData){
|
||||
LOG("gtk_widget_hide: "+gtkWidget+", "+gdkEv+", "+userData);
|
||||
try{
|
||||
let gdkWin = firetray.StatusIcon.getGdkWindowFromGtkWindow(gtkWidget);
|
||||
gdk.gdk_window_hide(gdkWin);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
let stopPropagation = true;
|
||||
return stopPropagation;
|
||||
},
|
||||
|
||||
windowState: function(gtkWidget, gdkEv, userData){
|
||||
LOG("window-state-event");
|
||||
let stopPropagation = true;
|
||||
return stopPropagation;
|
||||
}
|
||||
|
||||
}; // firetray.StatusIcon
|
||||
@ -445,7 +259,3 @@ firetray.Handler.setText = function(text, color) { // TODO: split into smaller f
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
firetray.Handler.showHideToTray = function() {
|
||||
// How to do that ?? is called in overlay.xul
|
||||
};
|
||||
|
228
src/modules/gtk2/FiretrayWindow.jsm
Normal file
228
src/modules/gtk2/FiretrayWindow.jsm
Normal file
@ -0,0 +1,228 @@
|
||||
/* -*- 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");
|
||||
Cu.import("resource://firetray/gobject.jsm");
|
||||
Cu.import("resource://firetray/gdk.jsm");
|
||||
Cu.import("resource://firetray/gtk.jsm");
|
||||
Cu.import("resource://firetray/libc.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
|
||||
const Services2 = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
Services2,
|
||||
"uuid",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator"
|
||||
);
|
||||
|
||||
if ("undefined" == typeof(firetray.Handler))
|
||||
ERROR("This module MUST be imported from/after FiretrayHandler !");
|
||||
|
||||
/**
|
||||
* 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 }
|
||||
]);
|
||||
|
||||
|
||||
firetray.Handler.registerWindow = function(win) {
|
||||
let that = this;
|
||||
|
||||
/* GTK TEST. */
|
||||
try {
|
||||
|
||||
let gtkWin = firetray.Window.getGtkWindowHandle(win);
|
||||
LOG("gtkWin="+gtkWin);
|
||||
let gdkWin = gtk.gtk_widget_get_window(ctypes.cast(gtkWin, gtk.GtkWidget.ptr));
|
||||
LOG("gdkWin="+gdkWin);
|
||||
/* NOTE: it should not be necessary to gtk_widget_add_events(gtkWin,
|
||||
gdk.GDK_ALL_EVENTS_MASK); */
|
||||
|
||||
// register
|
||||
let xid = gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
|
||||
LOG("XID="+xid);
|
||||
this.windows[xid] = {}; // windows.hasOwnProperty(xid) is true, remove with: delete windows[xid]
|
||||
this.windows[xid].gtkWin = gtkWin;
|
||||
this.windows[xid].gdkWin = gdkWin;
|
||||
|
||||
/* delete_event_cb (in gtk2/nsWindow.cpp) prevents us from catching
|
||||
"delete-event" */
|
||||
let deleteEventId = gobject.g_signal_lookup("delete-event", gtk.gtk_window_get_type());
|
||||
LOG("deleteEventId="+deleteEventId);
|
||||
let mozDeleteEventCb = gobject.g_signal_handler_find(gtkWin, gobject.G_SIGNAL_MATCH_ID, deleteEventId, 0, null, null, null);
|
||||
LOG("mozDeleteEventCb="+mozDeleteEventCb);
|
||||
gobject.g_signal_handler_block(gtkWin, mozDeleteEventCb); // not _disconnect !
|
||||
this.windows[xid].mozDeleteEventCb = mozDeleteEventCb; // FIXME: cb should be unblocked
|
||||
|
||||
this.windows[xid].windowDeleteCb = gtk.GCallbackGenericEvent_t(firetray.Window.windowDelete);
|
||||
res = gobject.g_signal_connect(gtkWin, "delete-event", that.windows[xid].windowDeleteCb, null);
|
||||
LOG("g_connect delete-event="+res);
|
||||
|
||||
/* we'll catch minimize events with Gtk:
|
||||
http://stackoverflow.com/questions/8018328/what-is-the-gtk-event-called-when-a-window-minimizes */
|
||||
this.windows[xid].windowStateCb = gtk.GCallbackGenericEvent_t(firetray.Window.windowState);
|
||||
res = gobject.g_signal_connect(gtkWin, "window-state-event", this.windows[xid].windowStateCb, null);
|
||||
LOG("g_connect window-state-event="+res);
|
||||
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
firetray.Handler.unregisterWindow = function(win) {};
|
||||
|
||||
firetray.Handler.showHideToTray = function(gtkStatusIcon, userData) {
|
||||
LOG("showHideToTray: "+userData);
|
||||
|
||||
for (let xid in firetray.Handler.windows) {
|
||||
LOG(xid);
|
||||
try {
|
||||
gdk.gdk_window_show(firetray.Handler.windows[xid].gdkWin);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
}
|
||||
|
||||
let stopPropagation = true;
|
||||
return stopPropagation;
|
||||
};
|
||||
|
||||
|
||||
firetray.Window = {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
getGtkWindowHandle: function(window) {
|
||||
let baseWindow = window
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIBaseWindow);
|
||||
|
||||
// Tag the base window
|
||||
let oldTitle = baseWindow.title;
|
||||
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();
|
||||
LOG("userData="+userData);
|
||||
gobject.g_list_foreach(widgets, findGtkWindowByTitleCb, userData);
|
||||
gobject.g_list_free(widgets);
|
||||
|
||||
if (userData.contents.outWindow.isNull()) {
|
||||
throw new Error("Window not found!");
|
||||
}
|
||||
LOG("found window: "+userData.contents.outWindow);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
} 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) {
|
||||
LOG("GTK Window: "+gtkWidget+", "+userData);
|
||||
|
||||
let data = ctypes.cast(userData, _find_data_t.ptr);
|
||||
let inTitle = data.contents.inTitle;
|
||||
LOG("inTitle="+inTitle.readString());
|
||||
|
||||
let gtkWin = ctypes.cast(gtkWidget, gtk.GtkWindow.ptr);
|
||||
let winTitle = gtk.gtk_window_get_title(gtkWin);
|
||||
|
||||
try {
|
||||
if (!winTitle.isNull()) {
|
||||
LOG(inTitle+" = "+winTitle);
|
||||
if (libc.strcmp(inTitle, winTitle) == 0)
|
||||
data.contents.outWindow = gtkWin;
|
||||
}
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
},
|
||||
|
||||
// FIXME: it may not be worth wrapping gtk_widget_get_window...
|
||||
getGdkWindowFromGtkWindow: function(gtkWin) {
|
||||
try {
|
||||
let gtkWid = ctypes.cast(gtkWin, gtk.GtkWidget.ptr);
|
||||
var gdkWin = gtk.gtk_widget_get_window(gtkWid);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
return gdkWin;
|
||||
},
|
||||
|
||||
getGdkWindowHandle: function(win) {
|
||||
try {
|
||||
let gtkWin = firetray.Window.getGtkWindowHandle(win);
|
||||
LOG("FOUND: "+gtk.gtk_window_get_title(gtkWin).readString());
|
||||
let gdkWin = this.getGdkWindowFromGtkWindow(gtkWin);
|
||||
if (!gdkWin.isNull()) {
|
||||
LOG("has window");
|
||||
return gdkWin;
|
||||
}
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
windowDelete: function(gtkWidget, gdkEv, userData){
|
||||
LOG("gtk_widget_hide: "+gtkWidget+", "+gdkEv+", "+userData);
|
||||
try{
|
||||
let gdkWin = firetray.Window.getGdkWindowFromGtkWindow(gtkWidget);
|
||||
gdk.gdk_window_hide(gdkWin);
|
||||
} catch (x) {
|
||||
ERROR(x);
|
||||
}
|
||||
let stopPropagation = true;
|
||||
return stopPropagation;
|
||||
},
|
||||
|
||||
windowState: function(gtkWidget, gdkEv, userData){
|
||||
LOG("window-state-event");
|
||||
let stopPropagation = true;
|
||||
return stopPropagation;
|
||||
}
|
||||
|
||||
}; // firetray.Window
|
@ -45,11 +45,13 @@ function x11_defines(lib) {
|
||||
this.Atom = ctypes.unsigned_long;
|
||||
this.Window = ctypes.unsigned_long;
|
||||
this.Time = ctypes.unsigned_long;
|
||||
this.XID = ctypes.unsigned_long;
|
||||
} else {
|
||||
this.CARD32 = ctypes.unsigned_long;
|
||||
this.Atom = this.CARD32;
|
||||
this.Window = this.CARD32;
|
||||
this.Time = this.CARD32;
|
||||
this.XID = this.CARD32;
|
||||
}
|
||||
|
||||
// X.h
|
||||
|
Loading…
Reference in New Issue
Block a user