1 /* Functions taken directly from X sources for use with the Microsoft Windows API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2017 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 (at
10 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 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
31 #define myfree(lp) GlobalFreePtr (lp)
33 CRITICAL_SECTION critsect
;
36 extern HANDLE keyboard_handle
;
37 #endif /* WINDOWSNT */
39 HANDLE input_available
= NULL
;
40 HANDLE interrupt_handle
= NULL
;
45 InitializeCriticalSection (&critsect
);
47 /* For safety, input_available should only be reset by get_next_msg
48 when the input queue is empty, so make it a manual reset event. */
49 input_available
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
52 keyboard_handle
= input_available
;
53 #endif /* WINDOWSNT */
55 /* interrupt_handle is signaled when quit (C-g) is detected, so that
56 blocking system calls can be interrupted. We make it a manual
57 reset event, so that if we should ever have multiple threads
58 performing system calls, they will all be interrupted (I'm guessing
59 that would the right response). Note that we use PulseEvent to
60 signal this event, so that it never remains signaled. */
61 interrupt_handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
67 DeleteCriticalSection (&critsect
);
71 CloseHandle (input_available
);
72 input_available
= NULL
;
76 CloseHandle (interrupt_handle
);
77 interrupt_handle
= NULL
;
84 /* Make sure this event never remains signaled; if the main thread
85 isn't in a blocking call, then this should do nothing. */
86 PulseEvent (interrupt_handle
);
90 select_palette (struct frame
*f
, HDC hdc
)
92 struct w32_display_info
*display_info
= FRAME_DISPLAY_INFO (f
);
94 if (!display_info
->has_palette
)
97 if (display_info
->palette
== 0)
100 if (!NILP (Vw32_enable_palette
))
101 f
->output_data
.w32
->old_palette
=
102 SelectPalette (hdc
, display_info
->palette
, FALSE
);
104 f
->output_data
.w32
->old_palette
= NULL
;
106 if (RealizePalette (hdc
) != GDI_ERROR
)
108 Lisp_Object frame
, framelist
;
109 FOR_EACH_FRAME (framelist
, frame
)
111 SET_FRAME_GARBAGED (XFRAME (frame
));
117 deselect_palette (struct frame
*f
, HDC hdc
)
119 if (f
->output_data
.w32
->old_palette
)
120 SelectPalette (hdc
, f
->output_data
.w32
->old_palette
, FALSE
);
123 /* Get a DC for frame and select palette for drawing; force an update of
124 all frames if palette's mapping changes. */
126 get_frame_dc (struct frame
*f
)
130 if (f
->output_method
!= output_w32
)
135 hdc
= GetDC (f
->output_data
.w32
->window_desc
);
137 /* If this gets called during startup before the frame is valid,
138 there is a chance of corrupting random data or crashing. */
140 select_palette (f
, hdc
);
146 release_frame_dc (struct frame
*f
, HDC hdc
)
150 deselect_palette (f
, hdc
);
151 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
158 typedef struct int_msg
161 struct int_msg
*lpNext
;
164 int_msg
*lpHead
= NULL
;
165 int_msg
*lpTail
= NULL
;
169 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
175 /* The while loop takes care of multiple sets */
177 while (!nQueue
&& bWait
)
180 WaitForSingleObject (input_available
, INFINITE
);
186 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
189 int_msg
* lpCur
= lpHead
;
191 lpHead
= lpHead
->lpNext
;
197 /* Consolidate WM_PAINT messages to optimize redrawing. */
198 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
200 int_msg
* lpCur
= lpHead
;
201 int_msg
* lpPrev
= NULL
;
202 int_msg
* lpNext
= NULL
;
204 while (lpCur
&& nQueue
)
206 lpNext
= lpCur
->lpNext
;
207 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
209 /* Remove this message from the queue. */
211 lpPrev
->lpNext
= lpNext
;
218 /* Adjust clip rectangle to cover both. */
219 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
220 &(lpCur
->w32msg
.rect
)))
222 SetRectEmpty (&(lpmsg
->rect
));
243 ResetEvent (input_available
);
250 extern char * w32_strerror (int error_no
);
252 /* Tell the main thread that we have input available; if the main
253 thread is blocked in select(), we wake it up here. */
255 notify_msg_ready (void)
257 SetEvent (input_available
);
260 /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
261 among other files. */
262 (void) PostThreadMessage (dwMainThreadId
, WM_EMACS_INPUT_READY
, 0, 0);
267 post_msg (W32Msg
* lpmsg
)
269 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
274 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
275 lpNew
->lpNext
= NULL
;
281 lpTail
->lpNext
= lpNew
;
296 prepend_msg (W32Msg
*lpmsg
)
298 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
303 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
308 lpNew
->lpNext
= lpHead
;
316 /* Process all messages in the current thread's queue. Value is 1 if
317 one of these messages was WM_EMACS_FILENOTIFY, zero otherwise. */
319 drain_message_queue (void)
324 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
326 if (msg
.message
== WM_EMACS_FILENOTIFY
)
328 TranslateMessage (&msg
);
329 DispatchMessage (&msg
);