Mercurial > hg > xemacs-beta
comparison src/gpmevent.c @ 398:74fd4e045ea6 r21-2-29
Import from CVS: tag r21-2-29
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:13:30 +0200 |
parents | c5d627a313b1 |
children | 2f8bb876ab1d |
comparison
equal
deleted
inserted
replaced
397:f4aeb21a5bad | 398:74fd4e045ea6 |
---|---|
1 /* William Perry 1997 */ | 1 /* GPM (General purpose mouse) functions |
2 Copyright (C) 1997 William M. Perry <wmperry@gnu.org> | |
3 Copyright (C) 1999 Free Software Foundation, Inc. | |
4 | |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not in FSF. */ | |
23 | |
24 /* Authors: William Perry */ | |
2 | 25 |
3 #include <config.h> | 26 #include <config.h> |
4 #include "lisp.h" | 27 #include "lisp.h" |
5 #include "console.h" | 28 #include "console.h" |
6 #include "console-tty.h" | 29 #include "console-tty.h" |
7 #include "device.h" | 30 #include "device.h" |
8 #include "events.h" | 31 #include "events.h" |
9 #include "events-mod.h" | 32 #include "events-mod.h" |
10 #include "sysdep.h" | 33 #include "sysdep.h" |
34 #include "commands.h" | |
35 #include "lstream.h" | |
36 #include "sysproc.h" /* for MAXDESC */ | |
37 #include "process.h" | |
11 | 38 |
12 #ifdef HAVE_GPM | 39 #ifdef HAVE_GPM |
13 #include "gpmevent.h" | 40 #include "gpmevent.h" |
14 #include <gpm.h> | 41 #include <gpm.h> |
15 | 42 |
19 #define KG_ALT 3 | 46 #define KG_ALT 3 |
20 #else | 47 #else |
21 #include <linux/keyboard.h> | 48 #include <linux/keyboard.h> |
22 #endif | 49 #endif |
23 | 50 |
24 int | 51 extern int gpm_tried; |
25 handle_gpm_read (struct Lisp_Event *event, struct console *con, int fd) | 52 extern void *gpm_stack; |
26 { | 53 |
27 Gpm_Event ev; | 54 static int (*orig_event_pending_p) (int); |
28 int modifiers = 0; | 55 static void (*orig_next_event_cb) (Lisp_Event *); |
29 int type = -1; | 56 |
30 int button = 1; | 57 static Lisp_Object gpm_event_queue; |
31 | 58 static Lisp_Object gpm_event_queue_tail; |
32 if (!Gpm_GetEvent(&ev)) | 59 |
33 return 0; | 60 struct __gpm_state { |
34 | 61 int gpm_tried; |
35 event->timestamp = 0; | 62 int gpm_flag; |
36 event->channel = CONSOLE_SELECTED_FRAME (con); | 63 void *gpm_stack; |
37 | 64 }; |
38 /* Whow, wouldn't named defines be NICE!?!?! */ | 65 |
39 modifiers = 0; | 66 static struct __gpm_state gpm_state_information[MAXDESC]; |
40 | 67 |
41 if (ev.modifiers & 1) modifiers |= MOD_SHIFT; | 68 static void |
42 if (ev.modifiers & 2) modifiers |= MOD_META; | 69 store_gpm_state (int fd) |
43 if (ev.modifiers & 4) modifiers |= MOD_CONTROL; | 70 { |
44 if (ev.modifiers & 8) modifiers |= MOD_META; | 71 gpm_state_information[fd].gpm_tried = gpm_tried; |
45 | 72 gpm_state_information[fd].gpm_flag = gpm_flag; |
46 if (ev.type & GPM_DOWN) | 73 gpm_state_information[fd].gpm_stack = gpm_stack; |
47 type = GPM_DOWN; | 74 } |
48 else if (ev.type & GPM_UP) | 75 |
49 type = GPM_UP; | 76 static void |
50 else if (ev.type & GPM_MOVE) { | 77 restore_gpm_state (int fd) |
51 type = GPM_MOVE; | 78 { |
52 GPM_DRAWPOINTER(&ev); | 79 gpm_tried = gpm_state_information[fd].gpm_tried; |
53 } | 80 gpm_flag = gpm_state_information[fd].gpm_flag; |
54 | 81 gpm_stack = gpm_state_information[fd].gpm_stack; |
55 if (ev.buttons & GPM_B_LEFT) | 82 gpm_consolefd = gpm_fd = fd; |
56 button = 1; | 83 } |
57 else if (ev.buttons & GPM_B_MIDDLE) | 84 |
58 button = 2; | 85 static void |
59 else if (ev.buttons & GPM_B_RIGHT) | 86 clear_gpm_state (int fd) |
60 button = 3; | 87 { |
61 | 88 if (fd >= 0) |
62 switch (type) { | 89 { |
63 case GPM_DOWN: | 90 memset(&gpm_state_information[fd], '\0', sizeof(struct __gpm_state)); |
64 case GPM_UP: | 91 } |
65 event->event_type = | 92 gpm_tried = gpm_flag = 1; |
66 type == GPM_DOWN ? button_press_event : button_release_event; | 93 gpm_fd = gpm_consolefd = -1; |
67 event->event.button.x = ev.x; | 94 gpm_stack = NULL; |
68 event->event.button.y = ev.y; | 95 } |
69 event->event.button.button = button; | 96 |
70 event->event.button.modifiers = modifiers; | 97 static int |
71 break; | 98 get_process_infd (Lisp_Process *p) |
72 case GPM_MOVE: | 99 { |
73 event->event_type = pointer_motion_event; | 100 Lisp_Object instr, outstr; |
74 event->event.motion.x = ev.x; | 101 get_process_streams (p, &instr, &outstr); |
75 event->event.motion.y = ev.y; | 102 assert (!NILP (instr)); |
76 event->event.motion.modifiers = modifiers; | 103 return filedesc_stream_fd (XLSTREAM (instr)); |
77 default: | 104 } |
78 return 0; | 105 |
79 } | 106 DEFUN ("receive-gpm-event", Freceive_gpm_event, 0, 2, 0, /* |
80 return 1; | 107 Run GPM_GetEvent(). |
81 } | 108 This function is the process handler for the GPM connection. |
82 | 109 */ |
83 void | 110 (process, string)) |
84 connect_to_gpm (struct console *con) | 111 { |
85 { | 112 Gpm_Event ev; |
86 /* Only do this if we are running after dumping and really interactive */ | 113 int modifiers = 0; |
87 if (!noninteractive && initialized) { | 114 int button = 1; |
88 /* We really only want to do this on a TTY */ | 115 Lisp_Object fake_event; |
89 CONSOLE_TTY_MOUSE_FD (con) = -1; | 116 Lisp_Event *event = NULL; |
90 if (EQ (CONSOLE_TYPE (con), Qtty)) { | 117 struct gcpro gcpro1; |
91 Gpm_Connect conn; | 118 static int num_events; |
92 int rval; | 119 |
93 | 120 CHECK_PROCESS (process); |
94 conn.eventMask = GPM_DOWN|GPM_UP|GPM_MOVE; | 121 |
95 conn.defaultMask = GPM_MOVE; | 122 restore_gpm_state (get_process_infd (XPROCESS (process))); |
96 conn.minMod = 0; | 123 |
97 conn.maxMod = ((1<<KG_SHIFT)|(1<<KG_ALT)|(1<<KG_CTRL)); | 124 if (!Gpm_GetEvent(&ev)) |
98 | 125 { |
99 rval = Gpm_Open (&conn, 0); | 126 warn_when_safe (Qnil, Qcritical, "Gpm_GetEvent failed - %d", gpm_fd); |
100 switch (rval) { | 127 return(Qzero); |
101 case -1: /* General failure */ | 128 } |
102 break; | 129 |
103 case -2: /* We are running under an XTerm */ | 130 GCPRO1(fake_event); |
131 | |
132 num_events++; | |
133 | |
134 fake_event = Fmake_event (Qnil, Qnil); | |
135 event = XEVENT(fake_event); | |
136 | |
137 event->timestamp = 0; | |
138 event->channel = Fselected_frame (Qnil); /* CONSOLE_SELECTED_FRAME (con); */ | |
139 | |
140 /* Whow, wouldn't named defines be NICE!?!?! */ | |
141 modifiers = 0; | |
142 | |
143 if (ev.modifiers & 1) modifiers |= MOD_SHIFT; | |
144 if (ev.modifiers & 2) modifiers |= MOD_META; | |
145 if (ev.modifiers & 4) modifiers |= MOD_CONTROL; | |
146 if (ev.modifiers & 8) modifiers |= MOD_META; | |
147 | |
148 if (ev.buttons & GPM_B_LEFT) | |
149 { | |
150 button = 1; | |
151 } | |
152 else if (ev.buttons & GPM_B_MIDDLE) | |
153 { | |
154 button = 2; | |
155 } | |
156 else if (ev.buttons & GPM_B_RIGHT) | |
157 { | |
158 button = 3; | |
159 } | |
160 | |
161 switch (GPM_BARE_EVENTS(ev.type)) { | |
162 case GPM_DOWN: | |
163 case GPM_UP: | |
164 event->event_type = | |
165 (ev.type & GPM_DOWN) ? button_press_event : button_release_event; | |
166 event->event.button.x = ev.x; | |
167 event->event.button.y = ev.y; | |
168 event->event.button.button = button; | |
169 event->event.button.modifiers = modifiers; | |
170 break; | |
171 case GPM_MOVE: | |
172 case GPM_DRAG: | |
173 event->event_type = pointer_motion_event; | |
174 event->event.motion.x = ev.x; | |
175 event->event.motion.y = ev.y; | |
176 event->event.motion.modifiers = modifiers; | |
177 default: | |
178 /* This will never happen */ | |
179 break; | |
180 } | |
181 | |
182 /* Handle the event */ | |
183 enqueue_event (fake_event, &gpm_event_queue, &gpm_event_queue_tail); | |
184 | |
185 UNGCPRO; | |
186 | |
187 return (Qzero); | |
188 } | |
189 | |
190 static void turn_off_gpm (char *process_name) | |
191 { | |
192 Lisp_Object process = Fget_process (build_string (process_name)); | |
193 int fd = -1; | |
194 | |
195 if (NILP (process)) | |
196 { | |
197 /* Something happened to our GPM process - fail silently */ | |
198 return; | |
199 } | |
200 | |
201 fd = get_process_infd (XPROCESS (process)); | |
202 | |
203 restore_gpm_state (fd); | |
204 | |
104 Gpm_Close(); | 205 Gpm_Close(); |
105 break; | 206 |
106 default: | 207 clear_gpm_state (fd); |
107 set_descriptor_non_blocking (gpm_fd); | 208 |
108 CONSOLE_TTY_MOUSE_FD (con) = gpm_fd; | 209 Fdelete_process (build_string (process_name)); |
109 } | 210 } |
110 } | 211 |
111 } | 212 #ifdef TIOCLINUX |
112 } | 213 static Lisp_Object |
113 | 214 tty_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type) |
215 { | |
216 /* This function can GC */ | |
217 struct device *d = decode_device (Qnil); | |
218 int fd = DEVICE_INFD (d); | |
219 char c = 3; | |
220 Lisp_Object output_stream; | |
221 Lisp_Object terminal_stream; | |
222 Lisp_Object output_string; | |
223 struct gcpro gcpro1,gcpro2,gcpro3; | |
224 | |
225 GCPRO3(output_stream,terminal_stream,output_string); | |
226 | |
227 /* The ioctl() to paste actually puts things in the input queue of | |
228 ** the virtual console, so we need to trap that data, since we are | |
229 ** supposed to return the actual string selection from this | |
230 ** function. | |
231 */ | |
232 | |
233 /* I really hate doing this, but it doesn't seem to cause any | |
234 ** problems, and it makes the Lstream_read stuff further down | |
235 ** error out correctly instead of trying to indefinitely read from | |
236 ** the console. | |
237 ** | |
238 ** There is no set_descriptor_blocking() function call, but in my | |
239 ** testing under linux, it has not proved fatal to leave the | |
240 ** descriptor in non-blocking mode. | |
241 ** | |
242 ** William Perry Nov 5, 1999 | |
243 */ | |
244 set_descriptor_non_blocking (fd); | |
245 | |
246 /* We need two streams, one for reading from the selected device, | |
247 ** and one to write the data into. There is no writable version | |
248 ** of the lisp-string lstream, so we make do with a resizing | |
249 ** buffer stream, and make a string out of it after we are | |
250 ** done. | |
251 */ | |
252 output_stream = make_resizing_buffer_output_stream (); | |
253 terminal_stream = make_filedesc_input_stream (fd, 0, -1, LSTR_BLOCKED_OK); | |
254 output_string = Qnil; | |
255 | |
256 /* #### We should arguably use a specbind() and an unwind routine here, | |
257 ** #### but I don't care that much right now. | |
258 */ | |
259 if (NILP (output_stream) || NILP (terminal_stream)) | |
260 { | |
261 /* Should we signal an error here? */ | |
262 goto out; | |
263 } | |
264 | |
265 if (ioctl (fd, TIOCLINUX, &c) < 0) | |
266 { | |
267 /* Could not get the selection - eek */ | |
268 UNGCPRO; | |
269 return (Qnil); | |
270 } | |
271 | |
272 while (1) | |
273 { | |
274 Bufbyte tempbuf[1024]; /* some random amount */ | |
275 ssize_t i; | |
276 ssize_t size_in_bytes = | |
277 Lstream_read (XLSTREAM (terminal_stream), | |
278 tempbuf, sizeof (tempbuf)); | |
279 | |
280 if (size_in_bytes <= 0) | |
281 { | |
282 /* end of the stream */ | |
283 break; | |
284 } | |
285 | |
286 /* convert CR->LF */ | |
287 for (i = 0; i < size_in_bytes; i++) | |
288 { | |
289 if (tempbuf[i] == '\r') | |
290 { | |
291 tempbuf[i] = '\n'; | |
292 } | |
293 } | |
294 | |
295 Lstream_write (XLSTREAM (output_stream), tempbuf, size_in_bytes); | |
296 } | |
297 | |
298 Lstream_flush (XLSTREAM (output_stream)); | |
299 | |
300 output_string = make_string (resizing_buffer_stream_ptr (XLSTREAM (output_stream)), | |
301 Lstream_byte_count (XLSTREAM (output_stream))); | |
302 | |
303 Lstream_delete (XLSTREAM (output_stream)); | |
304 Lstream_delete (XLSTREAM (terminal_stream)); | |
305 | |
306 out: | |
307 UNGCPRO; | |
308 return (output_string); | |
309 } | |
310 | |
311 static Lisp_Object | |
312 tty_selection_exists_p (Lisp_Object selection) | |
313 { | |
314 return (Qt); | |
315 } | |
316 #endif /* TIOCLINUX */ | |
317 | |
318 #if 0 | |
319 static Lisp_Object | |
320 tty_own_selection (Lisp_Object selection_name, Lisp_Object selection_value) | |
321 { | |
322 /* There is no way to do this cleanly - the GPM selection | |
323 ** 'protocol' (actually the TIOCLINUX ioctl) requires a start and | |
324 ** end position on the _screen_, not a string to stick in there. | |
325 ** Lame. | |
326 ** | |
327 ** William Perry Nov 4, 1999 | |
328 */ | |
329 } | |
114 #endif | 330 #endif |
331 | |
332 /* This function appears to work once in a blue moon. I'm not sure | |
333 ** exactly why either. *sigh* | |
334 ** | |
335 ** William Perry Nov 4, 1999 | |
336 ** | |
337 ** Apparently, this is the way (mouse-position) is supposed to work, | |
338 ** and I was just expecting something else. (mouse-pixel-position) | |
339 ** works just fine. | |
340 ** | |
341 ** William Perry Nov 7, 1999 | |
342 */ | |
343 static int | |
344 tty_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y) | |
345 { | |
346 Gpm_Event ev; | |
347 int num_buttons; | |
348 | |
349 memset(&ev,'\0',sizeof(ev)); | |
350 | |
351 num_buttons = Gpm_GetSnapshot(&ev); | |
352 | |
353 if (!num_buttons) | |
354 { | |
355 /* This means there are events pending... */ | |
356 | |
357 /* #### In theory, we should drain the events pending, stick | |
358 ** #### them in the queue, and return the mouse position | |
359 ** #### anyway. | |
360 */ | |
361 return(-1); | |
362 } | |
363 *x = ev.x; | |
364 *y = ev.y; | |
365 *frame = DEVICE_SELECTED_FRAME (d); | |
366 return (1); | |
367 } | |
368 | |
369 static void | |
370 tty_set_mouse_position (struct window *w, int x, int y) | |
371 { | |
372 /* | |
373 #### I couldn't find any GPM functions that set the mouse position. | |
374 #### Mr. Perry had left this function empty; that must be why. | |
375 #### karlheg | |
376 */ | |
377 } | |
378 | |
379 static int gpm_event_pending_p (int user_p) | |
380 { | |
381 Lisp_Object event; | |
382 | |
383 EVENT_CHAIN_LOOP (event, gpm_event_queue) | |
384 { | |
385 if (!user_p || command_event_p (event)) | |
386 { | |
387 return (1); | |
388 } | |
389 } | |
390 return (orig_event_pending_p (user_p)); | |
391 } | |
392 | |
393 static void gpm_next_event_cb (Lisp_Event *event) | |
394 { | |
395 /* #### It would be nice to preserve some sort of ordering of the | |
396 ** #### different types of events, but that would be quite a bit | |
397 ** #### of work, and would more than likely break the abstraction | |
398 ** #### between the other event loops and this one. | |
399 */ | |
400 | |
401 if (!NILP (gpm_event_queue)) | |
402 { | |
403 Lisp_Object queued_event = dequeue_event (&gpm_event_queue, &gpm_event_queue_tail); | |
404 *event = *(XEVENT (queued_event)); | |
405 | |
406 if (event->event_type == pointer_motion_event) | |
407 { | |
408 struct device *d = decode_device (event->channel); | |
409 int fd = DEVICE_INFD (d); | |
410 | |
411 /* Ok, now this is just freaky. Bear with me though. | |
412 ** | |
413 ** If you run gnuclient and attach to a XEmacs running in | |
414 ** X or on another TTY, the mouse cursor does not get | |
415 ** drawn correctly. This is because the ioctl() fails | |
416 ** with EPERM because the TTY specified is not our | |
417 ** controlling terminal. If you are the superuser, it | |
418 ** will work just spiffy. The appropriate source file (at | |
419 ** least in linux 2.2.x) is | |
420 ** .../linux/drivers/char/console.c in the function | |
421 ** tioclinux(). The following bit of code is brutal to | |
422 ** us: | |
423 ** | |
424 ** if (current->tty != tty && !suser()) | |
425 ** return -EPERM; | |
426 ** | |
427 ** I even tried setting us as a process leader, removing | |
428 ** our controlling terminal, and then using the TIOCSCTTY | |
429 ** to set up a new controlling terminal, all with no luck. | |
430 ** | |
431 ** What is even weirder is if you run XEmacs in a VC, and | |
432 ** attach to it from another VC with gnuclient, go back to | |
433 ** the original VC and hit a key, the mouse pointer | |
434 ** displays (in BOTH VCs), until you hit a key in the | |
435 ** second VC, after which it does not display in EITHER | |
436 ** VC. Bizarre, no? | |
437 ** | |
438 ** All I can say is thank god Linux comes with source code | |
439 ** or I would have been completely confused. Well, ok, | |
440 ** I'm still completely confused. I don't see why they | |
441 ** don't just check the permissions on the device | |
442 ** (actually, if you have enough access to it to get the | |
443 ** console's file descriptor, you should be able to do | |
444 ** with it as you wish, but maybe that is just me). | |
445 ** | |
446 ** William M. Perry - Nov 9, 1999 | |
447 */ | |
448 | |
449 Gpm_DrawPointer (event->event.motion.x,event->event.motion.y, fd); | |
450 } | |
451 | |
452 return; | |
453 } | |
454 | |
455 orig_next_event_cb (event); | |
456 } | |
457 | |
458 static void hook_event_callbacks_once (void) | |
459 { | |
460 static int hooker; | |
461 | |
462 if (!hooker) | |
463 { | |
464 orig_event_pending_p = event_stream->event_pending_p; | |
465 orig_next_event_cb = event_stream->next_event_cb; | |
466 event_stream->event_pending_p = gpm_event_pending_p; | |
467 event_stream->next_event_cb = gpm_next_event_cb; | |
468 hooker = 1; | |
469 } | |
470 } | |
471 | |
472 static void hook_console_methods_once (void) | |
473 { | |
474 static int hooker; | |
475 | |
476 if (!hooker) | |
477 { | |
478 /* Install the mouse position methods for the TTY console type */ | |
479 CONSOLE_HAS_METHOD (tty, get_mouse_position); | |
480 CONSOLE_HAS_METHOD (tty, set_mouse_position); | |
481 CONSOLE_HAS_METHOD (tty, get_foreign_selection); | |
482 CONSOLE_HAS_METHOD (tty, selection_exists_p); | |
483 #if 0 | |
484 CONSOLE_HAS_METHOD (tty, own_selection); | |
485 #endif | |
486 } | |
487 } | |
488 | |
489 DEFUN ("gpm-enabled-p", Fgpm_enabled_p, 0, 1, 0, /* | |
490 Return non-nil if GPM mouse support is currently enabled on DEVICE. | |
491 */ | |
492 (device)) | |
493 { | |
494 char *console_name = ttyname (DEVICE_INFD (decode_device (device))); | |
495 char process_name[1024]; | |
496 Lisp_Object proc; | |
497 | |
498 if (!console_name) | |
499 { | |
500 return (Qnil); | |
501 } | |
502 | |
503 memset (process_name, '\0', sizeof(process_name)); | |
504 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s", console_name); | |
505 | |
506 proc = Fget_process (build_string (process_name)); | |
507 | |
508 if (NILP (proc)) | |
509 { | |
510 return (Qnil); | |
511 } | |
512 | |
513 if (1) /* (PROCESS_LIVE_P (proc)) */ | |
514 { | |
515 return (Qt); | |
516 } | |
517 return (Qnil); | |
518 } | |
519 | |
520 DEFUN ("gpm-enable", Fgpm_enable, 0, 2, 0, /* | |
521 Toggle accepting of GPM mouse events. | |
522 */ | |
523 (device, arg)) | |
524 { | |
525 Gpm_Connect conn; | |
526 int rval; | |
527 Lisp_Object gpm_process; | |
528 Lisp_Object gpm_filter; | |
529 struct device *d = decode_device (device); | |
530 int fd = DEVICE_INFD (d); | |
531 char *console_name = ttyname (fd); | |
532 char process_name[1024]; | |
533 | |
534 hook_event_callbacks_once (); | |
535 hook_console_methods_once (); | |
536 | |
537 if (noninteractive) | |
538 { | |
539 error ("Can't connect to GPM in batch mode."); | |
540 } | |
541 | |
542 if (!console_name) | |
543 { | |
544 /* Something seriously wrong here... */ | |
545 return (Qnil); | |
546 } | |
547 | |
548 memset (process_name, '\0', sizeof(process_name)); | |
549 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s", console_name); | |
550 | |
551 if (NILP (arg)) | |
552 { | |
553 turn_off_gpm (process_name); | |
554 return (Qnil); | |
555 } | |
556 | |
557 /* DANGER DANGER. | |
558 ** Though shalt not call (gpm-enable t) after we have already | |
559 ** started, or stuff blows up. | |
560 */ | |
561 if (!NILP (Fgpm_enabled_p (device))) | |
562 { | |
563 error ("GPM already enabled for this console."); | |
564 } | |
565 | |
566 conn.eventMask = GPM_DOWN|GPM_UP|GPM_MOVE|GPM_DRAG; | |
567 conn.defaultMask = GPM_MOVE; | |
568 conn.minMod = 0; | |
569 conn.maxMod = ((1<<KG_SHIFT)|(1<<KG_ALT)|(1<<KG_CTRL)); | |
570 | |
571 /* Reset some silly static variables so that multiple Gpm_Open() | |
572 ** calls have even a sligh chance of working | |
573 */ | |
574 gpm_tried = 0; | |
575 gpm_flag = 0; | |
576 gpm_stack = NULL; | |
577 | |
578 /* Make sure Gpm_Open() does ioctl() on the correct | |
579 ** descriptor, or it can get the wrong terminal sizes, etc. | |
580 */ | |
581 gpm_consolefd = fd; | |
582 | |
583 /* We have to pass the virtual console manually, otherwise if you | |
584 ** use 'gnuclient -nw' to connect to an XEmacs that is running in | |
585 ** X, Gpm_Open() tries to use ttyname(0 | 1 | 2) to find out which | |
586 ** console you are using, which is of course not correct for the | |
587 ** new tty device. | |
588 */ | |
589 if (strncmp (console_name, "/dev/tty",8) || !isdigit (console_name[8])) | |
590 { | |
591 /* Urk, something really wrong */ | |
592 return (Qnil); | |
593 } | |
594 | |
595 rval = Gpm_Open (&conn, atoi(console_name + 8)); | |
596 | |
597 switch (rval) { | |
598 case -1: /* General failure */ | |
599 break; | |
600 case -2: /* We are running under an XTerm */ | |
601 Gpm_Close(); | |
602 break; | |
603 default: | |
604 /* Is this really necessary? */ | |
605 set_descriptor_non_blocking (gpm_fd); | |
606 store_gpm_state (gpm_fd); | |
607 gpm_process = connect_to_file_descriptor (build_string (process_name), Qnil, | |
608 make_int (gpm_fd), | |
609 make_int (gpm_fd)); | |
610 | |
611 if (!NILP (gpm_process)) | |
612 { | |
613 rval = 0; | |
614 Fprocess_kill_without_query (gpm_process, Qnil); | |
615 XSETSUBR (gpm_filter, &SFreceive_gpm_event); | |
616 set_process_filter (gpm_process, gpm_filter, 1); | |
617 | |
618 /* Keep track of the device for later */ | |
619 /* Fput (gpm_process, intern ("gpm-device"), device); */ | |
620 } | |
621 else | |
622 { | |
623 Gpm_Close(); | |
624 rval = -1; | |
625 } | |
626 } | |
627 | |
628 return(rval ? Qnil : Qt); | |
629 } | |
630 | |
631 void vars_of_gpmevent (void) | |
632 { | |
633 gpm_event_queue = Qnil; | |
634 gpm_event_queue_tail = Qnil; | |
635 staticpro (&gpm_event_queue); | |
636 staticpro (&gpm_event_queue_tail); | |
637 pdump_wire (&gpm_event_queue); | |
638 pdump_wire (&gpm_event_queue_tail); | |
639 } | |
640 | |
641 void syms_of_gpmevent (void) | |
642 { | |
643 DEFSUBR (Freceive_gpm_event); | |
644 DEFSUBR (Fgpm_enable); | |
645 DEFSUBR (Fgpm_enabled_p); | |
646 } | |
647 | |
648 #endif /* HAVE_GPM */ |