Line data Source code
1 : /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nsGDKErrorHandler.h"
7 :
8 : #include <gtk/gtk.h>
9 : #include <gdk/gdkx.h>
10 : #include <errno.h>
11 : #include <stdlib.h>
12 : #include <string.h>
13 :
14 : #include "nsDebug.h"
15 : #include "nsString.h"
16 : #include "nsX11ErrorHandler.h"
17 :
18 : #include "prenv.h"
19 :
20 :
21 : /* See https://bugzilla.gnome.org/show_bug.cgi?id=629608#c8
22 : *
23 : * GDK implements X11 error traps to ignore X11 errors.
24 : * Unfortunatelly We don't know which X11 events can be ignored
25 : * so we have to utilize the Gdk error handler to avoid
26 : * false alarms in Gtk3.
27 : */
28 : static void
29 0 : GdkErrorHandler(const gchar *log_domain, GLogLevelFlags log_level,
30 : const gchar *message, gpointer user_data)
31 : {
32 0 : if (strstr(message, "X Window System error")) {
33 : XErrorEvent event;
34 0 : nsDependentCString buffer(message);
35 : char *endptr;
36 :
37 : /* Parse Gdk X Window error message which has this format:
38 : * (Details: serial XXXX error_code XXXX request_code XXXX (XXXX) minor_code XXXX)
39 : */
40 0 : NS_NAMED_LITERAL_CSTRING(serialString, "(Details: serial ");
41 0 : int32_t start = buffer.Find(serialString);
42 0 : if (start == kNotFound)
43 0 : NS_RUNTIMEABORT(message);
44 :
45 0 : start += serialString.Length();
46 0 : errno = 0;
47 0 : event.serial = strtol(buffer.BeginReading() + start, &endptr, 10);
48 0 : if (errno)
49 0 : NS_RUNTIMEABORT(message);
50 :
51 0 : NS_NAMED_LITERAL_CSTRING(errorCodeString, " error_code ");
52 0 : if (!StringBeginsWith(Substring(endptr, buffer.EndReading()), errorCodeString))
53 0 : NS_RUNTIMEABORT(message);
54 :
55 0 : errno = 0;
56 0 : event.error_code = strtol(endptr + errorCodeString.Length(), &endptr, 10);
57 0 : if (errno)
58 0 : NS_RUNTIMEABORT(message);
59 :
60 0 : NS_NAMED_LITERAL_CSTRING(requestCodeString, " request_code ");
61 0 : if (!StringBeginsWith(Substring(endptr, buffer.EndReading()), requestCodeString))
62 0 : NS_RUNTIMEABORT(message);
63 :
64 0 : errno = 0;
65 0 : event.request_code = strtol(endptr + requestCodeString.Length(), &endptr, 10);
66 0 : if (errno)
67 0 : NS_RUNTIMEABORT(message);
68 :
69 0 : NS_NAMED_LITERAL_CSTRING(minorCodeString, " minor_code ");
70 0 : start = buffer.Find(minorCodeString, endptr - buffer.BeginReading());
71 0 : if (!start)
72 0 : NS_RUNTIMEABORT(message);
73 :
74 0 : errno = 0;
75 0 : event.minor_code = strtol(buffer.BeginReading() + start + minorCodeString.Length(), nullptr, 10);
76 0 : if (errno)
77 0 : NS_RUNTIMEABORT(message);
78 :
79 0 : event.display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
80 : // Gdk does not provide resource ID
81 0 : event.resourceid = 0;
82 :
83 0 : X11Error(event.display, &event);
84 : } else {
85 0 : g_log_default_handler(log_domain, log_level, message, user_data);
86 0 : NS_RUNTIMEABORT(message);
87 : }
88 0 : }
89 :
90 : void
91 3 : InstallGdkErrorHandler()
92 : {
93 : g_log_set_handler("Gdk",
94 : (GLogLevelFlags)(G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION),
95 : GdkErrorHandler,
96 3 : nullptr);
97 3 : if (PR_GetEnv("MOZ_X_SYNC")) {
98 0 : XSynchronize(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), True);
99 : }
100 3 : }
|