-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathxterm.c.27.1.patch
134 lines (131 loc) · 3.48 KB
/
xterm.c.27.1.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
diff --git a/src/xterm.c b/src/xterm.c
index 01ff790831..1acff2af0d 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -235,6 +235,117 @@ #define XtNinitialState "initialState"
static bool x_get_current_wm_state (struct frame *, Window, int *, bool *);
+
+#define CLOCKID CLOCK_REALTIME
+#define CONN_SIG (SIGRTMAX-1)
+#include <signal.h>
+#include "X11/Xlibint.h"
+
+static int connection_fd = -1;
+void
+connection_timeout_handler (int signum)
+{
+ if (connection_fd != -1) {
+ close(connection_fd);
+ connection_fd = -1;
+ }
+}
+Status
+XCheckConnection (
+ register Display *dpy,
+ Drawable d, int fd, double timeout)
+{
+
+ xGetGeometryReply rep;
+ register xResourceReq *req;
+ LockDisplay(dpy);
+ GetResReq(GetGeometry, d, req);
+ Status res = 0;
+
+ sigset_t origmask;
+ sigset_t sigmask;
+ sigemptyset(&sigmask);
+ pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
+
+ // Create the timer
+ timer_t timerid;
+ struct sigevent sev;
+ struct itimerspec its;
+ long long freq_nanosecs;
+
+ struct sigaction new_action, old_action;
+
+ new_action.sa_handler = connection_timeout_handler;
+ sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+
+ sigaction (CONN_SIG, &new_action, &old_action);
+
+ sev.sigev_notify = SIGEV_SIGNAL;
+ sev.sigev_signo = CONN_SIG;
+ sev.sigev_value.sival_ptr = &timerid;
+ (void) timer_create(CLOCKID, &sev, &timerid);
+
+ freq_nanosecs = (long long)(timeout * 1000000000);
+ its.it_value.tv_sec = freq_nanosecs / 1000000000;
+ its.it_value.tv_nsec = freq_nanosecs % 1000000000;
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+
+ (void) timer_settime(timerid, 0, &its, NULL);
+ connection_fd = fd;
+
+ res = _XReply (dpy, (xReply *)&rep, 0, xTrue);
+
+ connection_fd = -1;
+ (void) timer_delete(timerid);
+ pthread_sigmask(SIG_SETMASK, &origmask, NULL);
+ sigaction (CONN_SIG, &old_action, NULL);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return (int)res;
+}
+
+int check_frame_connection(struct frame * frame, double timeout)
+{
+ block_input ();
+ int fd = ConnectionNumber (FRAME_X_DISPLAY (frame));
+ int res = XCheckConnection (
+ FRAME_X_DISPLAY (frame), FRAME_OUTER_WINDOW (frame), fd, timeout);
+ unblock_input ();
+ return res;
+}
+
+DEFUN ("x-check-frame", Fx_check_frame,
+ Sx_check_frame, 1, 1, 0,
+ doc: /* check the connection with the display of the given frame. */)
+ (Lisp_Object f)
+{
+ if (!f)
+ return Qnil;
+
+ if (NILP (f))
+ return Qnil;
+
+ if (Fframep(f) != Qx)
+ return Qnil;
+
+ if (!FLOATP (Vx_check_frame_timeout))
+ return Qnil;
+
+ /* Default timeout is 0.5 second. This timeout will occur
+ only when the libx11 did not noticed the frame was
+ disconnected. */
+ double timeout = XFLOAT_DATA (Vx_check_frame_timeout);
+
+ struct frame *frame = XFRAME (f);
+ int ret = check_frame_connection (frame, timeout);
+ return ret ? Qt : Qnil;
+}
+
+
+
/* Flush display of frame F. */
static void
@@ -13747,4 +13641,11 @@ syms_of_xterm (void)
consuming frame position adjustments. In newer versions of GTK, Emacs
always uses gtk_window_move and ignores the value of this variable. */);
x_gtk_use_window_move = true;
+
+ defsubr (&Sx_check_frame);
+
+ DEFVAR_LISP ("x-check-frame-timeout", Vx_check_frame_timeout,
+ doc: /* How long to wait a display to response. */);
+ Vx_check_frame_timeout = make_float (0.5);
+
}