1 /* Functions taken directly from X sources for use with the Microsoft Windows API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2013 Free Software
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
29 #include "blockinput.h"
33 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
34 #define myfree(lp) GlobalFreePtr (lp)
36 CRITICAL_SECTION critsect
;
39 extern HANDLE keyboard_handle
;
40 #endif /* WINDOWSNT */
42 HANDLE input_available
= NULL
;
43 HANDLE interrupt_handle
= NULL
;
48 InitializeCriticalSection (&critsect
);
50 /* For safety, input_available should only be reset by get_next_msg
51 when the input queue is empty, so make it a manual reset event. */
52 input_available
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
55 keyboard_handle
= input_available
;
56 #endif /* WINDOWSNT */
58 /* interrupt_handle is signaled when quit (C-g) is detected, so that
59 blocking system calls can be interrupted. We make it a manual
60 reset event, so that if we should ever have multiple threads
61 performing system calls, they will all be interrupted (I'm guessing
62 that would the right response). Note that we use PulseEvent to
63 signal this event, so that it never remains signaled. */
64 interrupt_handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
70 DeleteCriticalSection (&critsect
);
74 CloseHandle (input_available
);
75 input_available
= NULL
;
79 CloseHandle (interrupt_handle
);
80 interrupt_handle
= NULL
;
87 /* Make sure this event never remains signaled; if the main thread
88 isn't in a blocking call, then this should do nothing. */
89 PulseEvent (interrupt_handle
);
93 select_palette (FRAME_PTR f
, HDC hdc
)
95 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
97 if (!display_info
->has_palette
)
100 if (display_info
->palette
== 0)
103 if (!NILP (Vw32_enable_palette
))
104 f
->output_data
.w32
->old_palette
=
105 SelectPalette (hdc
, display_info
->palette
, FALSE
);
107 f
->output_data
.w32
->old_palette
= NULL
;
109 if (RealizePalette (hdc
) != GDI_ERROR
)
111 Lisp_Object frame
, framelist
;
112 FOR_EACH_FRAME (framelist
, frame
)
114 SET_FRAME_GARBAGED (XFRAME (frame
));
120 deselect_palette (FRAME_PTR f
, HDC hdc
)
122 if (f
->output_data
.w32
->old_palette
)
123 SelectPalette (hdc
, f
->output_data
.w32
->old_palette
, FALSE
);
126 /* Get a DC for frame and select palette for drawing; force an update of
127 all frames if palette's mapping changes. */
129 get_frame_dc (FRAME_PTR f
)
133 if (f
->output_method
!= output_w32
)
138 hdc
= GetDC (f
->output_data
.w32
->window_desc
);
140 /* If this gets called during startup before the frame is valid,
141 there is a chance of corrupting random data or crashing. */
143 select_palette (f
, hdc
);
149 release_frame_dc (FRAME_PTR f
, HDC hdc
)
153 deselect_palette (f
, hdc
);
154 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
161 typedef struct int_msg
164 struct int_msg
*lpNext
;
167 int_msg
*lpHead
= NULL
;
168 int_msg
*lpTail
= NULL
;
172 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
178 /* The while loop takes care of multiple sets */
180 while (!nQueue
&& bWait
)
183 WaitForSingleObject (input_available
, INFINITE
);
189 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
192 int_msg
* lpCur
= lpHead
;
194 lpHead
= lpHead
->lpNext
;
200 /* Consolidate WM_PAINT messages to optimize redrawing. */
201 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
203 int_msg
* lpCur
= lpHead
;
204 int_msg
* lpPrev
= NULL
;
205 int_msg
* lpNext
= NULL
;
207 while (lpCur
&& nQueue
)
209 lpNext
= lpCur
->lpNext
;
210 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
212 /* Remove this message from the queue. */
214 lpPrev
->lpNext
= lpNext
;
221 /* Adjust clip rectangle to cover both. */
222 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
223 &(lpCur
->w32msg
.rect
)))
225 SetRectEmpty (&(lpmsg
->rect
));
246 ResetEvent (input_available
);
253 extern char * w32_strerror (int error_no
);
255 /* Tell the main thread that we have input available; if the main
256 thread is blocked in select(), we wake it up here. */
258 notify_msg_ready (void)
260 SetEvent (input_available
);
263 /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
264 among other files. */
265 (void) PostThreadMessage (dwMainThreadId
, WM_EMACS_INPUT_READY
, 0, 0);
270 post_msg (W32Msg
* lpmsg
)
272 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
277 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
278 lpNew
->lpNext
= NULL
;
284 lpTail
->lpNext
= lpNew
;
299 prepend_msg (W32Msg
*lpmsg
)
301 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
306 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
311 lpNew
->lpNext
= lpHead
;
319 /* Process all messages in the current thread's queue. */
321 drain_message_queue (void)
324 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
326 TranslateMessage (&msg
);
327 DispatchMessage (&msg
);
331 /* x_sync is a no-op on W32. */
333 x_sync (struct frame
*f
)