1 /* Functions taken directly from X sources for use with the Microsoft Windows API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2015 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/>. */
30 #include "blockinput.h"
34 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
35 #define myfree(lp) GlobalFreePtr (lp)
37 CRITICAL_SECTION critsect
;
40 extern HANDLE keyboard_handle
;
41 #endif /* WINDOWSNT */
43 HANDLE input_available
= NULL
;
44 HANDLE interrupt_handle
= NULL
;
49 InitializeCriticalSection (&critsect
);
51 /* For safety, input_available should only be reset by get_next_msg
52 when the input queue is empty, so make it a manual reset event. */
53 input_available
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
56 keyboard_handle
= input_available
;
57 #endif /* WINDOWSNT */
59 /* interrupt_handle is signaled when quit (C-g) is detected, so that
60 blocking system calls can be interrupted. We make it a manual
61 reset event, so that if we should ever have multiple threads
62 performing system calls, they will all be interrupted (I'm guessing
63 that would the right response). Note that we use PulseEvent to
64 signal this event, so that it never remains signaled. */
65 interrupt_handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
71 DeleteCriticalSection (&critsect
);
75 CloseHandle (input_available
);
76 input_available
= NULL
;
80 CloseHandle (interrupt_handle
);
81 interrupt_handle
= NULL
;
88 /* Make sure this event never remains signaled; if the main thread
89 isn't in a blocking call, then this should do nothing. */
90 PulseEvent (interrupt_handle
);
94 select_palette (struct frame
*f
, HDC hdc
)
96 struct w32_display_info
*display_info
= FRAME_DISPLAY_INFO (f
);
98 if (!display_info
->has_palette
)
101 if (display_info
->palette
== 0)
104 if (!NILP (Vw32_enable_palette
))
105 f
->output_data
.w32
->old_palette
=
106 SelectPalette (hdc
, display_info
->palette
, FALSE
);
108 f
->output_data
.w32
->old_palette
= NULL
;
110 if (RealizePalette (hdc
) != GDI_ERROR
)
112 Lisp_Object frame
, framelist
;
113 FOR_EACH_FRAME (framelist
, frame
)
115 SET_FRAME_GARBAGED (XFRAME (frame
));
121 deselect_palette (struct frame
*f
, HDC hdc
)
123 if (f
->output_data
.w32
->old_palette
)
124 SelectPalette (hdc
, f
->output_data
.w32
->old_palette
, FALSE
);
127 /* Get a DC for frame and select palette for drawing; force an update of
128 all frames if palette's mapping changes. */
130 get_frame_dc (struct frame
*f
)
134 if (f
->output_method
!= output_w32
)
139 hdc
= GetDC (f
->output_data
.w32
->window_desc
);
141 /* If this gets called during startup before the frame is valid,
142 there is a chance of corrupting random data or crashing. */
144 select_palette (f
, hdc
);
150 release_frame_dc (struct frame
*f
, HDC hdc
)
154 deselect_palette (f
, hdc
);
155 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
162 typedef struct int_msg
165 struct int_msg
*lpNext
;
168 int_msg
*lpHead
= NULL
;
169 int_msg
*lpTail
= NULL
;
173 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
179 /* The while loop takes care of multiple sets */
181 while (!nQueue
&& bWait
)
184 WaitForSingleObject (input_available
, INFINITE
);
190 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
193 int_msg
* lpCur
= lpHead
;
195 lpHead
= lpHead
->lpNext
;
201 /* Consolidate WM_PAINT messages to optimize redrawing. */
202 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
204 int_msg
* lpCur
= lpHead
;
205 int_msg
* lpPrev
= NULL
;
206 int_msg
* lpNext
= NULL
;
208 while (lpCur
&& nQueue
)
210 lpNext
= lpCur
->lpNext
;
211 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
213 /* Remove this message from the queue. */
215 lpPrev
->lpNext
= lpNext
;
222 /* Adjust clip rectangle to cover both. */
223 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
224 &(lpCur
->w32msg
.rect
)))
226 SetRectEmpty (&(lpmsg
->rect
));
247 ResetEvent (input_available
);
254 extern char * w32_strerror (int error_no
);
256 /* Tell the main thread that we have input available; if the main
257 thread is blocked in select(), we wake it up here. */
259 notify_msg_ready (void)
261 SetEvent (input_available
);
264 /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
265 among other files. */
266 (void) PostThreadMessage (dwMainThreadId
, WM_EMACS_INPUT_READY
, 0, 0);
271 post_msg (W32Msg
* lpmsg
)
273 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
278 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
279 lpNew
->lpNext
= NULL
;
285 lpTail
->lpNext
= lpNew
;
300 prepend_msg (W32Msg
*lpmsg
)
302 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
307 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
312 lpNew
->lpNext
= lpHead
;
320 /* Process all messages in the current thread's queue. Value is 1 if
321 one of these messages was WM_EMACS_FILENOTIFY, zero otherwise. */
323 drain_message_queue (void)
328 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
330 if (msg
.message
== WM_EMACS_FILENOTIFY
)
332 TranslateMessage (&msg
);
333 DispatchMessage (&msg
);