version 0.4.1
[expresskeys.git] / src-expresskeys / on_error.c
1 /*
2  expresskeys - Support ExpressKeys, Touch Strips, Scroll Wheel on Wacom tablets.
3
4  Copyright (C) 2005-2007 - Mats Johannesson
5
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc.,
18  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <stdio.h> /* NULL, FILE, fprintf, fopen, fclose */
22 #include <signal.h> /* SIGINT */
23 #include <X11/Xlib.h> /* XErrorEvent also pulls in X11/X.h with BadWindow def.*/
24 #include <X11/extensions/XIproto.h> /* Minor opcode error: X_OpenDevice */
25
26 #include "defines.h"
27
28 /* Externals: */
29
30 extern const char* our_prog_name;
31 extern const char* total_error_file;
32
33 extern void clean_up_exit(int signum);
34
35 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36  This function prints out the error strings from a caller and terminates:
37  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38
39 void exit_on_error(FILE* errorfp, char* string1, const char* string2,
40                                                         const char* string3)
41 {
42         if (errorfp) {
43                 fprintf(errorfp, string1, string2, string3);
44                 fclose(errorfp);
45         }
46
47         fprintf(stderr, string1, string2, string3);
48
49 /* We use SIGINT instead of SIGTERM to get rid of the "Terminated" message
50  printed by eg. a bash shell */
51         clean_up_exit(SIGINT);
52
53 }
54
55 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56  This function is a rudimentary error handler for Xserver error returns:
57  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
58
59 int xerror_handler(Display* display, XErrorEvent* error_event)
60 {
61 /* There seems to be no standard way to catch an "BadDevice, invalid or
62  uninitialized input device" error when trying to open devices which aren't
63  plugged in. The extension error code varies (I've seen 169 and 170 myself)
64  and the message string could be localized as well. Therefore we take a
65  two-pronged approach here: Just return if the error code falls within the
66  extension error range (>= 128) and at the same time is a X_OpenDevice
67  "Minor opcode" as defined in X11/extensions/XIproto.h
68    Also, in rare cases we might hit "BadWindow (invalid Window parameter)"
69  (code 3) when looking for the present focus-window. I've only seen it with
70  the "Firefox Preferences" window, but we better ignore any such case
71  (standard error code from X11/X.h pulled in through X11/Xlib.h): */
72         if (((error_event->error_code >= 128)
73         && (error_event->minor_code == X_OpenDevice))
74         || (error_event->error_code == BadWindow)) {
75                 return 0;
76         }
77
78 /* Turning X behaviour into sync (from async) takes care of 'double-free' and
79  other unpleasant conditions, should more than one X error surface here: */
80         XSynchronize(display, True);
81
82         FILE* errorfp = NULL;
83         errorfp = fopen(total_error_file, "w");
84
85         char error_buffer[MAXBUFFER];
86         XGetErrorText(display, error_event->error_code, error_buffer,MAXBUFFER);
87         fprintf(stderr, "\nX error message: %i %s\n", error_event->error_code,
88                                                                 error_buffer);
89
90         exit_on_error(errorfp,
91         "\n%s ERROR: A fatal error was returned from the X server: %s\n",
92                                                 our_prog_name, error_buffer);
93
94 /* We will never reach this: */
95         return 0;
96
97 }
98
99 /* End Code */
100