gfx/src/X11Util.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/src/X11Util.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,142 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * vim: sw=2 ts=8 et :
     1.6 + */
     1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#ifndef mozilla_X11Util_h
    1.12 +#define mozilla_X11Util_h
    1.13 +
    1.14 +// Utilities common to all X clients, regardless of UI toolkit.
    1.15 +
    1.16 +#if defined(MOZ_WIDGET_GTK)
    1.17 +#  include <gdk/gdk.h>
    1.18 +#  include <gdk/gdkx.h>
    1.19 +#elif defined(MOZ_WIDGET_QT)
    1.20 +#include "gfxQtPlatform.h"
    1.21 +#undef CursorShape
    1.22 +#  include <X11/Xlib.h>
    1.23 +#else
    1.24 +#  error Unknown toolkit
    1.25 +#endif 
    1.26 +
    1.27 +#include <string.h>                     // for memset
    1.28 +#include "gfxCore.h"                    // for NS_GFX
    1.29 +#include "mozilla/Scoped.h"             // for SCOPED_TEMPLATE
    1.30 +
    1.31 +namespace mozilla {
    1.32 +
    1.33 +/**
    1.34 + * Return the default X Display created and used by the UI toolkit.
    1.35 + */
    1.36 +inline Display*
    1.37 +DefaultXDisplay()
    1.38 +{
    1.39 +#if defined(MOZ_WIDGET_GTK)
    1.40 +  return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    1.41 +#elif defined(MOZ_WIDGET_QT)
    1.42 +  return gfxQtPlatform::GetXDisplay();
    1.43 +#endif
    1.44 +}
    1.45 +
    1.46 +/**
    1.47 + * Sets *aVisual to point to aDisplay's Visual struct corresponding to
    1.48 + * aVisualID, and *aDepth to its depth.  When aVisualID is None, these are set
    1.49 + * to nullptr and 0 respectively.  Both out-parameter pointers are assumed
    1.50 + * non-nullptr.
    1.51 + */
    1.52 +void
    1.53 +FindVisualAndDepth(Display* aDisplay, VisualID aVisualID,
    1.54 +                   Visual** aVisual, int* aDepth);
    1.55 +
    1.56 +
    1.57 +/**
    1.58 + * Ensure that all X requests have been processed.
    1.59 + *
    1.60 + * This is similar to XSync, but doesn't need a round trip if the previous
    1.61 + * request was synchronous or if events have been received since the last
    1.62 + * request.  Subsequent FinishX calls will be noops if there have been no
    1.63 + * intermediate requests.
    1.64 + */
    1.65 +
    1.66 +void
    1.67 +FinishX(Display* aDisplay);
    1.68 +
    1.69 +/**
    1.70 + * Invoke XFree() on a pointer to memory allocated by Xlib (if the
    1.71 + * pointer is nonnull) when this class goes out of scope.
    1.72 + */
    1.73 +template <typename T>
    1.74 +struct ScopedXFreePtrTraits
    1.75 +{
    1.76 +  typedef T *type;
    1.77 +  static T *empty() { return nullptr; }
    1.78 +  static void release(T *ptr) { if (ptr != nullptr) XFree(ptr); }
    1.79 +};
    1.80 +SCOPED_TEMPLATE(ScopedXFree, ScopedXFreePtrTraits)
    1.81 +
    1.82 +/**
    1.83 + * On construction, set a graceful X error handler that doesn't crash the application and records X errors.
    1.84 + * On destruction, restore the X error handler to what it was before construction.
    1.85 + * 
    1.86 + * The SyncAndGetError() method allows to know whether a X error occurred, optionally allows to get the full XErrorEvent,
    1.87 + * and resets the recorded X error state so that a single X error will be reported only once.
    1.88 + *
    1.89 + * Nesting is correctly handled: multiple nested ScopedXErrorHandler's don't interfere with each other's state. However,
    1.90 + * if SyncAndGetError is not called on the nested ScopedXErrorHandler, then any X errors caused by X calls made while the nested
    1.91 + * ScopedXErrorHandler was in place may then be caught by the other ScopedXErrorHandler. This is just a result of X being
    1.92 + * asynchronous and us not doing any implicit syncing: the only method in this class what causes syncing is SyncAndGetError().
    1.93 + *
    1.94 + * This class is not thread-safe at all. It is assumed that only one thread is using any ScopedXErrorHandler's. Given that it's
    1.95 + * not used on Mac, it should be easy to make it thread-safe by using thread-local storage with __thread.
    1.96 + */
    1.97 +class NS_GFX ScopedXErrorHandler
    1.98 +{
    1.99 +public:
   1.100 +    // trivial wrapper around XErrorEvent, just adding ctor initializing by zero.
   1.101 +    struct ErrorEvent
   1.102 +    {
   1.103 +        XErrorEvent mError;
   1.104 +
   1.105 +        ErrorEvent()
   1.106 +        {
   1.107 +            memset(this, 0, sizeof(ErrorEvent));
   1.108 +        }
   1.109 +    };
   1.110 +
   1.111 +private:
   1.112 +
   1.113 +    // this ScopedXErrorHandler's ErrorEvent object
   1.114 +    ErrorEvent mXError;
   1.115 +
   1.116 +    // static pointer for use by the error handler
   1.117 +    static ErrorEvent* sXErrorPtr;
   1.118 +
   1.119 +    // what to restore sXErrorPtr to on destruction
   1.120 +    ErrorEvent* mOldXErrorPtr;
   1.121 +
   1.122 +    // what to restore the error handler to on destruction
   1.123 +    int (*mOldErrorHandler)(Display *, XErrorEvent *);
   1.124 +
   1.125 +public:
   1.126 +
   1.127 +    static int
   1.128 +    ErrorHandler(Display *, XErrorEvent *ev);
   1.129 +
   1.130 +    ScopedXErrorHandler();
   1.131 +
   1.132 +    ~ScopedXErrorHandler();
   1.133 +
   1.134 +    /** \returns true if a X error occurred since the last time this method was called on this ScopedXErrorHandler object,
   1.135 +     *           or since the creation of this ScopedXErrorHandler object if this method was never called on it.
   1.136 +     *
   1.137 +     * \param ev this optional parameter, if set, will be filled with the XErrorEvent object. If multiple errors occurred,
   1.138 +     *           the first one will be returned.
   1.139 +     */
   1.140 +    bool SyncAndGetError(Display *dpy, XErrorEvent *ev = nullptr);
   1.141 +};
   1.142 +
   1.143 +} // namespace mozilla
   1.144 +
   1.145 +#endif  // mozilla_X11Util_h

mercurial