Bug 572295: Add X11Util.h for X11 toolkits. r=karlt,joedrew
authorChris Jones <jones.chris.g@gmail.com>
Mon, 21 Jun 2010 15:35:49 -0500
changeset 43912 28f111fe6ee9a76c2c0c4839ccb7636c7f8c80c2
parent 43911 c818b9dd148daac1a92ad7079cb90d03f7876f6f
child 43913 9ea93c9757b29c4906e922778f472025a2daa9ec
push id13958
push usercjones@mozilla.com
push dateMon, 21 Jun 2010 20:37:22 +0000
treeherdermozilla-central@7f2f32d46ed8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, joedrew
bugs572295
milestone1.9.3a6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 572295: Add X11Util.h for X11 toolkits. r=karlt,joedrew
dom/plugins/NPEventX11.h
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceParent.cpp
gfx/public/Makefile.in
gfx/public/X11Util.h
layout/generic/nsObjectFrame.cpp
modules/plugin/base/src/nsNPAPIPlugin.cpp
modules/plugin/base/src/nsPluginHost.cpp
toolkit/xre/nsX11ErrorHandler.cpp
--- a/dom/plugins/NPEventX11.h
+++ b/dom/plugins/NPEventX11.h
@@ -35,28 +35,19 @@
  * 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 ***** */
 
 #ifndef mozilla_dom_plugins_NPEventX11_h
 #define mozilla_dom_plugins_NPEventX11_h 1
 
-#if defined(MOZ_WIDGET_GTK2)
-#  include <gdk/gdkx.h>
-#elif defined(MOZ_WIDGET_QT)
-// X11/X.h has #define CursorShape 0, but Qt's qnamespace.h defines
-//   enum CursorShape { ... }.  Good times!
-#  undef CursorShape
-#  include <QX11Info>
-#else
-#  error Implement me for your toolkit
-#endif
+#include "npapi.h"
 
-#include "npapi.h"
+#include "mozilla/X11Util.h"
 
 namespace mozilla {
 
 namespace plugins {
 
 struct NPRemoteEvent {
     NPEvent event;
 };
@@ -110,49 +101,26 @@ struct ParamTraits<mozilla::plugins::NPR
 
     static void Log(const paramType& aParam, std::wstring* aLog)
     {
         // TODO
         aLog->append(L"(XEvent)");
     }
 
 private:
-    static Display* GetXDisplay(const XAnyEvent& ev)
-    {
-        // TODO: get Display* from Window in |ev|
-
-        // FIXME: do this using Xlib
-#if defined(MOZ_WIDGET_GTK2)
-        return GDK_DISPLAY();
-#elif defined(MOZ_WIDGET_QT)
-        return QX11Info::display();
-#endif
-    }
-
-    static Display* GetXDisplay(const XErrorEvent& ev)
-    {
-        // TODO: get Display* from Window in |ev|
-
-        // FIXME: do this using Xlib
-#if defined(MOZ_WIDGET_GTK2)
-        return GDK_DISPLAY();
-#elif defined(MOZ_WIDGET_QT)
-        return QX11Info::display();
-#endif
-    }
-
     static void SetXDisplay(XEvent& ev)
     {
+        Display* display = mozilla::DefaultXDisplay();
         if (ev.type >= KeyPress) {
-            ev.xany.display = GetXDisplay(ev.xany);
+            ev.xany.display = display;
         }
         else {
             // XXX assuming that this is an error event
             // (type == 0? not clear from Xlib.h)
-            ev.xerror.display = GetXDisplay(ev.xerror);
+            ev.xerror.display = display;
         }
     }
 };
 
 } // namespace IPC
 
 
 #endif // ifndef mozilla_dom_plugins_NPEventX11_h
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -115,21 +115,17 @@ PluginInstanceChild::PluginInstanceChild
 #endif
 {
     memset(&mWindow, 0, sizeof(mWindow));
     mData.ndata = (void*) this;
     mData.pdata = nsnull;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     mWindow.ws_info = &mWsInfo;
     memset(&mWsInfo, 0, sizeof(mWsInfo));
-#ifdef MOZ_WIDGET_GTK2
-    mWsInfo.display = GDK_DISPLAY();
-#elif defined(MOZ_WIDGET_QT)
-    mWsInfo.display = QX11Info::display();
-#endif // MOZ_WIDGET_GTK2
+    mWsInfo.display = DefaultXDisplay();
 #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
 #if defined(OS_WIN)
     memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
     mAlphaExtract.doublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
 #endif // OS_WIN
     InitQuirksModes(aMimeType);
 #if defined(OS_WIN)
     InitPopupMenuHook();
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -208,26 +208,16 @@ PluginInstanceParent::AllocPPluginStream
 
 bool
 PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent* stream)
 {
     delete stream;
     return true;
 }
 
-#ifdef MOZ_X11
-static Display* GetXDisplay() {
-#  ifdef MOZ_WIDGET_GTK2
-        return GDK_DISPLAY();
-#  elif defined(MOZ_WIDGET_QT)
-        return QX11Info::display();
-#  endif
-}
-#endif
-
 bool
 PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
                                                        bool* value,
                                                        NPError* result)
 {
     NPBool v;
     *result = mNPNIface->getvalue(mNPP, NPNVjavascriptEnabledBool, &v);
     *value = v;
@@ -695,24 +685,24 @@ PluginInstanceParent::NPP_HandleEvent(vo
                           npevent->xgraphicsexpose.drawable));
         // Make sure the X server has created the Drawable and completes any
         // drawing before the plugin draws on top.
         //
         // XSync() waits for the X server to complete.  Really this parent
         // process does not need to wait; the child is the process that needs
         // to wait.  A possibly-slightly-better alternative would be to send
         // an X event to the child that the child would wait for.
-        XSync(GetXDisplay(), False);
+        XSync(DefaultXDisplay(), False);
 
         return CallPaint(npremoteevent, &handled) ? handled : 0;
 
     case ButtonPress:
         // Release any active pointer grab so that the plugin X client can
         // grab the pointer if it wishes.
-        Display *dpy = GetXDisplay();
+        Display *dpy = DefaultXDisplay();
 #  ifdef MOZ_WIDGET_GTK2
         // GDK attempts to (asynchronously) track whether there is an active
         // grab so ungrab through GDK.
         gdk_pointer_ungrab(npevent->xbutton.time);
 #  else
         XUngrabPointer(dpy, npevent->xbutton.time);
 #  endif
         // Wait for the ungrab to complete.
--- a/gfx/public/Makefile.in
+++ b/gfx/public/Makefile.in
@@ -61,10 +61,15 @@ EXPORTS		= \
 		nsIFontMetrics.h \
 		nsIDeviceContext.h \
 		nsGfxCIID.h \
 		nsIRegion.h \
 		nsITheme.h \
 		nsThemeConstants.h \
 		$(NULL)
 
+ifdef MOZ_X11
+EXPORTS_NAMESPACES	= mozilla
+EXPORTS_mozilla		= X11Util.h
+endif
+
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/gfx/public/X11Util.h
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* ***** 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 Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** */
+
+#ifndef mozilla_X11Util_h
+#define mozilla_X11Util_h
+
+// Utilities common to all X clients, regardless of UI toolkit.
+
+#if defined(MOZ_WIDGET_GTK2)
+#  include <gdk/gdkx.h>
+#elif defined(MOZ_WIDGET_QT)
+#  include <QX11Info>
+#else
+#  error Unknown toolkit
+#endif 
+
+namespace mozilla {
+
+/**
+ * Return the default X Display created and used by the UI toolkit.
+ */
+inline Display*
+DefaultXDisplay()
+{
+#if defined(MOZ_WIDGET_GTK2)
+  return GDK_DISPLAY();
+#elif defined(MOZ_WIDGET_QT)
+  return QX11Info::display();
+#endif
+}
+
+/**
+ * Invoke XFree() on a pointer to memory allocated by Xlib (if the
+ * pointer is nonnull) when this class goes out of scope.
+ */
+template<typename T>
+struct ScopedXFree
+{
+  ScopedXFree(T* aPtr) : mPtr(aPtr) {}
+
+  ~ScopedXFree()
+  {
+    if (mPtr)
+      XFree(mPtr);
+  }
+
+  operator T*() const { return get(); }
+  T* operator->() const { return get(); }
+  T* get() const { return mPtr; }
+
+
+private:
+  T* mPtr;
+
+  // disable these
+  ScopedXFree(const ScopedXFree&);
+  ScopedXFree& operator=(const ScopedXFree&);
+  static void* operator new (size_t);
+  static void operator delete (void*);
+};
+
+} // namespace mozilla
+
+#endif  // mozilla_X11Util_h
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -191,24 +191,25 @@ enum { XKeyPress = KeyPress };
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #endif
 #endif
 
 #ifdef MOZ_WIDGET_GTK2
 #include "gfxGdkNativeRenderer.h"
-#define DISPLAY GDK_DISPLAY
 #endif
 
 #ifdef MOZ_WIDGET_QT
 #include "gfxQtNativeRenderer.h"
+#endif
+
 #ifdef MOZ_X11
-#define DISPLAY QX11Info::display
-#endif
+#include "mozilla/X11Util.h"
+using mozilla::DefaultXDisplay;
 #endif
 
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
 #ifdef MOZ_IPC
 #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
 #endif
@@ -4128,17 +4129,17 @@ static unsigned int XInputEventState(con
 #ifdef MOZ_COMPOSITED_PLUGINS
 static void find_dest_id(XID top, XID *root, XID *dest, int target_x, int target_y)
 {
   XID target_id = top;
   XID parent;
   XID *children;
   unsigned int nchildren;
 
-  Display *display = DISPLAY();
+  Display *display = DefaultXDisplay();
 
   while (1) {
 loop:
     //printf("searching %x\n", target_id);
     if (!XQueryTree(display, target_id, root, &parent, &children, &nchildren) ||
         !nchildren)
       break;
     for (unsigned int i=0; i<nchildren; i++) {
@@ -4297,20 +4298,20 @@ nsEventStatus nsPluginInstanceOwner::Pro
               be.xbutton =  event;
               XID target;
               XID root;
               int wx, wy;
               unsigned int width, height, border_width, depth;
 
               //printf("xbutton: %d %d %d\n", anEvent.message, be.xbutton.x, be.xbutton.y);
               XID w = (XID)mPluginWindow->window;
-              XGetGeometry(DISPLAY(), w, &root, &wx, &wy, &width, &height, &border_width, &depth);
+              XGetGeometry(DefaultXDisplay(), w, &root, &wx, &wy, &width, &height, &border_width, &depth);
               find_dest_id(w, &root, &target, pluginPoint.x + wx, pluginPoint.y + wy);
               be.xbutton.window = target;
-              XSendEvent (DISPLAY(), target,
+              XSendEvent (DefaultXDisplay(), target,
                   FALSE, event.type == ButtonPress ? ButtonPressMask : ButtonReleaseMask, &be);
 
             }
             break;
           }
       }
       break;
 
@@ -4355,20 +4356,20 @@ nsEventStatus nsPluginInstanceOwner::Pro
           be.xkey =  event;
           XID target;
           XID root;
           int wx, wy;
           unsigned int width, height, border_width, depth;
 
           //printf("xkey: %d %d %d\n", anEvent.message, be.xkey.keycode, be.xkey.state);
           XID w = (XID)mPluginWindow->window;
-          XGetGeometry(DISPLAY(), w, &root, &wx, &wy, &width, &height, &border_width, &depth);
+          XGetGeometry(DefaultXDisplay(), w, &root, &wx, &wy, &width, &height, &border_width, &depth);
           find_dest_id(w, &root, &target, mLastPoint.x + wx, mLastPoint.y + wy);
           be.xkey.window = target;
-          XSendEvent (DISPLAY(), target,
+          XSendEvent (DefaultXDisplay(), target,
               FALSE, event.type == XKeyPress ? KeyPressMask : KeyReleaseMask, &be);
 
 
         }
       else
         {
           // If we need to send synthesized key events, then
           // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
@@ -5604,29 +5605,29 @@ nsPluginInstanceOwner::Renderer::NativeD
     GtkWidget *plug = (GtkWidget*)(((nsPluginNativeWindow*)mWindow)->mPlugWindow);
     //GtkWidget *plug = (GtkWidget*)(((nsPluginNativeWindowGtk2*)mWindow)->mSocketWidget);
 
     /* Cairo has bugs with IncludeInferiors when using paint
      * so we use XCopyArea directly instead. */
     XGCValues gcv;
     gcv.subwindow_mode = IncludeInferiors;
     gcv.graphics_exposures = False;
-    GC gc = XCreateGC(GDK_DISPLAY(), gdk_x11_drawable_get_xid(drawable), GCGraphicsExposures | GCSubwindowMode, &gcv);
+    GC gc = XCreateGC(DefaultXDisplay(), gdk_x11_drawable_get_xid(drawable), GCGraphicsExposures | GCSubwindowMode, &gcv);
     /* The source and destination appear to always line up, so src and dest
      * coords should be the same */
-    XCopyArea(GDK_DISPLAY(), gdk_x11_drawable_get_xid(plug->window),
+    XCopyArea(DefaultXDisplay(), gdk_x11_drawable_get_xid(plug->window),
               gdk_x11_drawable_get_xid(drawable),
               gc,
               mDirtyRect.x,
               mDirtyRect.y,
               mDirtyRect.width,
               mDirtyRect.height,
               mDirtyRect.x,
               mDirtyRect.y);
-    XFreeGC(GDK_DISPLAY(), gc);
+    XFreeGC(DefaultXDisplay(), gc);
   }
 #endif
 #endif
   return NS_OK;
 }
 #endif
 
 void nsPluginInstanceOwner::SendIdleEvent()
@@ -5824,17 +5825,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
           nsIWidget* win = mObjectFrame->GetWindow();
           NPSetWindowCallbackStruct* ws_info = 
             static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
           if (win) {
             ws_info->display =
               static_cast<Display*>(win->GetNativeData(NS_NATIVE_DISPLAY));
           }
           else {
-            ws_info->display = DISPLAY();
+            ws_info->display = DefaultXDisplay();
           }
 #endif
         } else if (mWidget) {
           mWidget->Resize(mPluginWindow->width, mPluginWindow->height,
                           PR_FALSE);
 
           // mPluginWindow->type is used in |GetPluginPort| so it must
           // be initialized first
--- a/modules/plugin/base/src/nsNPAPIPlugin.cpp
+++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp
@@ -111,16 +111,20 @@ using mozilla::PluginLibrary;
 #include "mozilla/PluginPRLibrary.h"
 using mozilla::PluginPRLibrary;
 
 #ifdef MOZ_IPC
 #include "mozilla/plugins/PluginModuleParent.h"
 using mozilla::plugins::PluginModuleParent;
 #endif
 
+#ifdef MOZ_X11
+#include "mozilla/X11Util.h"
+#endif
+
 using namespace mozilla::plugins::parent;
 
 // We should make this const...
 static NPNetscapeFuncs sBrowserFuncs = {
   sizeof(sBrowserFuncs),
   (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
   _geturl,
   _posturl,
@@ -1880,21 +1884,17 @@ NPError NP_CALLBACK
       nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
       PRBool windowless = PR_FALSE;
       inst->IsWindowless(&windowless);
       NPBool needXEmbed = PR_FALSE;
       if (!windowless) {
         inst->GetValueFromPlugin(NPPVpluginNeedsXEmbed, &needXEmbed);
       }
       if (windowless || needXEmbed) {
-#ifdef MOZ_WIDGET_GTK2
-        (*(Display **)result) = GDK_DISPLAY();
-#else
-        (*(Display **)result) = QX11Info::display();
-#endif
+        (*(Display **)result) = mozilla::DefaultXDisplay();
         return NPERR_NO_ERROR;
       }
     }
 #ifdef MOZ_WIDGET_GTK2
     // adobe nppdf calls XtGetApplicationNameAndClass(display,
     // &instance, &class) we have to init Xt toolkit before get
     // XtDisplay just call gtk_xtbin_new(w,0) once
     static GtkWidget *gtkXtBinHolder = 0;
--- a/modules/plugin/base/src/nsPluginHost.cpp
+++ b/modules/plugin/base/src/nsPluginHost.cpp
@@ -152,20 +152,16 @@
 #include "nsContentErrors.h"
 #include "mozilla/TimeStamp.h"
 
 #if defined(XP_WIN)
 #include "windows.h"
 #include "winbase.h"
 #endif
 
-#if defined(XP_UNIX) && defined(MOZ_WIDGET_GTK2) & defined(MOZ_X11)
-#include <gdk/gdkx.h> // for GDK_DISPLAY()
-#endif
-
 using mozilla::TimeStamp;
 
 // Null out a strong ref to a linked list iteratively to avoid
 // exhausting the stack (bug 486349).
 #define NS_ITERATIVE_UNREF_LIST(type_, list_, mNext_)                \
   {                                                                  \
     while (list_) {                                                  \
       type_ temp = list_->mNext_;                                    \
--- a/toolkit/xre/nsX11ErrorHandler.cpp
+++ b/toolkit/xre/nsX11ErrorHandler.cpp
@@ -43,21 +43,17 @@
 using mozilla::plugins::PluginProcessChild;
 #endif
 
 #include "prenv.h"
 #include "nsXULAppAPI.h"
 #include "nsExceptionHandler.h"
 #include "nsDebug.h"
 
-#ifdef MOZ_WIDGET_GTK2
-#include <gdk/gdkx.h>
-#elif defined(MOZ_WIDGET_QT)
-#include <QX11Info>
-#endif
+#include "mozilla/X11Util.h"
 #include <X11/Xlib.h>
 
 #define BUFSIZE 2048 // What Xlib uses with XGetErrorDatabaseText
 
 extern "C" {
 static int
 IgnoreError(Display *display, XErrorEvent *event) {
   return 0; // This return value is ignored.
@@ -196,18 +192,14 @@ X11Error(Display *display, XErrorEvent *
 }
 }
 
 void
 InstallX11ErrorHandler()
 {
   XSetErrorHandler(X11Error);
 
-#ifdef MOZ_WIDGET_GTK2
-  Display *display = GDK_DISPLAY();
-#elif defined(MOZ_WIDGET_QT)
-  Display *display = QX11Info::display();
-#endif
+  Display *display = mozilla::DefaultXDisplay();
   NS_ASSERTION(display, "No X display");
   if (PR_GetEnv("MOZ_X_SYNC")) {
     XSynchronize(display, True);
   }
 }