Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/X11Util.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_X11Util_h
8
#define mozilla_X11Util_h
9
10
// Utilities common to all X clients, regardless of UI toolkit.
11
12
#if defined(MOZ_WIDGET_GTK)
13
#  include <gdk/gdk.h>
14
#  include <gdk/gdkx.h>
15
#  include "X11UndefineNone.h"
16
#else
17
#  error Unknown toolkit
18
#endif
19
20
#include <string.h>                     // for memset
21
#include "mozilla/Scoped.h"             // for SCOPED_TEMPLATE
22
23
namespace mozilla {
24
25
/**
26
 * Return the default X Display created and used by the UI toolkit.
27
 */
28
inline Display*
29
DefaultXDisplay()
30
0
{
31
0
#if defined(MOZ_WIDGET_GTK)
32
0
  return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
33
0
#endif
34
0
}
35
36
/**
37
 * Sets *aVisual to point to aDisplay's Visual struct corresponding to
38
 * aVisualID, and *aDepth to its depth.  When aVisualID is None, these are set
39
 * to nullptr and 0 respectively.  Both out-parameter pointers are assumed
40
 * non-nullptr.
41
 */
42
void
43
FindVisualAndDepth(Display* aDisplay, VisualID aVisualID,
44
                   Visual** aVisual, int* aDepth);
45
46
47
/**
48
 * Ensure that all X requests have been processed.
49
 *
50
 * This is similar to XSync, but doesn't need a round trip if the previous
51
 * request was synchronous or if events have been received since the last
52
 * request.  Subsequent FinishX calls will be noops if there have been no
53
 * intermediate requests.
54
 */
55
56
void
57
FinishX(Display* aDisplay);
58
59
/**
60
 * Invoke XFree() on a pointer to memory allocated by Xlib (if the
61
 * pointer is nonnull) when this class goes out of scope.
62
 */
63
template <typename T>
64
struct ScopedXFreePtrTraits
65
{
66
  typedef T *type;
67
0
  static T *empty() { return nullptr; }
68
0
  static void release(T *ptr) { if (ptr != nullptr) XFree(ptr); }
69
};
70
SCOPED_TEMPLATE(ScopedXFree, ScopedXFreePtrTraits)
71
72
/**
73
 * On construction, set a graceful X error handler that doesn't crash the application and records X errors.
74
 * On destruction, restore the X error handler to what it was before construction.
75
 * 
76
 * The SyncAndGetError() method allows to know whether a X error occurred, optionally allows to get the full XErrorEvent,
77
 * and resets the recorded X error state so that a single X error will be reported only once.
78
 *
79
 * Nesting is correctly handled: multiple nested ScopedXErrorHandler's don't interfere with each other's state. However,
80
 * if SyncAndGetError is not called on the nested ScopedXErrorHandler, then any X errors caused by X calls made while the nested
81
 * ScopedXErrorHandler was in place may then be caught by the other ScopedXErrorHandler. This is just a result of X being
82
 * asynchronous and us not doing any implicit syncing: the only method in this class what causes syncing is SyncAndGetError().
83
 *
84
 * This class is not thread-safe at all. It is assumed that only one thread is using any ScopedXErrorHandler's. Given that it's
85
 * not used on Mac, it should be easy to make it thread-safe by using thread-local storage with __thread.
86
 */
87
class ScopedXErrorHandler
88
{
89
public:
90
    // trivial wrapper around XErrorEvent, just adding ctor initializing by zero.
91
    struct ErrorEvent
92
    {
93
        XErrorEvent mError;
94
95
        ErrorEvent()
96
        {
97
            memset(this, 0, sizeof(ErrorEvent));
98
        }
99
    };
100
101
private:
102
103
    // this ScopedXErrorHandler's ErrorEvent object
104
    ErrorEvent mXError;
105
106
    // static pointer for use by the error handler
107
    static ErrorEvent* sXErrorPtr;
108
109
    // what to restore sXErrorPtr to on destruction
110
    ErrorEvent* mOldXErrorPtr;
111
112
    // what to restore the error handler to on destruction
113
    int (*mOldErrorHandler)(Display *, XErrorEvent *);
114
115
public:
116
117
    static int
118
    ErrorHandler(Display *, XErrorEvent *ev);
119
120
    /**
121
     * @param aAllowOffMainThread whether to warn if used off main thread
122
     */
123
    explicit ScopedXErrorHandler(bool aAllowOffMainThread = false);
124
125
    ~ScopedXErrorHandler();
126
127
    /** \returns true if a X error occurred since the last time this method was called on this ScopedXErrorHandler object,
128
     *           or since the creation of this ScopedXErrorHandler object if this method was never called on it.
129
     *
130
     * \param ev this optional parameter, if set, will be filled with the XErrorEvent object. If multiple errors occurred,
131
     *           the first one will be returned.
132
     */
133
    bool SyncAndGetError(Display *dpy, XErrorEvent *ev = nullptr);
134
};
135
136
class OffMainThreadScopedXErrorHandler : public ScopedXErrorHandler
137
{
138
public:
139
  OffMainThreadScopedXErrorHandler()
140
    : ScopedXErrorHandler(true)
141
0
  {
142
0
  }
143
};
144
145
} // namespace mozilla
146
147
#endif  // mozilla_X11Util_h