Mercurial > hg > xemacs-beta
comparison src/gpmevent.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
1 /* GPM (General purpose mouse) functions | 1 /* William Perry 1997 */ |
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 */ | |
25 | 2 |
26 #include <config.h> | 3 #include <config.h> |
27 #include "lisp.h" | 4 #include "lisp.h" |
28 #include "console.h" | 5 #include "console.h" |
29 #include "console-tty.h" | 6 #include "console-tty.h" |
30 #include "device.h" | 7 #include "device.h" |
31 #include "events.h" | 8 #include "events.h" |
32 #include "events-mod.h" | 9 #include "events-mod.h" |
33 #include "sysdep.h" | 10 #include "sysdep.h" |
34 #include "commands.h" | |
35 #include "lstream.h" | |
36 #include "sysproc.h" /* for MAXDESC */ | |
37 #include "process.h" | |
38 | 11 |
39 #ifdef HAVE_GPM | 12 #ifdef HAVE_GPM |
40 #include "gpmevent.h" | 13 #include "gpmevent.h" |
41 #include <gpm.h> | 14 #include <gpm.h> |
42 | 15 |
46 #define KG_ALT 3 | 19 #define KG_ALT 3 |
47 #else | 20 #else |
48 #include <linux/keyboard.h> | 21 #include <linux/keyboard.h> |
49 #endif | 22 #endif |
50 | 23 |
51 extern int gpm_tried; | 24 int |
52 extern void *gpm_stack; | 25 handle_gpm_read (struct Lisp_Event *event, struct console *con, int fd) |
26 { | |
27 Gpm_Event ev; | |
28 int modifiers = 0; | |
29 int type = -1; | |
30 int button = 1; | |
53 | 31 |
54 static int (*orig_event_pending_p) (int); | 32 if (!Gpm_GetEvent(&ev)) |
55 static void (*orig_next_event_cb) (Lisp_Event *); | 33 return 0; |
56 | 34 |
57 static Lisp_Object gpm_event_queue; | 35 event->timestamp = 0; |
58 static Lisp_Object gpm_event_queue_tail; | 36 event->channel = CONSOLE_SELECTED_FRAME (con); |
59 | 37 |
60 struct __gpm_state { | 38 /* Whow, wouldn't named defines be NICE!?!?! */ |
61 int gpm_tried; | 39 modifiers = 0; |
62 int gpm_flag; | |
63 void *gpm_stack; | |
64 }; | |
65 | 40 |
66 static struct __gpm_state gpm_state_information[MAXDESC]; | 41 if (ev.modifiers & 1) modifiers |= MOD_SHIFT; |
42 if (ev.modifiers & 2) modifiers |= MOD_META; | |
43 if (ev.modifiers & 4) modifiers |= MOD_CONTROL; | |
44 if (ev.modifiers & 8) modifiers |= MOD_META; | |
67 | 45 |
68 static void | 46 if (ev.type & GPM_DOWN) |
69 store_gpm_state (int fd) | 47 type = GPM_DOWN; |
70 { | 48 else if (ev.type & GPM_UP) |
71 gpm_state_information[fd].gpm_tried = gpm_tried; | 49 type = GPM_UP; |
72 gpm_state_information[fd].gpm_flag = gpm_flag; | 50 else if (ev.type & GPM_MOVE) { |
73 gpm_state_information[fd].gpm_stack = gpm_stack; | 51 type = GPM_MOVE; |
52 GPM_DRAWPOINTER(&ev); | |
53 } | |
54 | |
55 if (ev.buttons & GPM_B_LEFT) | |
56 button = 1; | |
57 else if (ev.buttons & GPM_B_MIDDLE) | |
58 button = 2; | |
59 else if (ev.buttons & GPM_B_RIGHT) | |
60 button = 3; | |
61 | |
62 switch (type) { | |
63 case GPM_DOWN: | |
64 case GPM_UP: | |
65 event->event_type = | |
66 type == GPM_DOWN ? button_press_event : button_release_event; | |
67 event->event.button.x = ev.x; | |
68 event->event.button.y = ev.y; | |
69 event->event.button.button = button; | |
70 event->event.button.modifiers = modifiers; | |
71 break; | |
72 case GPM_MOVE: | |
73 event->event_type = pointer_motion_event; | |
74 event->event.motion.x = ev.x; | |
75 event->event.motion.y = ev.y; | |
76 event->event.motion.modifiers = modifiers; | |
77 default: | |
78 return 0; | |
79 } | |
80 return 1; | |
74 } | 81 } |
75 | 82 |
76 static void | 83 void |
77 restore_gpm_state (int fd) | 84 connect_to_gpm (struct console *con) |
78 { | 85 { |
79 gpm_tried = gpm_state_information[fd].gpm_tried; | 86 /* Only do this if we are running after dumping and really interactive */ |
80 gpm_flag = gpm_state_information[fd].gpm_flag; | 87 if (!noninteractive && initialized) { |
81 gpm_stack = gpm_state_information[fd].gpm_stack; | 88 /* We really only want to do this on a TTY */ |
82 gpm_consolefd = gpm_fd = fd; | 89 CONSOLE_TTY_MOUSE_FD (con) = -1; |
90 if (EQ (CONSOLE_TYPE (con), Qtty)) { | |
91 Gpm_Connect conn; | |
92 int rval; | |
93 | |
94 conn.eventMask = GPM_DOWN|GPM_UP|GPM_MOVE; | |
95 conn.defaultMask = GPM_MOVE; | |
96 conn.minMod = 0; | |
97 conn.maxMod = ((1<<KG_SHIFT)|(1<<KG_ALT)|(1<<KG_CTRL)); | |
98 | |
99 rval = Gpm_Open (&conn, 0); | |
100 switch (rval) { | |
101 case -1: /* General failure */ | |
102 break; | |
103 case -2: /* We are running under an XTerm */ | |
104 Gpm_Close(); | |
105 break; | |
106 default: | |
107 set_descriptor_non_blocking (gpm_fd); | |
108 CONSOLE_TTY_MOUSE_FD (con) = gpm_fd; | |
109 } | |
110 } | |
111 } | |
83 } | 112 } |
84 | 113 |
85 static void | |
86 clear_gpm_state (int fd) | |
87 { | |
88 if (fd >= 0) | |
89 { | |
90 memset(&gpm_state_information[fd], '\0', sizeof(struct __gpm_state)); | |
91 } | |
92 gpm_tried = gpm_flag = 1; | |
93 gpm_fd = gpm_consolefd = -1; | |
94 gpm_stack = NULL; | |
95 } | |
96 | |
97 static int | |
98 get_process_infd (Lisp_Process *p) | |
99 { | |
100 Lisp_Object instr, outstr; | |
101 get_process_streams (p, &instr, &outstr); | |
102 assert (!NILP (instr)); | |
103 return filedesc_stream_fd (XLSTREAM (instr)); | |
104 } | |
105 | |
106 DEFUN ("receive-gpm-event", Freceive_gpm_event, 0, 2, 0, /* | |
107 Run GPM_GetEvent(). | |
108 This function is the process handler for the GPM connection. | |
109 */ | |
110 (process, string)) | |
111 { | |
112 Gpm_Event ev; | |
113 int modifiers = 0; | |
114 int button = 1; | |
115 Lisp_Object fake_event; | |
116 Lisp_Event *event = NULL; | |
117 struct gcpro gcpro1; | |
118 static int num_events; | |
119 | |
120 CHECK_PROCESS (process); | |
121 | |
122 restore_gpm_state (get_process_infd (XPROCESS (process))); | |
123 | |
124 if (!Gpm_GetEvent(&ev)) | |
125 { | |
126 warn_when_safe (Qnil, Qcritical, "Gpm_GetEvent failed - %d", gpm_fd); | |
127 return(Qzero); | |
128 } | |
129 | |
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 |= XEMACS_MOD_SHIFT; | |
144 if (ev.modifiers & 2) modifiers |= XEMACS_MOD_META; | |
145 if (ev.modifiers & 4) modifiers |= XEMACS_MOD_CONTROL; | |
146 if (ev.modifiers & 8) modifiers |= XEMACS_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 | |
205 Gpm_Close(); | |
206 | |
207 clear_gpm_state (fd); | |
208 | |
209 Fdelete_process (build_string (process_name)); | |
210 } | |
211 | |
212 #ifdef TIOCLINUX | |
213 static Lisp_Object | |
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, Lisp_Object selection_type) | |
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 Lisp_Object how_to_add, Lisp_Object selection_type) | |
322 { | |
323 /* There is no way to do this cleanly - the GPM selection | |
324 ** 'protocol' (actually the TIOCLINUX ioctl) requires a start and | |
325 ** end position on the _screen_, not a string to stick in there. | |
326 ** Lame. | |
327 ** | |
328 ** William Perry Nov 4, 1999 | |
329 */ | |
330 } | |
331 #endif | 114 #endif |
332 | |
333 /* This function appears to work once in a blue moon. I'm not sure | |
334 ** exactly why either. *sigh* | |
335 ** | |
336 ** William Perry Nov 4, 1999 | |
337 ** | |
338 ** Apparently, this is the way (mouse-position) is supposed to work, | |
339 ** and I was just expecting something else. (mouse-pixel-position) | |
340 ** works just fine. | |
341 ** | |
342 ** William Perry Nov 7, 1999 | |
343 */ | |
344 static int | |
345 tty_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y) | |
346 { | |
347 Gpm_Event ev; | |
348 int num_buttons; | |
349 | |
350 memset(&ev,'\0',sizeof(ev)); | |
351 | |
352 num_buttons = Gpm_GetSnapshot(&ev); | |
353 | |
354 if (!num_buttons) | |
355 { | |
356 /* This means there are events pending... */ | |
357 | |
358 /* #### In theory, we should drain the events pending, stick | |
359 ** #### them in the queue, and return the mouse position | |
360 ** #### anyway. | |
361 */ | |
362 return(-1); | |
363 } | |
364 *x = ev.x; | |
365 *y = ev.y; | |
366 *frame = DEVICE_SELECTED_FRAME (d); | |
367 return (1); | |
368 } | |
369 | |
370 static void | |
371 tty_set_mouse_position (struct window *w, int x, int y) | |
372 { | |
373 /* | |
374 #### I couldn't find any GPM functions that set the mouse position. | |
375 #### Mr. Perry had left this function empty; that must be why. | |
376 #### karlheg | |
377 */ | |
378 } | |
379 | |
380 static int gpm_event_pending_p (int user_p) | |
381 { | |
382 Lisp_Object event; | |
383 | |
384 EVENT_CHAIN_LOOP (event, gpm_event_queue) | |
385 { | |
386 if (!user_p || command_event_p (event)) | |
387 { | |
388 return (1); | |
389 } | |
390 } | |
391 return (orig_event_pending_p (user_p)); | |
392 } | |
393 | |
394 static void gpm_next_event_cb (Lisp_Event *event) | |
395 { | |
396 /* #### It would be nice to preserve some sort of ordering of the | |
397 ** #### different types of events, but that would be quite a bit | |
398 ** #### of work, and would more than likely break the abstraction | |
399 ** #### between the other event loops and this one. | |
400 */ | |
401 | |
402 if (!NILP (gpm_event_queue)) | |
403 { | |
404 Lisp_Object queued_event = dequeue_event (&gpm_event_queue, &gpm_event_queue_tail); | |
405 *event = *(XEVENT (queued_event)); | |
406 | |
407 if (event->event_type == pointer_motion_event) | |
408 { | |
409 struct device *d = decode_device (event->channel); | |
410 int fd = DEVICE_INFD (d); | |
411 | |
412 /* Ok, now this is just freaky. Bear with me though. | |
413 ** | |
414 ** If you run gnuclient and attach to a XEmacs running in | |
415 ** X or on another TTY, the mouse cursor does not get | |
416 ** drawn correctly. This is because the ioctl() fails | |
417 ** with EPERM because the TTY specified is not our | |
418 ** controlling terminal. If you are the superuser, it | |
419 ** will work just spiffy. The appropriate source file (at | |
420 ** least in linux 2.2.x) is | |
421 ** .../linux/drivers/char/console.c in the function | |
422 ** tioclinux(). The following bit of code is brutal to | |
423 ** us: | |
424 ** | |
425 ** if (current->tty != tty && !suser()) | |
426 ** return -EPERM; | |
427 ** | |
428 ** I even tried setting us as a process leader, removing | |
429 ** our controlling terminal, and then using the TIOCSCTTY | |
430 ** to set up a new controlling terminal, all with no luck. | |
431 ** | |
432 ** What is even weirder is if you run XEmacs in a VC, and | |
433 ** attach to it from another VC with gnuclient, go back to | |
434 ** the original VC and hit a key, the mouse pointer | |
435 ** displays (in BOTH VCs), until you hit a key in the | |
436 ** second VC, after which it does not display in EITHER | |
437 ** VC. Bizarre, no? | |
438 ** | |
439 ** All I can say is thank god Linux comes with source code | |
440 ** or I would have been completely confused. Well, ok, | |
441 ** I'm still completely confused. I don't see why they | |
442 ** don't just check the permissions on the device | |
443 ** (actually, if you have enough access to it to get the | |
444 ** console's file descriptor, you should be able to do | |
445 ** with it as you wish, but maybe that is just me). | |
446 ** | |
447 ** William M. Perry - Nov 9, 1999 | |
448 */ | |
449 | |
450 Gpm_DrawPointer (event->event.motion.x,event->event.motion.y, fd); | |
451 } | |
452 | |
453 return; | |
454 } | |
455 | |
456 orig_next_event_cb (event); | |
457 } | |
458 | |
459 static void hook_event_callbacks_once (void) | |
460 { | |
461 static int hooker; | |
462 | |
463 if (!hooker) | |
464 { | |
465 orig_event_pending_p = event_stream->event_pending_p; | |
466 orig_next_event_cb = event_stream->next_event_cb; | |
467 event_stream->event_pending_p = gpm_event_pending_p; | |
468 event_stream->next_event_cb = gpm_next_event_cb; | |
469 hooker = 1; | |
470 } | |
471 } | |
472 | |
473 static void hook_console_methods_once (void) | |
474 { | |
475 static int hooker; | |
476 | |
477 if (!hooker) | |
478 { | |
479 /* Install the mouse position methods for the TTY console type */ | |
480 CONSOLE_HAS_METHOD (tty, get_mouse_position); | |
481 CONSOLE_HAS_METHOD (tty, set_mouse_position); | |
482 CONSOLE_HAS_METHOD (tty, get_foreign_selection); | |
483 CONSOLE_HAS_METHOD (tty, selection_exists_p); | |
484 #if 0 | |
485 CONSOLE_HAS_METHOD (tty, own_selection); | |
486 #endif | |
487 } | |
488 } | |
489 | |
490 DEFUN ("gpm-enabled-p", Fgpm_enabled_p, 0, 1, 0, /* | |
491 Return non-nil if GPM mouse support is currently enabled on DEVICE. | |
492 */ | |
493 (device)) | |
494 { | |
495 char *console_name = ttyname (DEVICE_INFD (decode_device (device))); | |
496 char process_name[1024]; | |
497 Lisp_Object proc; | |
498 | |
499 if (!console_name) | |
500 { | |
501 return (Qnil); | |
502 } | |
503 | |
504 memset (process_name, '\0', sizeof(process_name)); | |
505 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s", console_name); | |
506 | |
507 proc = Fget_process (build_string (process_name)); | |
508 | |
509 if (NILP (proc)) | |
510 { | |
511 return (Qnil); | |
512 } | |
513 | |
514 if (1) /* (PROCESS_LIVE_P (proc)) */ | |
515 { | |
516 return (Qt); | |
517 } | |
518 return (Qnil); | |
519 } | |
520 | |
521 DEFUN ("gpm-enable", Fgpm_enable, 0, 2, 0, /* | |
522 Toggle accepting of GPM mouse events. | |
523 */ | |
524 (device, arg)) | |
525 { | |
526 Gpm_Connect conn; | |
527 int rval; | |
528 Lisp_Object gpm_process; | |
529 Lisp_Object gpm_filter; | |
530 struct device *d = decode_device (device); | |
531 int fd = DEVICE_INFD (d); | |
532 char *console_name = ttyname (fd); | |
533 char process_name[1024]; | |
534 | |
535 hook_event_callbacks_once (); | |
536 hook_console_methods_once (); | |
537 | |
538 if (noninteractive) | |
539 { | |
540 error ("Can't connect to GPM in batch mode."); | |
541 } | |
542 | |
543 if (!console_name) | |
544 { | |
545 /* Something seriously wrong here... */ | |
546 return (Qnil); | |
547 } | |
548 | |
549 memset (process_name, '\0', sizeof(process_name)); | |
550 snprintf (process_name, sizeof(process_name) - 1, "gpm for %s", console_name); | |
551 | |
552 if (NILP (arg)) | |
553 { | |
554 turn_off_gpm (process_name); | |
555 return (Qnil); | |
556 } | |
557 | |
558 /* DANGER DANGER. | |
559 ** Though shalt not call (gpm-enable t) after we have already | |
560 ** started, or stuff blows up. | |
561 */ | |
562 if (!NILP (Fgpm_enabled_p (device))) | |
563 { | |
564 error ("GPM already enabled for this console."); | |
565 } | |
566 | |
567 conn.eventMask = GPM_DOWN|GPM_UP|GPM_MOVE|GPM_DRAG; | |
568 conn.defaultMask = GPM_MOVE; | |
569 conn.minMod = 0; | |
570 conn.maxMod = ((1<<KG_SHIFT)|(1<<KG_ALT)|(1<<KG_CTRL)); | |
571 | |
572 /* Reset some silly static variables so that multiple Gpm_Open() | |
573 ** calls have even a sligh chance of working | |
574 */ | |
575 gpm_tried = 0; | |
576 gpm_flag = 0; | |
577 gpm_stack = NULL; | |
578 | |
579 /* Make sure Gpm_Open() does ioctl() on the correct | |
580 ** descriptor, or it can get the wrong terminal sizes, etc. | |
581 */ | |
582 gpm_consolefd = fd; | |
583 | |
584 /* We have to pass the virtual console manually, otherwise if you | |
585 ** use 'gnuclient -nw' to connect to an XEmacs that is running in | |
586 ** X, Gpm_Open() tries to use ttyname(0 | 1 | 2) to find out which | |
587 ** console you are using, which is of course not correct for the | |
588 ** new tty device. | |
589 */ | |
590 if (strncmp (console_name, "/dev/tty",8) || !isdigit (console_name[8])) | |
591 { | |
592 /* Urk, something really wrong */ | |
593 return (Qnil); | |
594 } | |
595 | |
596 rval = Gpm_Open (&conn, atoi(console_name + 8)); | |
597 | |
598 switch (rval) { | |
599 case -1: /* General failure */ | |
600 break; | |
601 case -2: /* We are running under an XTerm */ | |
602 Gpm_Close(); | |
603 break; | |
604 default: | |
605 /* Is this really necessary? */ | |
606 set_descriptor_non_blocking (gpm_fd); | |
607 store_gpm_state (gpm_fd); | |
608 gpm_process = connect_to_file_descriptor (build_string (process_name), Qnil, | |
609 make_int (gpm_fd), | |
610 make_int (gpm_fd)); | |
611 | |
612 if (!NILP (gpm_process)) | |
613 { | |
614 rval = 0; | |
615 Fprocess_kill_without_query (gpm_process, Qnil); | |
616 XSETSUBR (gpm_filter, &SFreceive_gpm_event); | |
617 set_process_filter (gpm_process, gpm_filter, 1); | |
618 | |
619 /* Keep track of the device for later */ | |
620 /* Fput (gpm_process, intern ("gpm-device"), device); */ | |
621 } | |
622 else | |
623 { | |
624 Gpm_Close(); | |
625 rval = -1; | |
626 } | |
627 } | |
628 | |
629 return(rval ? Qnil : Qt); | |
630 } | |
631 | |
632 void vars_of_gpmevent (void) | |
633 { | |
634 gpm_event_queue = Qnil; | |
635 gpm_event_queue_tail = Qnil; | |
636 staticpro (&gpm_event_queue); | |
637 staticpro (&gpm_event_queue_tail); | |
638 pdump_wire (&gpm_event_queue); | |
639 pdump_wire (&gpm_event_queue_tail); | |
640 } | |
641 | |
642 void syms_of_gpmevent (void) | |
643 { | |
644 DEFSUBR (Freceive_gpm_event); | |
645 DEFSUBR (Fgpm_enable); | |
646 DEFSUBR (Fgpm_enabled_p); | |
647 } | |
648 | |
649 #endif /* HAVE_GPM */ |