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/>. */
27 #include "blockinput.h"
31 #define myalloc(cb) GlobalAllocPtr (GPTR, cb)
32 #define myfree(lp) GlobalFreePtr (lp)
34 CRITICAL_SECTION critsect
;
35 extern HANDLE keyboard_handle
;
36 HANDLE input_available
= NULL
;
37 HANDLE interrupt_handle
= NULL
;
42 InitializeCriticalSection (&critsect
);
44 /* For safety, input_available should only be reset by get_next_msg
45 when the input queue is empty, so make it a manual reset event. */
46 keyboard_handle
= input_available
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
48 /* interrupt_handle is signaled when quit (C-g) is detected, so that
49 blocking system calls can be interrupted. We make it a manual
50 reset event, so that if we should ever have multiple threads
51 performing system calls, they will all be interrupted (I'm guessing
52 that would the right response). Note that we use PulseEvent to
53 signal this event, so that it never remains signaled. */
54 interrupt_handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
60 DeleteCriticalSection (&critsect
);
64 CloseHandle (input_available
);
65 input_available
= NULL
;
69 CloseHandle (interrupt_handle
);
70 interrupt_handle
= NULL
;
77 /* Make sure this event never remains signaled; if the main thread
78 isn't in a blocking call, then this should do nothing. */
79 PulseEvent (interrupt_handle
);
83 select_palette (FRAME_PTR f
, HDC hdc
)
85 struct w32_display_info
*display_info
= FRAME_W32_DISPLAY_INFO (f
);
87 if (!display_info
->has_palette
)
90 if (display_info
->palette
== 0)
93 if (!NILP (Vw32_enable_palette
))
94 f
->output_data
.w32
->old_palette
=
95 SelectPalette (hdc
, display_info
->palette
, FALSE
);
97 f
->output_data
.w32
->old_palette
= NULL
;
99 if (RealizePalette (hdc
) != GDI_ERROR
)
101 Lisp_Object frame
, framelist
;
102 FOR_EACH_FRAME (framelist
, frame
)
104 SET_FRAME_GARBAGED (XFRAME (frame
));
110 deselect_palette (FRAME_PTR f
, HDC hdc
)
112 if (f
->output_data
.w32
->old_palette
)
113 SelectPalette (hdc
, f
->output_data
.w32
->old_palette
, FALSE
);
116 /* Get a DC for frame and select palette for drawing; force an update of
117 all frames if palette's mapping changes. */
119 get_frame_dc (FRAME_PTR f
)
123 if (f
->output_method
!= output_w32
)
128 hdc
= GetDC (f
->output_data
.w32
->window_desc
);
130 /* If this gets called during startup before the frame is valid,
131 there is a chance of corrupting random data or crashing. */
133 select_palette (f
, hdc
);
139 release_frame_dc (FRAME_PTR f
, HDC hdc
)
143 deselect_palette (f
, hdc
);
144 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
151 typedef struct int_msg
154 struct int_msg
*lpNext
;
157 int_msg
*lpHead
= NULL
;
158 int_msg
*lpTail
= NULL
;
162 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
168 /* The while loop takes care of multiple sets */
170 while (!nQueue
&& bWait
)
173 WaitForSingleObject (input_available
, INFINITE
);
179 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
182 int_msg
* lpCur
= lpHead
;
184 lpHead
= lpHead
->lpNext
;
190 /* Consolidate WM_PAINT messages to optimize redrawing. */
191 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
193 int_msg
* lpCur
= lpHead
;
194 int_msg
* lpPrev
= NULL
;
195 int_msg
* lpNext
= NULL
;
197 while (lpCur
&& nQueue
)
199 lpNext
= lpCur
->lpNext
;
200 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
202 /* Remove this message from the queue. */
204 lpPrev
->lpNext
= lpNext
;
211 /* Adjust clip rectangle to cover both. */
212 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
213 &(lpCur
->w32msg
.rect
)))
215 SetRectEmpty (&(lpmsg
->rect
));
236 ResetEvent (input_available
);
244 post_msg (W32Msg
* lpmsg
)
246 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
251 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
252 lpNew
->lpNext
= NULL
;
258 lpTail
->lpNext
= lpNew
;
266 SetEvent (input_available
);
274 prepend_msg (W32Msg
*lpmsg
)
276 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
281 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
286 lpNew
->lpNext
= lpHead
;
294 /* Process all messages in the current thread's queue. */
296 drain_message_queue (void)
299 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
301 TranslateMessage (&msg
);
302 DispatchMessage (&msg
);
306 /* x_sync is a no-op on W32. */
308 x_sync (struct frame
*f
)