1 /* Functions taken directly from X sources for use with the Microsoft Windows API.
2 Copyright (C) 1989, 1992-1995, 1999, 2001-2016 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
);
51 /* Initialize the linked list of notifications sets that will be
52 used to communicate between the watching worker threads and the
54 notifications_set_head
= malloc (sizeof(struct notifications_set
));
55 if (notifications_set_head
)
57 memset (notifications_set_head
, 0, sizeof(struct notifications_set
));
58 notifications_set_head
->next
59 = notifications_set_head
->prev
= notifications_set_head
;
62 DebPrint(("Out of memory: can't initialize notifications sets."));
65 keyboard_handle
= input_available
;
66 #endif /* WINDOWSNT */
68 /* interrupt_handle is signaled when quit (C-g) is detected, so that
69 blocking system calls can be interrupted. We make it a manual
70 reset event, so that if we should ever have multiple threads
71 performing system calls, they will all be interrupted (I'm guessing
72 that would the right response). Note that we use PulseEvent to
73 signal this event, so that it never remains signaled. */
74 interrupt_handle
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
80 DeleteCriticalSection (&critsect
);
84 CloseHandle (input_available
);
85 input_available
= NULL
;
89 CloseHandle (interrupt_handle
);
90 interrupt_handle
= NULL
;
93 if (notifications_set_head
)
95 /* Free any remaining notifications set that could be left over. */
96 while (notifications_set_head
->next
!= notifications_set_head
)
98 struct notifications_set
*ns
= notifications_set_head
->next
;
99 notifications_set_head
->next
= ns
->next
;
100 ns
->next
->prev
= notifications_set_head
;
101 if (ns
->notifications
)
102 free (ns
->notifications
);
106 free (notifications_set_head
);
112 /* Make sure this event never remains signaled; if the main thread
113 isn't in a blocking call, then this should do nothing. */
114 PulseEvent (interrupt_handle
);
118 select_palette (struct frame
*f
, HDC hdc
)
120 struct w32_display_info
*display_info
= FRAME_DISPLAY_INFO (f
);
122 if (!display_info
->has_palette
)
125 if (display_info
->palette
== 0)
128 if (!NILP (Vw32_enable_palette
))
129 f
->output_data
.w32
->old_palette
=
130 SelectPalette (hdc
, display_info
->palette
, FALSE
);
132 f
->output_data
.w32
->old_palette
= NULL
;
134 if (RealizePalette (hdc
) != GDI_ERROR
)
136 Lisp_Object frame
, framelist
;
137 FOR_EACH_FRAME (framelist
, frame
)
139 SET_FRAME_GARBAGED (XFRAME (frame
));
145 deselect_palette (struct frame
*f
, HDC hdc
)
147 if (f
->output_data
.w32
->old_palette
)
148 SelectPalette (hdc
, f
->output_data
.w32
->old_palette
, FALSE
);
151 /* Get a DC for frame and select palette for drawing; force an update of
152 all frames if palette's mapping changes. */
154 get_frame_dc (struct frame
*f
)
158 if (f
->output_method
!= output_w32
)
163 hdc
= GetDC (f
->output_data
.w32
->window_desc
);
165 /* If this gets called during startup before the frame is valid,
166 there is a chance of corrupting random data or crashing. */
168 select_palette (f
, hdc
);
174 release_frame_dc (struct frame
*f
, HDC hdc
)
178 deselect_palette (f
, hdc
);
179 ret
= ReleaseDC (f
->output_data
.w32
->window_desc
, hdc
);
186 typedef struct int_msg
189 struct int_msg
*lpNext
;
192 int_msg
*lpHead
= NULL
;
193 int_msg
*lpTail
= NULL
;
197 get_next_msg (W32Msg
* lpmsg
, BOOL bWait
)
203 /* The while loop takes care of multiple sets */
205 while (!nQueue
&& bWait
)
208 WaitForSingleObject (input_available
, INFINITE
);
214 memcpy (lpmsg
, &lpHead
->w32msg
, sizeof (W32Msg
));
217 int_msg
* lpCur
= lpHead
;
219 lpHead
= lpHead
->lpNext
;
225 /* Consolidate WM_PAINT messages to optimize redrawing. */
226 if (lpmsg
->msg
.message
== WM_PAINT
&& nQueue
)
228 int_msg
* lpCur
= lpHead
;
229 int_msg
* lpPrev
= NULL
;
230 int_msg
* lpNext
= NULL
;
232 while (lpCur
&& nQueue
)
234 lpNext
= lpCur
->lpNext
;
235 if (lpCur
->w32msg
.msg
.message
== WM_PAINT
)
237 /* Remove this message from the queue. */
239 lpPrev
->lpNext
= lpNext
;
246 /* Adjust clip rectangle to cover both. */
247 if (!UnionRect (&(lpmsg
->rect
), &(lpmsg
->rect
),
248 &(lpCur
->w32msg
.rect
)))
250 SetRectEmpty (&(lpmsg
->rect
));
271 ResetEvent (input_available
);
278 extern char * w32_strerror (int error_no
);
280 /* Tell the main thread that we have input available; if the main
281 thread is blocked in select(), we wake it up here. */
283 notify_msg_ready (void)
285 SetEvent (input_available
);
288 /* Wakes up the main thread, which is blocked select()ing for /dev/windows,
289 among other files. */
290 (void) PostThreadMessage (dwMainThreadId
, WM_EMACS_INPUT_READY
, 0, 0);
295 post_msg (W32Msg
* lpmsg
)
297 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
302 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
303 lpNew
->lpNext
= NULL
;
309 lpTail
->lpNext
= lpNew
;
324 prepend_msg (W32Msg
*lpmsg
)
326 int_msg
* lpNew
= (int_msg
*) myalloc (sizeof (int_msg
));
331 memcpy (&lpNew
->w32msg
, lpmsg
, sizeof (W32Msg
));
336 lpNew
->lpNext
= lpHead
;
344 /* Process all messages in the current thread's queue. Value is 1 if
345 one of these messages was WM_EMACS_FILENOTIFY, zero otherwise. */
347 drain_message_queue (void)
352 while (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
))
354 if (msg
.message
== WM_EMACS_FILENOTIFY
)
356 TranslateMessage (&msg
);
357 DispatchMessage (&msg
);