[Pkg-mozext-commits] [firetray] 16/33: Add gtk3 support.

David Prévot taffit at moszumanska.debian.org
Fri Oct 23 21:35:11 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository firetray.

commit 4d9816ee439dab1773ef79b12726b799a25b3d88
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Mon Aug 17 23:22:47 2015 +0200

    Add gtk3 support.
    
    Not fully tested yet.
    The code got a bit messier. Supporting both gtk2 and gtk3 is a
    temporary situation: we intend to drop support for gtk2 when major moz
    apps have migrated to gtk3.
---
 src/modules/ctypes/linux/cairo.jsm                 |  10 +
 .../ctypes/linux/{gtk2/gdk.jsm => gdk23.jsm}       |  89 +------
 src/modules/ctypes/linux/gtk2/gdk.jsm              | 284 +++------------------
 src/modules/ctypes/linux/gtk2/gtk.jsm              |   3 +
 src/modules/ctypes/linux/gtk23.jsm                 |  21 ++
 src/modules/ctypes/linux/gtk3/appindicator.jsm     |  58 +++++
 src/modules/ctypes/linux/gtk3/gdk.jsm              |  69 +++++
 src/modules/ctypes/linux/{gtk2 => gtk3}/gtk.jsm    |  13 +-
 src/modules/linux/FiretrayChatStatusIcon.jsm       |   6 +-
 src/modules/linux/FiretrayGtkStatusIcon.jsm        |  55 ++--
 src/modules/linux/FiretrayPopupMenu.jsm            |  14 +-
 src/modules/linux/FiretrayStatusIcon.jsm           |   3 +
 src/modules/linux/FiretrayWindow.jsm               |  53 ++--
 src/modules/logging.jsm                            |   2 +-
 14 files changed, 306 insertions(+), 374 deletions(-)

diff --git a/src/modules/ctypes/linux/cairo.jsm b/src/modules/ctypes/linux/cairo.jsm
index 7a3bccc..f9c4c94 100644
--- a/src/modules/ctypes/linux/cairo.jsm
+++ b/src/modules/ctypes/linux/cairo.jsm
@@ -13,12 +13,22 @@ Cu.import("resource://gre/modules/ctypes.jsm");
 Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
 
 function cairo_defines(lib) {
+  this.cairo_format_t = ctypes.int;     // enum
+  this.CAIRO_FORMAT_ARGB32 = 0;
+  this.CAIRO_FORMAT_RGB24 = 1;
+  this.CAIRO_FORMAT_A8 = 2;
+  this.CAIRO_FORMAT_A1 = 3;
+
   this.cairo_t = ctypes.StructType("cairo_t");
+  this.cairo_surface_t = ctypes.StructType("cairo_surface_t");
 
   lib.lazy_bind("cairo_rectangle", ctypes.void_t, this.cairo_t.ptr, ctypes.double, ctypes.double, ctypes.double, ctypes.double);
   lib.lazy_bind("cairo_set_source_rgb", ctypes.void_t, this.cairo_t.ptr, ctypes.double, ctypes.double, ctypes.double);
   lib.lazy_bind("cairo_fill", ctypes.void_t, this.cairo_t.ptr);
   lib.lazy_bind("cairo_move_to", ctypes.void_t, this.cairo_t.ptr, ctypes.double, ctypes.double);
+  lib.lazy_bind("cairo_image_surface_create", this.cairo_surface_t.ptr, this.cairo_format_t, ctypes.int, ctypes.int);
+  lib.lazy_bind("cairo_surface_destroy", ctypes.void_t, this.cairo_surface_t.ptr);
+  lib.lazy_bind("cairo_create", this.cairo_t.ptr, this.cairo_surface_t.ptr);
   lib.lazy_bind("cairo_destroy", ctypes.void_t, this.cairo_t.ptr);
 
 }
diff --git a/src/modules/ctypes/linux/gtk2/gdk.jsm b/src/modules/ctypes/linux/gdk23.jsm
similarity index 76%
copy from src/modules/ctypes/linux/gtk2/gdk.jsm
copy to src/modules/ctypes/linux/gdk23.jsm
index 27cf198..6bb5f82 100644
--- a/src/modules/ctypes/linux/gtk2/gdk.jsm
+++ b/src/modules/ctypes/linux/gdk23.jsm
@@ -1,59 +1,21 @@
-/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- *	 Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Firetray
- *
- * The Initial Developer of the Original Code is
- * Mozilla Messaging, Ltd.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *    Mike Conley <mconley at mozillamessaging.com>
- *    Foudil Brétel <foudil.newbie+amo at gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-var EXPORTED_SYMBOLS = [ "gdk" ];
-
-const GDK_LIBNAME = "gdk-x11-2.0";
-const GDK_ABIS    = [ 0 ];
+/*
+ * This module contains definitions common to gtk2 and gtk3.
+ * It is thus ONLY MEANT TO BE IMPORTED BY gtk.jsm modules !
+ */
+var EXPORTED_SYMBOLS = [ "gdk23_defines" ];
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/ctypes.jsm");
-Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
 Cu.import("resource://firetray/ctypes/linux/cairo.jsm");
 Cu.import("resource://firetray/ctypes/linux/glib.jsm");
 Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
 Cu.import("resource://firetray/ctypes/linux/x11.jsm");
 
-function gdk_defines(lib) {
+function gdk23_defines(lib) {
+
   this.GdkInterpType = ctypes.int; // enum
   this.GDK_INTERP_NEAREST  = 0;
   this.GDK_INTERP_TILES    = 1;
@@ -146,6 +108,10 @@ function gdk_defines(lib) {
   this.GdkColorspace = ctypes.int;     // enum
   this.GDK_COLORSPACE_RGB = 0;
 
+  this.GdkWindowClass = ctypes.int;     // enum
+  this.GDK_INPUT_OUTPUT = 0;
+  this.GDK_INPUT_ONLY   = 1;
+
   this.GdkWindow = ctypes.StructType("GdkWindow");
   this.GdkByteOrder = ctypes.int; // enum
   this.GdkVisualType = ctypes.int; // enum
@@ -180,27 +146,8 @@ function gdk_defines(lib) {
   this.GdkCursor = ctypes.StructType("GdkCursor");
   this.GdkWindowTypeHint = ctypes.StructType("GdkWindowTypeHint");
   this.GdkWindowClass = ctypes.StructType("GdkWindowClass");
-  this.GdkWindowAttributes = ctypes.StructType("GdkWindowAttributes", [
-    { "title": gobject.gchar },
-    { "event_mask": gobject.gint },
-    { "x": gobject.gint },
-    { "y": gobject.gint },
-    { "width": gobject.gint },
-    { "height": gobject.gint },
-    { "wclass": gobject.gint },
-    { "visual": this.GdkVisual.ptr },
-    { "colormap": this.GdkColormap.ptr },
-    { "window_type": gobject.gint },
-    { "cursor": this.GdkCursor.ptr },
-    { "wmclass_name": gobject.gchar },
-    { "wmclass_class": gobject.gchar },
-    { "override_redirect": gobject.gboolean },
-    { "type_hint": gobject.gint }
-  ]);
   this.GdkPixbuf = ctypes.StructType("GdkPixbuf");
   this.GdkScreen = ctypes.StructType("GdkScreen");
-  this.GdkPixmap = ctypes.StructType("GdkPixmap");
-  this.GdkDrawable = ctypes.StructType("GdkDrawable");
   this.GdkGC = ctypes.StructType("GdkGC");
   this.GdkXEvent = ctypes.void_t; // will probably be cast to XEvent
   this.GdkEvent = ctypes.void_t;
@@ -257,8 +204,6 @@ function gdk_defines(lib) {
   lib.lazy_bind("gdk_error_trap_push", ctypes.void_t);
   lib.lazy_bind("gdk_error_trap_pop", gobject.gint);
 
-  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);
   lib.lazy_bind("gdk_window_hide", ctypes.void_t, this.GdkWindow.ptr);
@@ -284,20 +229,13 @@ function gdk_defines(lib) {
   lib.lazy_bind("gdk_pixbuf_get_byte_length", gobject.gsize, this.GdkPixbuf.ptr);
   lib.lazy_bind("gdk_pixbuf_copy", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr);
 
+  lib.lazy_bind("gdk_screen_get_system_visual", this.GdkVisual.ptr, this.GdkScreen.ptr);
   lib.lazy_bind("gdk_screen_get_system_colormap", this.GdkColormap.ptr, this.GdkScreen.ptr);
   lib.lazy_bind("gdk_colormap_get_visual", this.GdkVisual.ptr, this.GdkColormap.ptr);
   lib.lazy_bind("gdk_color_parse", gobject.gboolean, gobject.gchar.ptr, this.GdkColor.ptr);
   lib.lazy_bind("gdk_colormap_alloc_color", gobject.gboolean, this.GdkColormap.ptr, this.GdkColor.ptr, gobject.gboolean, gobject.gboolean);
-  lib.lazy_bind("gdk_pixmap_new", this.GdkPixmap.ptr, this.GdkDrawable.ptr, gobject.gint, gobject.gint, gobject.gint);
-
-  // DEPRECATED
-  // lib.lazy_bind("gdk_gc_new", this.GdkGC.ptr, this.GdkDrawable.ptr);
-  // lib.lazy_bind("gdk_gc_set_foreground", ctypes.void_t, this.GdkGC.ptr, this.GdkColor.ptr);
-  // lib.lazy_bind("gdk_draw_rectangle", ctypes.void_t, this.GdkDrawable.ptr, this.GdkGC.ptr, gobject.gboolean, gobject.gint, gobject.gint, gobject.gint, gobject.gint);
 
-  lib.lazy_bind("gdk_cairo_create", cairo.cairo_t.ptr, this.GdkDrawable.ptr);
   lib.lazy_bind("gdk_cairo_set_source_color", ctypes.void_t, cairo.cairo_t.ptr, this.GdkColor.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_from_drawable", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, this.GdkDrawable.ptr, this.GdkColormap.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int);
   lib.lazy_bind("gdk_pixbuf_add_alpha", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, gobject.gboolean, gobject.guchar, gobject.guchar, gobject.guchar);
   lib.lazy_bind("gdk_pixbuf_composite", ctypes.void_t, this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.double, ctypes.double, ctypes.double, ctypes.double, this.GdkInterpType, ctypes.int);
 
@@ -316,7 +254,6 @@ function gdk_defines(lib) {
   lib.lazy_bind("gdk_x11_display_get_xdisplay", x11.Display.ptr, this.GdkDisplay.ptr);
   lib.lazy_bind("gdk_window_get_state", this.GdkWindowState, this.GdkWindow.ptr);
   lib.lazy_bind("gdk_window_get_position", ctypes.void_t, this.GdkWindow.ptr, gobject.gint.ptr, gobject.gint.ptr);
-  lib.lazy_bind("gdk_drawable_get_size", ctypes.void_t, this.GdkDrawable.ptr, gobject.gint.ptr, gobject.gint.ptr);
   // lib.lazy_bind("gdk_window_get_geometry", ctypes.void_t, this.GdkWindow.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr);
   lib.lazy_bind("gdk_window_move_resize", ctypes.void_t, this.GdkWindow.ptr, gobject.gint, gobject.gint, gobject.gint, gobject.gint);
   lib.lazy_bind("gdk_window_get_user_data", ctypes.void_t, this.GdkWindow.ptr, gobject.gpointer.ptr);
@@ -329,5 +266,3 @@ function gdk_defines(lib) {
   lib.lazy_bind("gdk_display_get_n_screens", gobject.gint, this.GdkDisplay.ptr);
   lib.lazy_bind("gdk_display_get_screen", this.GdkScreen.ptr, this.GdkDisplay.ptr, gobject.gint);
 }
-
-new ctypes_library(GDK_LIBNAME, GDK_ABIS, gdk_defines, this);
diff --git a/src/modules/ctypes/linux/gtk2/gdk.jsm b/src/modules/ctypes/linux/gtk2/gdk.jsm
index 27cf198..d14b61f 100644
--- a/src/modules/ctypes/linux/gtk2/gdk.jsm
+++ b/src/modules/ctypes/linux/gtk2/gdk.jsm
@@ -49,139 +49,38 @@ const Ci = Components.interfaces;
 Cu.import("resource://gre/modules/ctypes.jsm");
 Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
 Cu.import("resource://firetray/ctypes/linux/cairo.jsm");
-Cu.import("resource://firetray/ctypes/linux/glib.jsm");
 Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
 Cu.import("resource://firetray/ctypes/linux/x11.jsm");
+Cu.import("resource://firetray/ctypes/linux/gdk23.jsm");
 
 function gdk_defines(lib) {
-  this.GdkInterpType = ctypes.int; // enum
-  this.GDK_INTERP_NEAREST  = 0;
-  this.GDK_INTERP_TILES    = 1;
-  this.GDK_INTERP_BILINEAR = 2;
-  this.GDK_INTERP_HYPE     = 3;
-  this.GdkFilterReturn = ctypes.int; // enum
-  this.GDK_FILTER_CONTINUE  = 0;
-  this.GDK_FILTER_TRANSLATE = 1;
-  this.GDK_FILTER_REMOVE    = 2;
-  this.GdkWindowState = ctypes.int; // enum
-  this.GDK_WINDOW_STATE_WITHDRAWN  = 1 << 0,
-  this.GDK_WINDOW_STATE_ICONIFIED  = 1 << 1,
-  this.GDK_WINDOW_STATE_MAXIMIZED  = 1 << 2,
-  this.GDK_WINDOW_STATE_STICKY     = 1 << 3,
-  this.GDK_WINDOW_STATE_FULLSCREEN = 1 << 4,
-  this.GDK_WINDOW_STATE_ABOVE      = 1 << 5,
-  this.GDK_WINDOW_STATE_BELOW      = 1 << 6;
-  this.GdkEventType = ctypes.int; // enum
-  this.GDK_NOTHING           = -1;
-  this.GDK_DELETE            = 0;
-  this.GDK_DESTROY           = 1;
-  this.GDK_EXPOSE            = 2;
-  this.GDK_MOTION_NOTIFY     = 3;
-  this.GDK_BUTTON_PRESS      = 4;
-  this.GDK_2BUTTON_PRESS     = 5;
-  this.GDK_3BUTTON_PRESS     = 6;
-  this.GDK_BUTTON_RELEASE    = 7;
-  this.GDK_KEY_PRESS         = 8;
-  this.GDK_KEY_RELEASE       = 9;
-  this.GDK_ENTER_NOTIFY      = 10;
-  this.GDK_LEAVE_NOTIFY      = 11;
-  this.GDK_FOCUS_CHANGE      = 12;
-  this.GDK_CONFIGURE         = 13;
-  this.GDK_MAP               = 14;
-  this.GDK_UNMAP             = 15;
-  this.GDK_PROPERTY_NOTIFY   = 16;
-  this.GDK_SELECTION_CLEAR   = 17;
-  this.GDK_SELECTION_REQUEST = 18;
-  this.GDK_SELECTION_NOTIFY  = 19;
-  this.GDK_PROXIMITY_IN      = 20;
-  this.GDK_PROXIMITY_OUT     = 21;
-  this.GDK_DRAG_ENTER        = 22;
-  this.GDK_DRAG_LEAVE        = 23;
-  this.GDK_DRAG_MOTION       = 24;
-  this.GDK_DRAG_STATUS       = 25;
-  this.GDK_DROP_START        = 26;
-  this.GDK_DROP_FINISHED     = 27;
-  this.GDK_CLIENT_EVENT      = 28;
-  this.GDK_VISIBILITY_NOTIFY = 29;
-  this.GDK_NO_EXPOSE         = 30;
-  this.GDK_SCROLL            = 31;
-  this.GDK_WINDOW_STATE      = 32;
-  this.GDK_SETTING           = 33;
-  this.GDK_OWNER_CHANGE      = 34;
-  this.GDK_GRAB_BROKEN       = 35;
-  this.GDK_DAMAGE            = 36;
-  this.GDK_EVENT_LAST = 37;      /* helper variable for decls */
-  this.GdkPropMode = ctypes.int; // enum
-  this.GDK_PROP_MODE_REPLACE = 0;
-  this.GDK_PROP_MODE_PREPEN  = 1;
-  this.GDK_PROP_MODE_APPEND  = 2;
-  this.GdkScrollDirection = ctypes.int; // enum
-  this.GDK_SCROLL_UP    = 0;
-  this.GDK_SCROLL_DOWN  = 1;
-  this.GDK_SCROLL_LEFT  = 2;
-  this.GDK_SCROLL_RIGHT = 3;
-  this.GdkEventMask = ctypes.int; // enum
-  this.GDK_EXPOSURE_MASK            = 1 << 1,
-  this.GDK_POINTER_MOTION_MASK      = 1 << 2,
-  this.GDK_POINTER_MOTION_HINT_MASK = 1 << 3,
-  this.GDK_BUTTON_MOTION_MASK       = 1 << 4,
-  this.GDK_BUTTON1_MOTION_MASK      = 1 << 5,
-  this.GDK_BUTTON2_MOTION_MASK      = 1 << 6,
-  this.GDK_BUTTON3_MOTION_MASK      = 1 << 7,
-  this.GDK_BUTTON_PRESS_MASK        = 1 << 8,
-  this.GDK_BUTTON_RELEASE_MASK      = 1 << 9,
-  this.GDK_KEY_PRESS_MASK           = 1 << 10,
-  this.GDK_KEY_RELEASE_MASK         = 1 << 11,
-  this.GDK_ENTER_NOTIFY_MASK        = 1 << 12,
-  this.GDK_LEAVE_NOTIFY_MASK        = 1 << 13,
-  this.GDK_FOCUS_CHANGE_MASK        = 1 << 14,
-  this.GDK_STRUCTURE_MASK           = 1 << 15,
-  this.GDK_PROPERTY_CHANGE_MASK     = 1 << 16,
-  this.GDK_VISIBILITY_NOTIFY_MASK   = 1 << 17,
-  this.GDK_PROXIMITY_IN_MASK        = 1 << 18,
-  this.GDK_PROXIMITY_OUT_MASK       = 1 << 19,
-  this.GDK_SUBSTRUCTURE_MASK        = 1 << 20,
-  this.GDK_SCROLL_MASK              = 1 << 21,
-  this.GDK_ALL_EVENTS_MASK          = 0x3FFFFE
-  this.GdkColorspace = ctypes.int;     // enum
-  this.GDK_COLORSPACE_RGB = 0;
 
-  this.GdkWindow = ctypes.StructType("GdkWindow");
-  this.GdkByteOrder = ctypes.int; // enum
-  this.GdkVisualType = ctypes.int; // enum
-  this.GdkVisual = ctypes.StructType("GdkVisual", [
-    { "parent_instance": gobject.GObject },
-    { "type": this.GdkVisualType },
-    { "depth": gobject.gint },
-    { "byte": this.GdkByteOrder },
-    { "colormap": gobject.gint },
-    { "bits": gobject.gint },
-    { "red_mask": gobject.guint32 },
-    { "red_shift": gobject.gint },
-    { "red_prec": gobject.gint },
-    { "green_mask": gobject.guint32 },
-    { "green_shift": gobject.gint },
-    { "green_prec": gobject.gint },
-    { "blue_mask": gobject.guint32 },
-    { "blue_shift": gobject.gint },
-    { "blue_prec": gobject.gint }
-  ]);
-  this.GdkColor = ctypes.StructType("GdkColor", [
-    { "pixel": gobject.guint32 },
-    { "red": gobject.guint16 },
-    { "green": gobject.guint16 },
-    { "blue": gobject.guint16 }
-  ]);
-  this.GdkColormap = ctypes.StructType("GdkColormap", [
-    { "size": gobject.gint },
-    { "colors": this.GdkColor.ptr }
-  ]);
-  this.GdkWindowType = ctypes.StructType("GdkWindowType");
-  this.GdkCursor = ctypes.StructType("GdkCursor");
-  this.GdkWindowTypeHint = ctypes.StructType("GdkWindowTypeHint");
-  this.GdkWindowClass = ctypes.StructType("GdkWindowClass");
+  gdk23_defines.call(this, lib);
+
+  this.GdkWindowAttributesType = ctypes.int; // enum
+  this.GDK_WA_TITLE     = 1 << 1;
+  this.GDK_WA_X         = 1 << 2;
+  this.GDK_WA_Y         = 1 << 3;
+  this.GDK_WA_CURSOR    = 1 << 4;
+  this.GDK_WA_COLORMAP  = 1 << 5;
+  this.GDK_WA_VISUAL    = 1 << 6;
+  this.GDK_WA_WMCLASS   = 1 << 7;
+  this.GDK_WA_NOREDIR   = 1 << 8;
+  this.GDK_WA_TYPE_HINT = 1 << 9;
+
+  this.GdkWindowType        = ctypes.int; // enum
+  this.GDK_WINDOW_ROOT      = 0;
+  this.GDK_WINDOW_TOPLEVEL  = 1;
+  this.GDK_WINDOW_CHILD     = 2;
+  this.GDK_WINDOW_DIALOG    = 3;
+  this.GDK_WINDOW_TEMP      = 4;
+  this.GDK_WINDOW_FOREIGN   = 5;
+  this.GDK_WINDOW_OFFSCREEN = 6;
+
+  this.GdkPixmap = ctypes.StructType("GdkPixmap");
+  this.GdkDrawable = ctypes.StructType("GdkDrawable");
   this.GdkWindowAttributes = ctypes.StructType("GdkWindowAttributes", [
-    { "title": gobject.gchar },
+    { "title": gobject.gchar.ptr },
     { "event_mask": gobject.gint },
     { "x": gobject.gint },
     { "y": gobject.gint },
@@ -197,137 +96,14 @@ function gdk_defines(lib) {
     { "override_redirect": gobject.gboolean },
     { "type_hint": gobject.gint }
   ]);
-  this.GdkPixbuf = ctypes.StructType("GdkPixbuf");
-  this.GdkScreen = ctypes.StructType("GdkScreen");
-  this.GdkPixmap = ctypes.StructType("GdkPixmap");
-  this.GdkDrawable = ctypes.StructType("GdkDrawable");
-  this.GdkGC = ctypes.StructType("GdkGC");
-  this.GdkXEvent = ctypes.void_t; // will probably be cast to XEvent
-  this.GdkEvent = ctypes.void_t;
-  this.GdkDisplay = ctypes.StructType("GdkDisplay");
-  this.GdkFilterFunc = ctypes.voidptr_t;
-  this.GdkEventWindowState = ctypes.StructType("GdkEventWindowState", [
-    { "type": this.GdkEventType },
-    { "window": this.GdkWindow.ptr },
-    { "send_event": gobject.gint8 },
-    { "changed_mask": this.GdkWindowState },
-    { "new_window_state": this.GdkWindowState },
-  ]);
-  this.GdkDevice = ctypes.StructType("GdkDevice");
-  this.GdkEventScroll = ctypes.StructType("GdkEventScroll", [
-    { "type": this.GdkEventType },
-    { "window": this.GdkWindow.ptr },
-    { "send_event": gobject.gint8 },
-    { "time": gobject.guint32 },
-    { "x": gobject.gdouble },
-    { "y": gobject.gdouble },
-    { "state": gobject.guint },
-    { "direction": this.GdkScrollDirection },
-    { "device": this.GdkDevice.ptr },
-    { "x_root": gobject.gdouble },
-    { "y_root": gobject.gdouble }
-  ]);
-  this.GdkAtom = ctypes.StructType("GdkAtom");
-  this.GdkEventButton = ctypes.StructType("GdkEventButton", [
-    { "type": this.GdkEventType },
-    { "window": this.GdkWindow.ptr },
-    { "send_event": gobject.gint8 },
-    { "time": gobject.guint32 },
-    { "x": gobject.gdouble },
-    { "y": gobject.gdouble },
-    { "axes": gobject.gdouble.ptr },
-    { "state": gobject.guint },
-    { "button": gobject.guint },
-    { "device": this.GdkDevice.ptr },
-    { "x_root": gobject.gdouble },
-    { "y_root": gobject.gdouble }
-  ]);
-  this.GdkEventFocus = ctypes.StructType("GdkEventFocus", [
-    { "type": this.GdkEventType },
-    { "window": this.GdkWindow.ptr },
-    { "send_event": gobject.gint8 },
-    { "in": gobject.gint16 },
-  ]);
-
-  this.GdkFilterFunc_t = ctypes.FunctionType(
-    ctypes.default_abi, this.GdkFilterReturn,
-    [this.GdkXEvent.ptr, this.GdkEvent.ptr, gobject.gpointer]).ptr;
-
-  lib.lazy_bind("gdk_flush", ctypes.void_t);
-  lib.lazy_bind("gdk_error_trap_push", ctypes.void_t);
-  lib.lazy_bind("gdk_error_trap_pop", gobject.gint);
-
-  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);
-  lib.lazy_bind("gdk_window_hide", ctypes.void_t, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_show_unraised", ctypes.void_t, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_screen_get_default", this.GdkScreen.ptr);
-  lib.lazy_bind("gdk_screen_get_toplevel_windows", gobject.GList.ptr, this.GdkScreen.ptr);
-  lib.lazy_bind("gdk_screen_get_number", gobject.gint, this.GdkScreen.ptr);
-  lib.lazy_bind("gdk_screen_get_display", this.GdkDisplay.ptr, this.GdkScreen.ptr);
-  lib.lazy_bind("gdk_x11_get_xatom_by_name_for_display", x11.Atom, this.GdkDisplay.ptr, gobject.gchar.ptr);
-  lib.lazy_bind("gdk_pixbuf_new_from_file", this.GdkPixbuf.ptr, gobject.gchar.ptr, glib.GError.ptr.ptr);
-  lib.lazy_bind("gdk_pixbuf_copy", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_composite", ctypes.void_t, this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.double, ctypes.double, ctypes.double, ctypes.double, ctypes.int, ctypes.int);
-  lib.lazy_bind("gdk_pixbuf_get_has_alpha", gobject.gboolean, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_add_alpha", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, gobject.gboolean, gobject.guchar, gobject.guchar, gobject.guchar);
-  lib.lazy_bind("gdk_pixbuf_get_colorspace", this.GdkColorspace, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_n_channels", ctypes.int, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_has_alpha", gobject.gboolean, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_bits_per_sample", ctypes.int, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_pixels", gobject.guchar.ptr, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_width", ctypes.int, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_height", ctypes.int, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_rowstride", ctypes.int, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_byte_length", gobject.gsize, this.GdkPixbuf.ptr);
-  lib.lazy_bind("gdk_pixbuf_copy", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr);
-
-  lib.lazy_bind("gdk_screen_get_system_colormap", this.GdkColormap.ptr, this.GdkScreen.ptr);
-  lib.lazy_bind("gdk_colormap_get_visual", this.GdkVisual.ptr, this.GdkColormap.ptr);
-  lib.lazy_bind("gdk_color_parse", gobject.gboolean, gobject.gchar.ptr, this.GdkColor.ptr);
-  lib.lazy_bind("gdk_colormap_alloc_color", gobject.gboolean, this.GdkColormap.ptr, this.GdkColor.ptr, gobject.gboolean, gobject.gboolean);
-  lib.lazy_bind("gdk_pixmap_new", this.GdkPixmap.ptr, this.GdkDrawable.ptr, gobject.gint, gobject.gint, gobject.gint);
-
-  // DEPRECATED
-  // lib.lazy_bind("gdk_gc_new", this.GdkGC.ptr, this.GdkDrawable.ptr);
-  // lib.lazy_bind("gdk_gc_set_foreground", ctypes.void_t, this.GdkGC.ptr, this.GdkColor.ptr);
-  // lib.lazy_bind("gdk_draw_rectangle", ctypes.void_t, this.GdkDrawable.ptr, this.GdkGC.ptr, gobject.gboolean, gobject.gint, gobject.gint, gobject.gint, gobject.gint);
 
   lib.lazy_bind("gdk_cairo_create", cairo.cairo_t.ptr, this.GdkDrawable.ptr);
-  lib.lazy_bind("gdk_cairo_set_source_color", ctypes.void_t, cairo.cairo_t.ptr, this.GdkColor.ptr);
-  lib.lazy_bind("gdk_pixbuf_get_from_drawable", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, this.GdkDrawable.ptr, this.GdkColormap.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int);
-  lib.lazy_bind("gdk_pixbuf_add_alpha", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, gobject.gboolean, gobject.guchar, gobject.guchar, gobject.guchar);
-  lib.lazy_bind("gdk_pixbuf_composite", ctypes.void_t, this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.double, ctypes.double, ctypes.double, ctypes.double, this.GdkInterpType, ctypes.int);
-
-  lib.lazy_bind("gdk_window_stick", ctypes.void_t, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_iconify", ctypes.void_t, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_deiconify", ctypes.void_t, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_set_title", ctypes.void_t, this.GdkWindow.ptr, gobject.gchar.ptr);
-  lib.lazy_bind("gdk_window_beep", ctypes.void_t, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_get_width", ctypes.int, this.GdkWindow.ptr);
-
-  lib.lazy_bind("gdk_window_get_events", this.GdkEventMask, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_set_events", ctypes.void_t, this.GdkWindow.ptr, this.GdkEventMask);
-  lib.lazy_bind("gdk_window_add_filter", ctypes.void_t, this.GdkWindow.ptr, this.GdkFilterFunc, gobject.gpointer);
-  lib.lazy_bind("gdk_window_remove_filter", ctypes.void_t, this.GdkWindow.ptr, this.GdkFilterFunc, gobject.gpointer);
-  lib.lazy_bind("gdk_display_get_default", this.GdkDisplay.ptr);
-  lib.lazy_bind("gdk_x11_display_get_xdisplay", x11.Display.ptr, this.GdkDisplay.ptr);
-  lib.lazy_bind("gdk_window_get_state", this.GdkWindowState, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_get_position", ctypes.void_t, this.GdkWindow.ptr, gobject.gint.ptr, gobject.gint.ptr);
   lib.lazy_bind("gdk_drawable_get_size", ctypes.void_t, this.GdkDrawable.ptr, gobject.gint.ptr, gobject.gint.ptr);
-  // lib.lazy_bind("gdk_window_get_geometry", ctypes.void_t, this.GdkWindow.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr);
-  lib.lazy_bind("gdk_window_move_resize", ctypes.void_t, this.GdkWindow.ptr, gobject.gint, gobject.gint, gobject.gint, gobject.gint);
-  lib.lazy_bind("gdk_window_get_user_data", ctypes.void_t, this.GdkWindow.ptr, gobject.gpointer.ptr);
-  lib.lazy_bind("gdk_atom_intern", this.GdkAtom, gobject.gchar.ptr, gobject.gboolean);
-  lib.lazy_bind("gdk_property_change", ctypes.void_t, this.GdkWindow.ptr, this.GdkAtom, this.GdkAtom, gobject.gint, this.GdkPropMode, gobject.guchar.ptr, gobject.gint);
-  lib.lazy_bind("gdk_window_get_toplevel", this.GdkWindow.ptr, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_window_get_effective_toplevel", this.GdkWindow.ptr, this.GdkWindow.ptr);
-  lib.lazy_bind("gdk_screen_get_active_window", this.GdkWindow.ptr, this.GdkScreen.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_from_drawable", this.GdkPixbuf.ptr, this.GdkPixbuf.ptr, this.GdkDrawable.ptr, this.GdkColormap.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int);
+  lib.lazy_bind("gdk_pixmap_new", this.GdkPixmap.ptr, this.GdkDrawable.ptr, gobject.gint, gobject.gint, gobject.gint);
+  lib.lazy_bind("gdk_window_new", this.GdkWindow.ptr, this.GdkWindow.ptr, this.GdkWindowAttributes.ptr, gobject.gint);
+  lib.lazy_bind("gdk_x11_drawable_get_xid", x11.XID, this.GdkDrawable.ptr);
 
-  lib.lazy_bind("gdk_display_get_n_screens", gobject.gint, this.GdkDisplay.ptr);
-  lib.lazy_bind("gdk_display_get_screen", this.GdkScreen.ptr, this.GdkDisplay.ptr, gobject.gint);
 }
 
 new ctypes_library(GDK_LIBNAME, GDK_ABIS, gdk_defines, this);
diff --git a/src/modules/ctypes/linux/gtk2/gtk.jsm b/src/modules/ctypes/linux/gtk2/gtk.jsm
index ce58024..6f657f4 100644
--- a/src/modules/ctypes/linux/gtk2/gtk.jsm
+++ b/src/modules/ctypes/linux/gtk2/gtk.jsm
@@ -17,6 +17,7 @@ Cu.import("resource://firetray/ctypes/linux/pango.jsm");
 Cu.import("resource://firetray/ctypes/linux/gtk2/gdk.jsm");
 
 function gtk_defines(lib) {
+
   this.FIRETRAY_REQUIRED_GTK_MAJOR_VERSION = 2;
   this.FIRETRAY_REQUIRED_GTK_MINOR_VERSION = 20;
   this.FIRETRAY_REQUIRED_GTK_MICRO_VERSION = 0;
@@ -98,6 +99,8 @@ function gtk_defines(lib) {
     [this.GtkWidget.ptr, gdk.GdkEventFocus.ptr, gobject.gpointer]).ptr;
 
   lib.lazy_bind("gtk_check_version", gobject.gchar.ptr, gobject.guint, gobject.guint, gobject.guint);
+  this.gtk_get_major_version = function(){return 2;};
+  this.gtk_get_minor_version = function(){}; // undefined
 
   lib.lazy_bind("gtk_icon_theme_get_default", this.GtkIconTheme.ptr);
   lib.lazy_bind("gtk_icon_theme_get_for_screen", this.GtkIconTheme.ptr, gdk.GdkScreen.ptr);
diff --git a/src/modules/ctypes/linux/gtk23.jsm b/src/modules/ctypes/linux/gtk23.jsm
new file mode 100644
index 0000000..6748fb0
--- /dev/null
+++ b/src/modules/ctypes/linux/gtk23.jsm
@@ -0,0 +1,21 @@
+/*
+ * This module contains definitions common to gtk2 and gtk3.
+ * It is thus ONLY MEANT TO BE IMPORTED BY gtk.jsm modules !
+ */
+var EXPORTED_SYMBOLS = [ "gtk" ];
+
+const Cu = Components.utils;
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function gtk23_defines(lib) {
+  /* FIXME: We can't easily share code btw. gtk2/gtk.jsm and gtk3/gtk.jsm
+   because we'd need to import a gdk.jsm into gtk23.jsm... We can't import
+   gdk23.jsm either because it's not supposed to provide 'gdk'. We can't even
+   share say everything but gdk-related code because for ex. GtkWidget needs
+   gdk, and is needed by *a lot* of other definitions. So we'll just keep it
+   simple and have duplicate code in gtk2/gtk.jsm and gtk3/gtk.jsm for now.
+
+   We'll probably drop support for gtk2 when all Moz apps are ported to
+   gtk3. */
+}
diff --git a/src/modules/ctypes/linux/gtk3/appindicator.jsm b/src/modules/ctypes/linux/gtk3/appindicator.jsm
new file mode 100644
index 0000000..0a8679a
--- /dev/null
+++ b/src/modules/ctypes/linux/gtk3/appindicator.jsm
@@ -0,0 +1,58 @@
+/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+var EXPORTED_SYMBOLS = [ "appind" ];
+
+const APPINDICATOR_LIBNAME = "appindicator3";
+const APPINDICATOR_ABIS    = [ 1 ];
+
+const Cu = Components.utils;
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
+Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
+Cu.import("resource://firetray/ctypes/linux/gtk3/gtk.jsm");
+
+function appindicator_defines(lib) {
+  this.AppIndicator = ctypes.StructType("AppIndicator");
+
+  this.INDICATOR_APPLICATION_DBUS_ADDR  = "com.canonical.indicator.application";
+  this.INDICATOR_APPLICATION_DBUS_OBJ   = "/com/canonical/indicator/application/service";
+  this.INDICATOR_APPLICATION_DBUS_IFACE = "com.canonical.indicator.application.service";
+  this.NOTIFICATION_WATCHER_DBUS_ADDR   = "org.kde.StatusNotifierWatcher";
+  this.NOTIFICATION_WATCHER_DBUS_OBJ    = "/StatusNotifierWatcher";
+  this.NOTIFICATION_WATCHER_DBUS_IFACE  = "org.kde.StatusNotifierWatcher";
+  this.NOTIFICATION_ITEM_DBUS_IFACE     = "org.kde.StatusNotifierItem";
+  this.NOTIFICATION_ITEM_DEFAULT_OBJ    = "/StatusNotifierItem";
+  this.NOTIFICATION_APPROVER_DBUS_IFACE = "org.ayatana.StatusNotifierApprover";
+
+  this.AppIndicatorCategory = ctypes.int;             // enum
+  this.APP_INDICATOR_CATEGORY_APPLICATION_STATUS = 0; /*< nick=ApplicationStatus >*/
+  this.APP_INDICATOR_CATEGORY_COMMUNICATIONS     = 1; /*< nick=Communications >*/
+  this.APP_INDICATOR_CATEGORY_SYSTEM_SERVICES    = 2; /*< nick=SystemServices >*/
+  this.APP_INDICATOR_CATEGORY_HARDWARE           = 3; /*< nick=Hardware >*/
+  this.APP_INDICATOR_CATEGORY_OTHER              = 4; /*< nick=Other >*/
+
+  this.AppIndicatorStatus = ctypes.int;    // enum
+  this.APP_INDICATOR_STATUS_PASSIVE   = 0; /*< nick=Passive >*/
+  this.APP_INDICATOR_STATUS_ACTIVE    = 1; /*< nick=Active >*/
+  this.APP_INDICATOR_STATUS_ATTENTION = 2; /*< nick=NeedsAttention >*/
+
+  lib.lazy_bind("app_indicator_new", this.AppIndicator.ptr, gobject.gchar.ptr, gobject.gchar.ptr, this.AppIndicatorCategory);
+  lib.lazy_bind("app_indicator_set_status", ctypes.void_t, this.AppIndicator.ptr, this.AppIndicatorStatus);
+  lib.lazy_bind("app_indicator_get_status", this.AppIndicatorStatus, this.AppIndicator.ptr);
+  lib.lazy_bind("app_indicator_set_menu", ctypes.void_t, this.AppIndicator.ptr, gtk.GtkMenu.ptr);
+  lib.lazy_bind("app_indicator_set_icon", ctypes.void_t, this.AppIndicator.ptr, gobject.gchar.ptr);
+  lib.lazy_bind("app_indicator_set_attention_icon", ctypes.void_t, this.AppIndicator.ptr, gobject.gchar.ptr);
+  lib.lazy_bind("app_indicator_set_label", ctypes.void_t, this.AppIndicator.ptr, gobject.gchar.ptr, gobject.gchar.ptr);
+  lib.lazy_bind("app_indicator_set_secondary_activate_target", ctypes.void_t, this.AppIndicator.ptr, gtk.GtkWidget.ptr);
+
+  this.ConnectionChangedCb_t = ctypes.FunctionType(
+    ctypes.default_abi, ctypes.void_t, [this.AppIndicator.ptr, gobject.gboolean, gobject.gpointer]).ptr;
+
+  this.OnScrollCb_t = ctypes.FunctionType(
+    ctypes.default_abi, ctypes.void_t, [this.AppIndicator.ptr, gobject.gint, gobject.guint, gobject.gpointer]).ptr;
+};
+
+var appind = new ctypes_library(APPINDICATOR_LIBNAME, APPINDICATOR_ABIS, appindicator_defines, this);
diff --git a/src/modules/ctypes/linux/gtk3/gdk.jsm b/src/modules/ctypes/linux/gtk3/gdk.jsm
new file mode 100644
index 0000000..849e066
--- /dev/null
+++ b/src/modules/ctypes/linux/gtk3/gdk.jsm
@@ -0,0 +1,69 @@
+/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+var EXPORTED_SYMBOLS = [ "gdk" ];
+
+const GDK_LIBNAME = "gdk-3";
+const GDK_ABIS    = [ 0 ];
+
+const Cu = Components.utils;
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
+Cu.import("resource://firetray/ctypes/linux/cairo.jsm");
+Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
+Cu.import("resource://firetray/ctypes/linux/x11.jsm");
+Cu.import("resource://firetray/ctypes/linux/gdk23.jsm");
+
+function gdk_defines(lib) {
+
+  gdk23_defines.call(this, lib);
+
+  this.GDK_SCROLL_SMOOTH = 4;
+
+  this.GdkWindowAttributesType = ctypes.int; // enum
+  this.GDK_WA_TITLE     = 1 << 1;
+  this.GDK_WA_X         = 1 << 2;
+  this.GDK_WA_Y         = 1 << 3;
+  this.GDK_WA_CURSOR    = 1 << 4;
+  this.GDK_WA_VISUAL    = 1 << 5,
+  this.GDK_WA_WMCLASS   = 1 << 6,
+  this.GDK_WA_NOREDIR   = 1 << 7,
+  this.GDK_WA_TYPE_HINT = 1 << 8
+
+  this.GdkWindowType         = ctypes.int; // enum
+  this.GDK_WINDOW_ROOT       = 0;
+  this.GDK_WINDOW_TOPLEVEL   = 1;
+  this.GDK_WINDOW_CHILD      = 2;
+  this.GDK_WINDOW_TEMP       = 3;
+  this.GDK_WINDOW_FOREIGN    = 4;
+  this.GDK_WINDOW_OFFSCREEN  = 5;
+  this.GDK_WINDOW_SUBSURFACE = 6;
+
+  this.GdkWindowAttr = ctypes.StructType("GdkWindowAttr", [
+    { "title": gobject.gchar.ptr },
+    { "event_mask": gobject.gint },
+    { "x": gobject.gint },
+    { "y": gobject.gint },
+    { "width": gobject.gint },
+    { "height": gobject.gint },
+    { "wclass": gobject.gint },
+    { "visual": this.GdkVisual.ptr },
+    { "window_type": gobject.gint },
+    { "cursor": this.GdkCursor.ptr },
+    { "wmclass_name": gobject.gchar },
+    { "wmclass_class": gobject.gchar },
+    { "override_redirect": gobject.gboolean },
+    { "type_hint": gobject.gint }
+  ]);
+
+  lib.lazy_bind("gdk_cairo_create", cairo.cairo_t.ptr, this.GdkWindow.ptr);
+  lib.lazy_bind("gdk_pixbuf_get_from_window", this.GdkPixbuf.ptr, this.GdkWindow.ptr, ctypes.int, ctypes.int, ctypes.int, ctypes.int);
+  lib.lazy_bind("gdk_x11_window_get_xid", x11.XID, this.GdkWindow.ptr);
+  lib.lazy_bind("gdk_window_new", this.GdkWindow.ptr, this.GdkWindow.ptr, this.GdkWindowAttr.ptr, gobject.gint);
+  lib.lazy_bind("gdk_pixbuf_get_from_surface", this.GdkPixbuf.ptr, cairo.cairo_surface_t.ptr, gobject.gint, gobject.gint, gobject.gint, gobject.gint);
+
+}
+
+new ctypes_library(GDK_LIBNAME, GDK_ABIS, gdk_defines, this);
diff --git a/src/modules/ctypes/linux/gtk2/gtk.jsm b/src/modules/ctypes/linux/gtk3/gtk.jsm
similarity index 96%
copy from src/modules/ctypes/linux/gtk2/gtk.jsm
copy to src/modules/ctypes/linux/gtk3/gtk.jsm
index ce58024..7f306e7 100644
--- a/src/modules/ctypes/linux/gtk2/gtk.jsm
+++ b/src/modules/ctypes/linux/gtk3/gtk.jsm
@@ -2,7 +2,7 @@
 
 var EXPORTED_SYMBOLS = [ "gtk" ];
 
-const GTK_LIBNAME = "gtk-x11-2.0";
+const GTK_LIBNAME = "gtk-3";
 const GTK_ABIS    = [ 0 ];
 
 const Cu = Components.utils;
@@ -14,11 +14,12 @@ Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
 Cu.import("resource://firetray/ctypes/linux/gio.jsm");
 Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
 Cu.import("resource://firetray/ctypes/linux/pango.jsm");
-Cu.import("resource://firetray/ctypes/linux/gtk2/gdk.jsm");
+Cu.import("resource://firetray/ctypes/linux/gtk3/gdk.jsm");
 
 function gtk_defines(lib) {
-  this.FIRETRAY_REQUIRED_GTK_MAJOR_VERSION = 2;
-  this.FIRETRAY_REQUIRED_GTK_MINOR_VERSION = 20;
+
+  this.FIRETRAY_REQUIRED_GTK_MAJOR_VERSION = 3;
+  this.FIRETRAY_REQUIRED_GTK_MINOR_VERSION = 4;
   this.FIRETRAY_REQUIRED_GTK_MICRO_VERSION = 0;
 
   this.GtkIconSize = ctypes.int; // enum
@@ -98,6 +99,8 @@ function gtk_defines(lib) {
     [this.GtkWidget.ptr, gdk.GdkEventFocus.ptr, gobject.gpointer]).ptr;
 
   lib.lazy_bind("gtk_check_version", gobject.gchar.ptr, gobject.guint, gobject.guint, gobject.guint);
+  lib.lazy_bind("gtk_get_major_version", gobject.guint);
+  lib.lazy_bind("gtk_get_minor_version", gobject.guint);
 
   lib.lazy_bind("gtk_icon_theme_get_default", this.GtkIconTheme.ptr);
   lib.lazy_bind("gtk_icon_theme_get_for_screen", this.GtkIconTheme.ptr, gdk.GdkScreen.ptr);
@@ -106,7 +109,7 @@ function gtk_defines(lib) {
   lib.lazy_bind("gtk_icon_theme_prepend_search_path", ctypes.void_t, this.GtkIconTheme.ptr, gobject.gchar.ptr);
   lib.lazy_bind("gtk_icon_theme_choose_icon", this.GtkIconInfo.ptr, this.GtkIconTheme.ptr, gobject.gchar.ptr.array(), gobject.gint, this.GtkIconLookupFlags);
   lib.lazy_bind("gtk_icon_info_load_icon", gdk.GdkPixbuf.ptr, this.GtkIconInfo.ptr, glib.GError.ptr.ptr);
-  lib.lazy_bind("gtk_icon_info_free", ctypes.void_t, this.GtkIconInfo.ptr);
+  lib.lazy_bind("gtk_icon_info_free", ctypes.void_t, this.GtkIconInfo.ptr); // FIXME: gtk3 deprecated
 
   lib.lazy_bind("gtk_status_icon_new", this.GtkStatusIcon.ptr);
   lib.lazy_bind("gtk_status_icon_set_from_file", ctypes.void_t, this.GtkStatusIcon.ptr, ctypes.char.ptr);
diff --git a/src/modules/linux/FiretrayChatStatusIcon.jsm b/src/modules/linux/FiretrayChatStatusIcon.jsm
index 6d46d19..864495d 100644
--- a/src/modules/linux/FiretrayChatStatusIcon.jsm
+++ b/src/modules/linux/FiretrayChatStatusIcon.jsm
@@ -131,7 +131,11 @@ firetray.ChatStatusIcon = {
 
     // create pixbuf
     let pixbuf = gdk.gdk_pixbuf_copy(gtk.gtk_icon_info_load_icon(icon_info, null));
-    gtk.gtk_icon_info_free(icon_info);   // gobject.g_object_unref(icon_info) in 3.8
+if (gtk.gtk_get_major_version() == 3 && gtk.gtk_get_minor_version() >= 8) { // gtk3
+    gobject.g_object_unref(icon_info);
+} else {
+    gtk.gtk_icon_info_free(icon_info);
+}
 
     // checks
     if (gdk.gdk_pixbuf_get_colorspace(pixbuf) != gdk.GDK_COLORSPACE_RGB)
diff --git a/src/modules/linux/FiretrayGtkStatusIcon.jsm b/src/modules/linux/FiretrayGtkStatusIcon.jsm
index 2d27c8a..c0f7d0e 100644
--- a/src/modules/linux/FiretrayGtkStatusIcon.jsm
+++ b/src/modules/linux/FiretrayGtkStatusIcon.jsm
@@ -218,7 +218,7 @@ firetray.Handler.setIconTooltip = function(toolTipStr) {
   return true;
 };
 
-firetray.Handler.setIconText = function(text, color) { // FIXME: function too long
+firetray.Handler.setIconText = function(text, color) {
   log.debug("setIconText, color="+color);
   if (typeof(text) != "string")
     throw new TypeError();
@@ -232,27 +232,40 @@ firetray.Handler.setIconText = function(text, color) { // FIXME: function too lo
     let h = gdk.gdk_pixbuf_get_height(specialIcon);
 
     // prepare colors/alpha
-    let colorMap = gdk.gdk_screen_get_system_colormap(gdk.gdk_screen_get_default());
-    let visual = gdk.gdk_colormap_get_visual(colorMap);
-    let visualDepth = visual.contents.depth;
+/* FIXME: draw everything with cairo when dropping gtk2 support. Use
+ gdk_pixbuf_get_from_surface(). */
+if (firetray.Handler.app.widgetTk == "gtk2") {
+    var colorMap = gdk.gdk_screen_get_system_colormap(gdk.gdk_screen_get_default());
+    var visual = gdk.gdk_colormap_get_visual(colorMap);
+    var visualDepth = visual.contents.depth;
     log.debug("colorMap="+colorMap+" visual="+visual+" visualDepth="+visualDepth);
+}
     let fore = new gdk.GdkColor;
     fore.pixel = fore.red = fore.green = fore.blue = 0;
     let alpha  = new gdk.GdkColor;
     alpha.pixel = alpha.red = alpha.green = alpha.blue = 0xFFFF;
     if (!fore || !alpha)
-      log.warn("Undefined GdkColor fore or alpha");
+      log.warn("Undefined fore or alpha GdkColor");
     gdk.gdk_color_parse(color, fore.address());
     if(fore.red == alpha.red && fore.green == alpha.green && fore.blue == alpha.blue) {
       alpha.red=0; // make sure alpha is different from fore
     }
+if (firetray.Handler.app.widgetTk == "gtk2") {
     gdk.gdk_colormap_alloc_color(colorMap, fore.address(), true, true);
     gdk.gdk_colormap_alloc_color(colorMap, alpha.address(), true, true);
-
-    // build pixmap with rectangle
-    let pm = gdk.gdk_pixmap_new(null, w, h, visualDepth);
-    let pmDrawable = ctypes.cast(pm, gdk.GdkDrawable.ptr);
-    let cr = gdk.gdk_cairo_create(pmDrawable);
+}
+
+    // build text rectangle
+    let cr;
+if (firetray.Handler.app.widgetTk == "gtk2") {
+    var pm = gdk.gdk_pixmap_new(null, w, h, visualDepth);
+    var pmDrawable = ctypes.cast(pm, gdk.GdkDrawable.ptr);
+    cr = gdk.gdk_cairo_create(pmDrawable);
+} else {
+    // FIXME: gtk3 text position is incorrect.
+    var surface = cairo.cairo_image_surface_create(cairo.CAIRO_FORMAT_ARGB32, w, h);
+    cr = cairo.cairo_create(surface);
+}
     gdk.gdk_cairo_set_source_color(cr, alpha.address());
     cairo.cairo_rectangle(cr, 0, 0, w, h);
     cairo.cairo_set_source_rgb(cr, 1, 1, 1);
@@ -262,9 +275,9 @@ firetray.Handler.setIconText = function(text, color) { // FIXME: function too lo
     let scratch = gtk.gtk_window_new(gtk.GTK_WINDOW_TOPLEVEL);
     let layout = gtk.gtk_widget_create_pango_layout(scratch, null);
     gtk.gtk_widget_destroy(scratch);
-    let fnt = pango.pango_font_description_from_string("Sans 18");
-    pango.pango_font_description_set_weight(fnt,pango.PANGO_WEIGHT_SEMIBOLD);
-    pango.pango_layout_set_spacing(layout,0);
+    let fnt = pango.pango_font_description_from_string("Sans 32");
+    pango.pango_font_description_set_weight(fnt, pango.PANGO_WEIGHT_SEMIBOLD);
+    pango.pango_layout_set_spacing(layout, 0);
     pango.pango_layout_set_font_description(layout, fnt);
     log.debug("layout="+layout);
     log.debug("text="+text);
@@ -278,20 +291,21 @@ firetray.Handler.setIconText = function(text, color) { // FIXME: function too lo
     // fit text to the icon by decreasing font size
     while ( tw.value > (w - border) || th.value > (h - border) ) {
       sz = pango.pango_font_description_get_size(fnt);
-      if(sz < firetray.GtkStatusIcon.MIN_FONT_SIZE) {
+      if (sz < firetray.GtkStatusIcon.MIN_FONT_SIZE) {
         sz = firetray.GtkStatusIcon.MIN_FONT_SIZE;
         break;
       }
       sz -= pango.PANGO_SCALE;
-      pango.pango_font_description_set_size(fnt,sz);
+      pango.pango_font_description_set_size(fnt, sz);
       pango.pango_layout_set_font_description(layout, fnt);
       pango.pango_layout_get_pixel_size(layout, tw.address(), th.address());
     }
-    log.debug("tw="+tw.value+" th="+th.value);
+    log.debug("tw="+tw.value+" th="+th.value+" sz="+sz);
     pango.pango_font_description_free(fnt);
     // center text
     let px = (w-tw.value)/2;
     let py = (h-th.value)/2;
+    log.debug("px="+px+" py="+py);
 
     // draw text on pixmap
     gdk.gdk_cairo_set_source_color(cr, fore.address());
@@ -300,8 +314,15 @@ firetray.Handler.setIconText = function(text, color) { // FIXME: function too lo
     cairo.cairo_destroy(cr);
     gobject.g_object_unref(layout);
 
-    let buf = gdk.gdk_pixbuf_get_from_drawable(null, pmDrawable, null, 0, 0, 0, 0, w, h);
+    let buf = null;
+if (firetray.Handler.app.widgetTk == "gtk2") {
+    buf = gdk.gdk_pixbuf_get_from_drawable(null, pmDrawable, null, 0, 0, 0, 0, w, h);
     gobject.g_object_unref(pm);
+}
+else {
+    buf = gdk.gdk_pixbuf_get_from_surface(surface, 0, 0, w, h);
+    cairo.cairo_surface_destroy(surface);
+}
     log.debug("alpha="+alpha);
     let alphaRed = gobject.guint16(alpha.red);
     let alphaRed_guchar = ctypes.cast(alphaRed, gobject.guchar);
diff --git a/src/modules/linux/FiretrayPopupMenu.jsm b/src/modules/linux/FiretrayPopupMenu.jsm
index 73ccf9e..a5f772b 100644
--- a/src/modules/linux/FiretrayPopupMenu.jsm
+++ b/src/modules/linux/FiretrayPopupMenu.jsm
@@ -86,8 +86,20 @@ firetray.PopupMenu = {
     this.initialized = false;
   },
 
+  /* FIXME: gtk3 "GtkImageMenuItem has been deprecated since GTK+ 3.10".
+   GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+   GtkWidget *icon = gtk_image_new_from_icon_name ("folder-music-symbolic", GTK_ICON_SIZE_MENU);
+   GtkWidget *label = gtk_label_new ("Music");
+   GtkWidget *menu_item = gtk_menu_item_new ();
+   gtk_container_add (GTK_CONTAINER (box), icon);
+   gtk_container_add (GTK_CONTAINER (box), label);
+   gtk_container_add (GTK_CONTAINER (menu_item), box);
+   gtk_widget_show_all (menu_item);
+   */
   addItem: function(it) {
-    var menuItemLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel."+it.itemName); // shouldn't need to convert to utf8 later thank to js-ctypes
+    // shouldn't need to convert to utf8 later thank to js-ctypes
+    var menuItemLabel = firetray.Utils.strings
+          .GetStringFromName("popupMenu.itemLabel."+it.itemName);
     var menuItem = gtk.gtk_image_menu_item_new_with_label(menuItemLabel);
     var menuItemIcon = gtk.gtk_image_new_from_stock(it.iconName, gtk.GTK_ICON_SIZE_MENU);
     gtk.gtk_image_menu_item_set_image(menuItem, menuItemIcon);
diff --git a/src/modules/linux/FiretrayStatusIcon.jsm b/src/modules/linux/FiretrayStatusIcon.jsm
index 517e585..29ee653 100644
--- a/src/modules/linux/FiretrayStatusIcon.jsm
+++ b/src/modules/linux/FiretrayStatusIcon.jsm
@@ -203,6 +203,9 @@ firetray.StatusIcon = {
       else if (scroll_mode === "up_hides")
         firetray.Handler.showAllWindows();
       break;
+    case gdk.GDK_SCROLL_SMOOTH:
+      // ignore
+      break;
     default:
       log.error("SCROLL UNKNOWN");
     }
diff --git a/src/modules/linux/FiretrayWindow.jsm b/src/modules/linux/FiretrayWindow.jsm
index f8c56e1..32b38c3 100644
--- a/src/modules/linux/FiretrayWindow.jsm
+++ b/src/modules/linux/FiretrayWindow.jsm
@@ -157,14 +157,33 @@ firetray.Window.getGdkWindowFromGtkWindow = function(gtkWin) {
   return null;
 };
 
-firetray.Window.getXIDFromGdkWindow = function(gdkWin) {
-  return gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
-};
+if (firetray.Handler.app.widgetTk == "gtk2") {
 
-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));
-};
+  firetray.Window.getXIDFromGdkWindow = function(gdkWin) {
+    return gdk.gdk_x11_drawable_get_xid(ctypes.cast(gdkWin, gdk.GdkDrawable.ptr));
+  };
+
+  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));
+  };
+
+}
+else if (firetray.Handler.app.widgetTk == "gtk3") {
+
+  firetray.Window.getXIDFromGdkWindow = function(gdkWin) {
+    return gdk.gdk_x11_window_get_xid(gdkWin);
+  };
+
+  firetray.Window.getXIDFromGtkWidget = function(gtkWid) {
+    let gdkWin = gtk.gtk_widget_get_window(gtkWid);
+    return gdk.gdk_x11_window_get_xid(gdkWin);
+  };
+
+}
+else {
+  log.error("Unhandled widgetTk: "+firetray.Handler.app.widgetTk);
+}
 
 firetray.Window.addrPointedByInHex = function(ptr) {
   return "0x"+ctypes.cast(ptr, ctypes.uintptr_t.ptr).contents.toString(16);
@@ -499,16 +518,14 @@ firetray.Window.getXWindowDesktop = function(xwin) {
   return desktop;
 };
 
-firetray.Window.checkSubscribedEventMasks = function(xid) {
-  let xWindowAttributes = new x11.XWindowAttributes;
-  let status = x11.XGetWindowAttributes(x11.current.Display, xid, xWindowAttributes.address());
-  log.debug("xWindowAttributes: "+xWindowAttributes);
-  let xEventMask = xWindowAttributes.your_event_mask;
-  let xEventMaskNeeded = x11.VisibilityChangeMask|x11.StructureNotifyMask|
-        x11.FocusChangeMask|x11.PropertyChangeMask;
-  log.debug("xEventMask="+xEventMask+" xEventMaskNeeded="+xEventMaskNeeded);
-  if ((xEventMask & xEventMaskNeeded) !== xEventMaskNeeded) {
-    log.error("missing mandatory event-masks"); // change with gdk_window_set_events()
+firetray.Window.correctSubscribedEventMasks = function(gdkWin) {
+  let eventMask = gdk.gdk_window_get_events(gdkWin);
+  let eventMaskNeeded = gdk.GDK_STRUCTURE_MASK | gdk.GDK_PROPERTY_CHANGE_MASK |
+        gdk.GDK_VISIBILITY_NOTIFY_MASK;
+  log.debug("eventMask="+eventMask+" eventMaskNeeded="+eventMaskNeeded);
+  if ((eventMask & eventMaskNeeded) !== eventMaskNeeded) {
+    log.info("subscribing window to missing mandatory event-masks");
+    gdk.gdk_window_set_events(gdkWin, eventMask|eventMaskNeeded);
   }
 };
 
@@ -649,7 +666,7 @@ firetray.Handler.registerWindow = function(win) {
   Object.defineProperties(this.windows[xid], {
     "visible": { get: function(){return firetray.Window.getVisibility(xid);} }
   });
-  firetray.Window.checkSubscribedEventMasks(xid);
+  firetray.Window.correctSubscribedEventMasks(gdkWin);
   try {
     this.gtkWindows.insert(xid, gtkWin);
     this.gdkWindows.insert(xid, gdkWin);
diff --git a/src/modules/logging.jsm b/src/modules/logging.jsm
index 06a5c1a..3a83a97 100644
--- a/src/modules/logging.jsm
+++ b/src/modules/logging.jsm
@@ -8,7 +8,7 @@ const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
-const FIRETRAY_LOG_LEVEL = "All"; // "All" for debugging
+const FIRETRAY_LOG_LEVEL = "Warn"; // "All" for debugging
 
 const COLOR_NORMAL          = "";
 const COLOR_RESET           = "\033[m";

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list