1 /* Functions taken directly from X sources for use with the Microsoft Windows API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2012 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28 #include "blockinput.h"
32 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
33 #define myfree(lp) GlobalFreePtr (lp)
35 CRITICAL_SECTION critsect
;
38 extern HANDLE keyboard_handle
;
39 #endif /* WINDOWSNT */
41 HANDLE input_available
= NULL
;
42 HANDLE interrupt_handle
= NULL
;
47 InitializeCriticalSection (&critsect
);
49 /* For safety, input_available should only be reset by get_next_msg
50 when the input queue is empty, so make it a manual reset event. */
51 input_available
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
54 keyboard_handle
= input_available
;
55 #endif /* WINDOWSNT */
57 /* interrupt_handle is signaled when quit (C-g) is detected, so that
58 blocking system calls can be interrupted. We make it a manual
59 reset event, so that if we should ever have multiple threads
60 performing system calls, they will all be interrupted (I'm guessing
61 that would the right response). Note that we use PulseEvent to
62 signal this event, so that it never remains signaled. */
63 interrupt_handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
69 DeleteCriticalSection (&critsect
);
73 CloseHandle (input_available
);
74 input_available
= NULL
;
78 CloseHandle (interrupt_handle
);
79 interrupt_handle
= NULL
;
86 /* Make sure this event never remains signaled; if the main thread
87 isn't in a blocking call, then this should do nothing. */
88 PulseEvent (interrupt_handle
);
92 select_palette (FRAME_PTR f
, HDC hdc
)
94 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
96 if (!display_info
->has_palette
)
99 if (display_info
->palette
== 0)
102 if (!NILP (Vw32_enable_palette
))
103 f
->output_data
.w32
->old_palette
=
104 SelectPalette (hdc
, display_info
->palette
, FALSE
);
106 f
->output_data
.w32
->old_palette
= NULL
;
108 if (RealizePalette (hdc
) != GDI_ERROR
)
110 Lisp_Object frame
, framelist
;
111 FOR_EACH_FRAME (framelist
, frame
)
113 SET_FRAME_GARBAGED (XFRAME (frame
));
119 deselect_palette (FRAME_PTR f
, HDC hdc
)
121 if (f
->output_data
.w32
->old_palette
)
122 SelectPalette (hdc
, f
->output_data
.w32
->old_palette
, FALSE
);
125 /* Get a DC for frame and select palette for drawing; force an update of
126 all frames if palette's mapping changes. */
128 get_frame_dc (FRAME_PTR f
)
132 if (f
->output_method
!= output_w32
)
137 hdc
= GetDC (f
->output_data
.w32
->window_desc
);
139 /* If this gets called during startup before the frame is valid,
140 there is a chance of corrupting random data or crashing. */
142 select_palette (f
, hdc
);
148 release_frame_dc (FRAME_PTR f
, HDC hdc
)
152 deselect_palette (f
, hdc
);
153 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
160 typedef struct int_msg
163 struct int_msg
*lpNext
;
166 int_msg
*lpHead
= NULL
;
167 int_msg
*lpTail
= NULL
;
171 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
177 /* The while loop takes care of multiple sets */
179 while (!nQueue
&& bWait
)
182 WaitForSingleObject (input_available
, INFINITE
);
188 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
191 int_msg
* lpCur
= lpHead
;
193 lpHead
= lpHead
->lpNext
;
199 /* Consolidate WM_PAINT messages to optimize redrawing. */
200 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
202 int_msg
* lpCur
= lpHead
;
203 int_msg
* lpPrev
= NULL
;
204 int_msg
* lpNext
= NULL
;
206 while (lpCur
&& nQueue
)
208 lpNext
= lpCur
->lpNext
;
209 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
211 /* Remove this message from the queue. */
213 lpPrev
->lpNext
= lpNext
;
220 /* Adjust clip rectangle to cover both. */
221 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
222 &(lpCur
->w32msg
.rect
)))
224 SetRectEmpty (&(lpmsg
->rect
));
245 ResetEvent (input_available
);
252 extern char * w32_strerror (int error_no
);
254 /* Tell the main thread that we have input available; if the main
255 thread is blocked in select(), we wake it up here. */
257 notify_msg_ready (void)
259 SetEvent (input_available
);
262 /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
263 among other files. */
264 (void) PostThreadMessage (dwMainThreadId
, WM_EMACS_INPUT_READY
, 0, 0);
269 post_msg (W32Msg
* lpmsg
)
271 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
276 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
277 lpNew
->lpNext
= NULL
;
283 lpTail
->lpNext
= lpNew
;
298 prepend_msg (W32Msg
*lpmsg
)
300 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
305 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
310 lpNew
->lpNext
= lpHead
;
318 /* Process all messages in the current thread's queue. */
320 drain_message_queue (void)
323 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
325 TranslateMessage (&msg
);
326 DispatchMessage (&msg
);
330 /* x_sync is a no-op on W32. */
332 x_sync (struct frame
*f
)