Mercurial > hg > xemacs-beta
comparison src/event-msw.c @ 213:78f53ef88e17 r20-4b5
Import from CVS: tag r20-4b5
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:06:47 +0200 |
parents | |
children | 262b8bb4a523 |
comparison
equal
deleted
inserted
replaced
212:d8688acf4c5b | 213:78f53ef88e17 |
---|---|
1 /* The mswindows event_stream interface. | |
2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Sun Microsystems, Inc. | |
4 Copyright (C) 1996 Ben Wing. | |
5 Copyright (C) 1997 Jonathan Harris. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 | |
26 /* Authorship: | |
27 | |
28 Ultimately based on FSF. | |
29 Rewritten by Ben Wing. | |
30 Rewritten for mswindows by Jonathan Harris, November 1997 for 20.4. | |
31 */ | |
32 | |
33 #include <config.h> | |
34 #include "lisp.h" | |
35 | |
36 #include "device.h" | |
37 #include "console-msw.h" | |
38 #include "events.h" | |
39 #include "frame.h" | |
40 #include "process.h" | |
41 | |
42 #include "sysproc.h" | |
43 #include "syswait.h" | |
44 #include "systime.h" | |
45 | |
46 #include "event-msw.h" | |
47 | |
48 static struct event_stream *mswindows_event_stream; | |
49 static Lisp_Object mswindows_dispatch_event_queue, mswindows_dispatch_event_queue_tail; | |
50 static mswindows_waitable_count=0; | |
51 CRITICAL_SECTION mswindows_dispatch_crit; | |
52 | |
53 static Lisp_Object mswindows_dequeue_dispatch_event (void); | |
54 | |
55 /* | |
56 * List of mswindows waitable handles. | |
57 * Apart from the dispatch queue semaphore, all of these handles may be waited | |
58 * on multiple times in emacs_mswindows_next_event before being processed and so must | |
59 * be manual-reset events. | |
60 */ | |
61 static HANDLE mswindows_waitable[MAX_WAITABLE]; | |
62 | |
63 /* random emacs info associated with each of the wait handles */ | |
64 static mswindows_waitable_info_type mswindows_waitable_info[MAX_WAITABLE]; | |
65 | |
66 void | |
67 mswindows_enqueue_dispatch_event (Lisp_Object event) | |
68 { | |
69 assert(mswindows_waitable_count); | |
70 // EnterCriticalSection (&mswindows_dispatch_crit); | |
71 enqueue_event (event, &mswindows_dispatch_event_queue, &mswindows_dispatch_event_queue_tail); | |
72 ReleaseSemaphore(mswindows_waitable[0], 1, NULL); | |
73 // LeaveCriticalSection (&mswindows_dispatch_crit); | |
74 } | |
75 | |
76 static Lisp_Object | |
77 mswindows_dequeue_dispatch_event (void) | |
78 { | |
79 Lisp_Object event; | |
80 assert(mswindows_waitable_count); | |
81 // EnterCriticalSection (&mswindows_dispatch_crit); | |
82 event = dequeue_event (&mswindows_dispatch_event_queue, &mswindows_dispatch_event_queue_tail); | |
83 // LeaveCriticalSection (&mswindows_dispatch_crit); | |
84 return event; | |
85 } | |
86 | |
87 /* | |
88 * Find a free waitable slot | |
89 */ | |
90 static int | |
91 mswindows_find_free_waitable(void) | |
92 { | |
93 int i; | |
94 for (i=0; i<mswindows_waitable_count; i++) | |
95 if (mswindows_waitable_info[i].type == mswindows_waitable_type_none) | |
96 return i; | |
97 assert (mswindows_waitable_count < MAX_WAITABLE); | |
98 return mswindows_waitable_count++; | |
99 } | |
100 | |
101 /* | |
102 * Create a new waitable using the type and data passed in by the info structure | |
103 * Returns a pointer to the info associated with the assigned waitable object | |
104 */ | |
105 mswindows_waitable_info_type * | |
106 mswindows_add_waitable(mswindows_waitable_info_type *info) | |
107 { | |
108 int waitable; | |
109 | |
110 switch (info->type) | |
111 { | |
112 case mswindows_waitable_type_dispatch: | |
113 /* Can only have one waitable for the dispatch queue, and it's the first one */ | |
114 assert (mswindows_waitable_count++ == 0); | |
115 waitable=0; | |
116 InitializeCriticalSection(&mswindows_dispatch_crit); | |
117 assert (mswindows_waitable[0] = CreateSemaphore (NULL, 0, 0x7fffffff, NULL)); | |
118 return mswindows_waitable_info+0; | |
119 | |
120 #if 0 /* Windows95 doesn't support WaitableTimers */ | |
121 case mswindows_waitable_type_timeout: | |
122 { | |
123 LARGE_INTEGER due; | |
124 due.QuadPart = 10000 * (LONGLONG) info->data.timeout.milliseconds; | |
125 waitable = mswindows_find_free_waitable(); | |
126 mswindows_waitable[waitable] = CreateWaitableTimer(NULL, TRUE, NULL); | |
127 SetWaitableTimer(mswindows_waitable[waitable], &due, 0, NULL, NULL, FALSE); | |
128 mswindows_waitable_info[waitable].data.timeout.id = waitable; | |
129 } | |
130 break; | |
131 #endif | |
132 | |
133 default: | |
134 assert(0); | |
135 } | |
136 mswindows_waitable_info[waitable].type = info->type; | |
137 return mswindows_waitable_info+waitable; | |
138 } | |
139 | |
140 /* | |
141 * Remove a waitable using the type and data passed in by the info structure. | |
142 */ | |
143 void | |
144 mswindows_remove_waitable(mswindows_waitable_info_type *info) | |
145 { | |
146 int waitable; | |
147 | |
148 switch (info->type) | |
149 { | |
150 #if 0 | |
151 case mswindows_waitable_type_timeout: | |
152 waitable = info->data.timeout.id; | |
153 CancelWaitableTimeout(mswindows_waitable[waitable]); | |
154 break; | |
155 #endif | |
156 | |
157 default: | |
158 assert(0); | |
159 } | |
160 | |
161 CloseHandle(mswindows_waitable[waitable]); | |
162 mswindows_waitable[waitable] = 0; | |
163 mswindows_waitable_info[waitable].type = mswindows_waitable_type_none; | |
164 if (waitable == mswindows_waitable_count-1) | |
165 --mswindows_waitable_count; | |
166 } | |
167 | |
168 | |
169 /************************************************************************/ | |
170 /* methods */ | |
171 /************************************************************************/ | |
172 | |
173 static int | |
174 emacs_mswindows_add_timeout (EMACS_TIME thyme) | |
175 { | |
176 EMACS_TIME current_time; | |
177 int milliseconds; | |
178 int id; | |
179 mswindows_request_type request; | |
180 | |
181 EMACS_GET_TIME (current_time); | |
182 EMACS_SUB_TIME (thyme, thyme, current_time); | |
183 milliseconds = EMACS_SECS (thyme) * 1000 + EMACS_USECS (thyme) / 1000; | |
184 if (milliseconds < 1) | |
185 milliseconds = 1; | |
186 request.thing1 = (void *) milliseconds; | |
187 id = mswindows_make_request(WM_XEMACS_SETTIMER, 0, &request); | |
188 assert(id); /* XXX */ | |
189 return id; | |
190 } | |
191 | |
192 static void | |
193 emacs_mswindows_remove_timeout (int id) | |
194 { | |
195 mswindows_request_type request = { (void *) id }; | |
196 mswindows_make_request(WM_XEMACS_KILLTIMER, 0, &request); | |
197 } | |
198 | |
199 static int | |
200 emacs_mswindows_event_pending_p (int user_p) | |
201 { | |
202 return 0; | |
203 } | |
204 | |
205 static struct console * | |
206 find_console_from_fd (int fd) | |
207 { | |
208 return 0; | |
209 } | |
210 | |
211 /* | |
212 * Return the next event | |
213 * We return windows events off the dispatch event queue in preference to other events | |
214 */ | |
215 static void | |
216 emacs_mswindows_next_event (struct Lisp_Event *emacs_event) | |
217 { | |
218 DWORD active; | |
219 active = WaitForMultipleObjects (mswindows_waitable_count, mswindows_waitable, | |
220 FALSE, INFINITE); | |
221 assert(active >= WAIT_OBJECT_0 && active <= WAIT_OBJECT_0 + mswindows_waitable_count - 1); | |
222 | |
223 /* Windows events on the dispatch event queue */ | |
224 if (active == WAIT_OBJECT_0) | |
225 { | |
226 /* XXX Copied from event-Xt.c */ | |
227 Lisp_Object event, event2; | |
228 | |
229 EnterCriticalSection (&mswindows_dispatch_crit); | |
230 XSETEVENT (event2, emacs_event); | |
231 event = mswindows_dequeue_dispatch_event (); | |
232 Fcopy_event (event, event2); | |
233 Fdeallocate_event (event); | |
234 LeaveCriticalSection (&mswindows_dispatch_crit); | |
235 } | |
236 else | |
237 { | |
238 /* XXX FIXME: We should do some kind of round-robin scheme to ensure fairness */ | |
239 int waitable = active - WAIT_OBJECT_0; | |
240 mswindows_waitable_info_type *info = mswindows_waitable_info + waitable; | |
241 | |
242 switch (info->type) | |
243 { | |
244 case mswindows_waitable_type_timeout: | |
245 emacs_event->channel = Qnil; | |
246 emacs_event->event_type = timeout_event; | |
247 emacs_event->event.timeout.interval_id = info->data.timeout.id; | |
248 mswindows_remove_waitable(info); | |
249 break; | |
250 | |
251 default: | |
252 assert(0); | |
253 } | |
254 } | |
255 } | |
256 | |
257 /* | |
258 * Handle a magic event off the dispatch queue. | |
259 * XXX split into seperate functions for clarity. | |
260 */ | |
261 static void | |
262 emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event) | |
263 { | |
264 RECT *rect = &EVENT_MSWINDOWS_MAGIC_DATA(emacs_event); | |
265 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event)); | |
266 Lisp_Object frame = Qnil; | |
267 XSETFRAME (frame, f); | |
268 #if 0 | |
269 stderr_out("magic %x, (%d,%d), (%d,%d)\n", | |
270 EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event), | |
271 rect->left, rect->top, rect->right, rect->bottom); | |
272 #endif | |
273 switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event)) | |
274 { | |
275 case WM_SETFOCUS: | |
276 case WM_KILLFOCUS: | |
277 { | |
278 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS); | |
279 Lisp_Object conser; | |
280 /* struct gcpro gcpro1; */ | |
281 | |
282 /* Clear sticky modifiers here (if we had any) */ | |
283 | |
284 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil)); | |
285 /* GCPRO1 (conser); XXX Not necessary? */ | |
286 emacs_handle_focus_change_preliminary (conser); | |
287 /* Under X the stuff up to here is done in the X event handler. | |
288 I Don't know why */ | |
289 emacs_handle_focus_change_final (conser); | |
290 /* UNGCPRO; */ | |
291 } | |
292 break; | |
293 | |
294 /* XXX What about Enter & Leave */ | |
295 #if 0 | |
296 va_run_hook_with_args (in_p ? Qmouse_enter_frame_hook : | |
297 Qmouse_leave_frame_hook, 1, frame); | |
298 break; | |
299 #endif | |
300 | |
301 case WM_SIZE: | |
302 if ((rect->left & rect->top & rect->right & rect->bottom) == -1) | |
303 { | |
304 /* Iconified */ | |
305 FRAME_VISIBLE_P (f) = 0; | |
306 va_run_hook_with_args (Qunmap_frame_hook, 1, frame); | |
307 Fframe_iconified_p (frame); | |
308 } | |
309 else | |
310 { | |
311 /* If we're uniconified, our size may or may not have changed */ | |
312 int columns, rows; | |
313 int was_visible = FRAME_VISIBLE_P (f); | |
314 pixel_to_char_size (f, rect->right, rect->bottom, &columns, &rows); | |
315 | |
316 FRAME_VISIBLE_P (f) = 1; | |
317 if (f->height!=rows || f->width!=columns || f->size_change_pending) | |
318 { | |
319 /* Size changed */ | |
320 f->pixwidth = rect->right; | |
321 f->pixheight = rect->bottom; | |
322 change_frame_size (f, rows, columns, 0); | |
323 /* MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* XXX Too extreme? */ | |
324 } | |
325 | |
326 if (!was_visible) | |
327 va_run_hook_with_args (Qmap_frame_hook, 1, frame); | |
328 | |
329 } | |
330 break; | |
331 | |
332 case WM_PAINT: | |
333 mswindows_redraw_exposed_area(f, rect->left, rect->top, | |
334 rect->right, rect->bottom); | |
335 break; | |
336 | |
337 default: | |
338 assert(0); | |
339 } | |
340 } | |
341 | |
342 static void | |
343 emacs_mswindows_select_process (struct Lisp_Process *process) | |
344 { | |
345 } | |
346 | |
347 static void | |
348 emacs_mswindows_unselect_process (struct Lisp_Process *process) | |
349 { | |
350 } | |
351 | |
352 static void | |
353 emacs_mswindows_select_console (struct console *con) | |
354 { | |
355 } | |
356 | |
357 static void | |
358 emacs_mswindows_unselect_console (struct console *con) | |
359 { | |
360 } | |
361 | |
362 static void | |
363 emacs_mswindows_quit_p (void) | |
364 { | |
365 } | |
366 | |
367 /* This is called from GC when a process object is about to be freed. | |
368 If we've still got pointers to it in this file, we're gonna lose hard. | |
369 */ | |
370 void | |
371 debug_process_finalization (struct Lisp_Process *p) | |
372 { | |
373 #if 0 /* #### */ | |
374 int i; | |
375 int infd, outfd; | |
376 get_process_file_descriptors (p, &infd, &outfd); | |
377 /* if it still has fds, then it hasn't been killed yet. */ | |
378 assert (infd < 0); | |
379 assert (outfd < 0); | |
380 /* Better not still be in the "with input" table; we know it's got no fds. */ | |
381 for (i = 0; i < MAXDESC; i++) | |
382 { | |
383 Lisp_Object process = filedesc_fds_with_input [i]; | |
384 assert (!PROCESSP (process) || XPROCESS (process) != p); | |
385 } | |
386 #endif | |
387 } | |
388 | |
389 /************************************************************************/ | |
390 /* initialization */ | |
391 /************************************************************************/ | |
392 | |
393 void | |
394 vars_of_event_mswindows (void) | |
395 { | |
396 mswindows_dispatch_event_queue = Qnil; | |
397 staticpro (&mswindows_dispatch_event_queue); | |
398 mswindows_dispatch_event_queue_tail = Qnil; | |
399 | |
400 mswindows_event_stream = xnew (struct event_stream); | |
401 | |
402 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; | |
403 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; | |
404 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event; | |
405 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout; | |
406 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout; | |
407 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console; | |
408 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console; | |
409 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process; | |
410 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process; | |
411 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; | |
412 } | |
413 | |
414 void | |
415 syms_of_event_mswindows (void) | |
416 { | |
417 } | |
418 | |
419 void | |
420 init_event_mswindows_late (void) | |
421 { | |
422 event_stream = mswindows_event_stream; | |
423 } |