Merge WM_MOUSEMOVE messages.
[wine/multimedia.git] / server / queue.c
blob2c53a927a39e5536ff62d1849ff0d9acad19fe7d
1 /*
2 * Server-side message queues
4 * Copyright (C) 2000 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
11 #include "winbase.h"
12 #include "wingdi.h"
13 #include "winuser.h"
15 #include "handle.h"
16 #include "thread.h"
17 #include "process.h"
18 #include "request.h"
20 struct message_result
22 struct message_result *send_next; /* next in sender list */
23 struct message_result *recv_next; /* next in receiver list */
24 struct msg_queue *sender; /* sender queue */
25 struct msg_queue *receiver; /* receiver queue */
26 int replied; /* has it been replied to? */
27 unsigned int result; /* reply result */
28 unsigned int error; /* error code to pass back to sender */
31 struct message
33 struct message *next; /* next message in list */
34 struct message *prev; /* prev message in list */
35 int type; /* message type (FIXME) */
36 handle_t win; /* window handle */
37 unsigned int msg; /* message code */
38 unsigned int wparam; /* parameters */
39 unsigned int lparam; /* parameters */
40 unsigned short x; /* x position */
41 unsigned short y; /* y position */
42 unsigned int time; /* message time */
43 unsigned int info; /* extra info */
44 struct message_result *result; /* result in sender queue */
47 struct message_list
49 struct message *first; /* head of list */
50 struct message *last; /* tail of list */
53 struct timer
55 struct timer *next; /* next timer in list */
56 struct timer *prev; /* prev timer in list */
57 struct timeval when; /* next expiration */
58 unsigned int rate; /* timer rate in ms */
59 handle_t win; /* window handle */
60 unsigned int msg; /* message to post */
61 unsigned int id; /* timer id */
62 unsigned int lparam; /* lparam for message */
65 struct msg_queue
67 struct object obj; /* object header */
68 unsigned int wake_bits; /* wakeup bits */
69 unsigned int wake_mask; /* wakeup mask */
70 unsigned int changed_bits; /* changed wakeup bits */
71 unsigned int changed_mask; /* changed wakeup mask */
72 int paint_count; /* pending paint messages count */
73 struct message_list msg_list[NB_MSG_KINDS]; /* lists of messages */
74 struct message_result *send_result; /* stack of sent messages waiting for result */
75 struct message_result *recv_result; /* stack of received messages waiting for result */
76 struct message *last_msg; /* last msg returned to the app and not removed */
77 enum message_kind last_msg_kind; /* message kind of last_msg */
78 struct timer *first_timer; /* head of timer list */
79 struct timer *last_timer; /* tail of timer list */
80 struct timer *next_timer; /* next timer to expire */
81 struct timeout_user *timeout; /* timeout for next timer to expire */
84 static void msg_queue_dump( struct object *obj, int verbose );
85 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
86 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
87 static int msg_queue_signaled( struct object *obj, struct thread *thread );
88 static int msg_queue_satisfied( struct object *obj, struct thread *thread );
89 static void msg_queue_destroy( struct object *obj );
90 static void timer_callback( void *private );
92 static const struct object_ops msg_queue_ops =
94 sizeof(struct msg_queue), /* size */
95 msg_queue_dump, /* dump */
96 msg_queue_add_queue, /* add_queue */
97 msg_queue_remove_queue, /* remove_queue */
98 msg_queue_signaled, /* signaled */
99 msg_queue_satisfied, /* satisfied */
100 NULL, /* get_poll_events */
101 NULL, /* poll_event */
102 no_get_fd, /* get_fd */
103 no_flush, /* flush */
104 no_get_file_info, /* get_file_info */
105 msg_queue_destroy /* destroy */
109 static struct msg_queue *create_msg_queue( struct thread *thread )
111 struct msg_queue *queue;
112 int i;
114 if ((queue = alloc_object( &msg_queue_ops, -1 )))
116 queue->wake_bits = 0;
117 queue->wake_mask = 0;
118 queue->changed_bits = 0;
119 queue->changed_mask = 0;
120 queue->paint_count = 0;
121 queue->send_result = NULL;
122 queue->recv_result = NULL;
123 queue->last_msg = NULL;
124 queue->first_timer = NULL;
125 queue->last_timer = NULL;
126 queue->next_timer = NULL;
127 queue->timeout = NULL;
128 for (i = 0; i < NB_MSG_KINDS; i++)
129 queue->msg_list[i].first = queue->msg_list[i].last = NULL;
131 thread->queue = queue;
132 if (!thread->process->queue)
133 thread->process->queue = (struct msg_queue *)grab_object( queue );
135 return queue;
138 /* check the queue status */
139 inline static int is_signaled( struct msg_queue *queue )
141 return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
144 /* set/clear some queue bits */
145 inline static void change_queue_bits( struct msg_queue *queue, unsigned int set, unsigned int clear )
147 queue->wake_bits = (queue->wake_bits | set) & ~clear;
148 queue->changed_bits = (queue->changed_bits | set) & ~clear;
149 if (is_signaled( queue )) wake_up( &queue->obj, 0 );
152 /* get the QS_* bit corresponding to a given hardware message */
153 inline static int get_hardware_msg_bit( struct message *msg )
155 if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
156 if (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST) return QS_KEY;
157 return QS_MOUSEBUTTON;
160 /* get the current thread queue, creating it if needed */
161 inline struct msg_queue *get_current_queue(void)
163 struct msg_queue *queue = current->queue;
164 if (!queue) queue = create_msg_queue( current );
165 return queue;
168 /* append a message to the end of a list */
169 inline static void append_message( struct message_list *list, struct message *msg )
171 msg->next = NULL;
172 if ((msg->prev = list->last)) msg->prev->next = msg;
173 else list->first = msg;
174 list->last = msg;
177 /* unlink a message from a list it */
178 inline static void unlink_message( struct message_list *list, struct message *msg )
180 if (msg->next) msg->next->prev = msg->prev;
181 else list->last = msg->prev;
182 if (msg->prev) msg->prev->next = msg->next;
183 else list->first = msg->next;
186 /* try to merge a message with the last in the list; return 1 if successful */
187 static int merge_message( struct message_list *list, const struct message *msg )
189 struct message *prev = list->last;
191 if (!prev) return 0;
192 if (prev->result) return 0;
193 if (prev->win != msg->win) return 0;
194 if (prev->msg != msg->msg) return 0;
195 if (prev->type != msg->type) return 0;
196 /* now we can merge it */
197 prev->wparam = msg->wparam;
198 prev->lparam = msg->lparam;
199 prev->x = msg->x;
200 prev->y = msg->y;
201 prev->time = msg->time;
202 prev->info = msg->info;
203 return 1;
206 /* free a message when deleting a queue or window */
207 static void free_message( struct message *msg )
209 struct message_result *result = msg->result;
210 if (result)
212 if (result->sender)
214 result->result = 0;
215 result->error = STATUS_ACCESS_DENIED; /* FIXME */
216 result->replied = 1;
217 result->receiver = NULL;
218 /* wake sender queue if waiting on this result */
219 if (result->sender->send_result == result)
220 change_queue_bits( result->sender, QS_SMRESULT, 0 );
222 else free( result );
224 free( msg );
227 /* remove (and free) a message from a message list */
228 static void remove_queue_message( struct msg_queue *queue, struct message *msg,
229 enum message_kind kind )
231 int clr_bit;
232 struct message *other;
234 if (queue->last_msg == msg) queue->last_msg = NULL;
235 unlink_message( &queue->msg_list[kind], msg );
236 switch(kind)
238 case SEND_MESSAGE:
239 if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
240 break;
241 case POST_MESSAGE:
242 if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_POSTMESSAGE );
243 break;
244 case COOKED_HW_MESSAGE:
245 case RAW_HW_MESSAGE:
246 clr_bit = get_hardware_msg_bit( msg );
247 for (other = queue->msg_list[kind].first; other; other = other->next)
248 if (get_hardware_msg_bit( other ) == clr_bit) break;
249 if (!other) change_queue_bits( queue, 0, clr_bit );
250 break;
252 free_message( msg );
255 /* send a message from the sender queue to the receiver queue */
256 static int send_message( struct msg_queue *send_queue, struct msg_queue *recv_queue,
257 struct message *msg )
259 struct message_result *result = mem_alloc( sizeof(*result) );
260 if (!result) return 0;
262 /* put the result on the sender result stack */
263 result->sender = send_queue;
264 result->receiver = recv_queue;
265 result->replied = 0;
266 result->send_next = send_queue->send_result;
267 send_queue->send_result = result;
269 /* and put the message on the receiver queue */
270 msg->result = result;
271 append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
272 change_queue_bits( recv_queue, QS_SENDMESSAGE, 0 );
273 return 1;
276 /* receive a message, removing it from the sent queue */
277 static void receive_message( struct msg_queue *queue, struct message *msg )
279 struct message_result *result = msg->result;
281 unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
282 /* put the result on the receiver result stack */
283 result->recv_next = queue->recv_result;
284 queue->recv_result = result;
285 free( msg );
286 if (!queue->msg_list[SEND_MESSAGE].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
289 /* set the result of the current received message */
290 static void reply_message( struct msg_queue *queue, unsigned int result,
291 unsigned int error, int remove )
293 struct message_result *res = queue->recv_result;
295 if (remove)
297 queue->recv_result = res->recv_next;
298 res->receiver = NULL;
299 if (!res->sender) /* no one waiting for it */
301 free( res );
302 return;
305 if (!res->replied)
307 res->result = result;
308 res->error = error;
309 res->replied = 1;
310 /* wake sender queue if waiting on this result */
311 if (res->sender && res->sender->send_result == res)
312 change_queue_bits( res->sender, QS_SMRESULT, 0 );
316 /* retrieve the reply of the current message being sent */
317 static unsigned int get_message_reply( struct msg_queue *queue, int cancel )
319 struct message_result *res = queue->send_result;
320 unsigned int ret = 0;
322 set_error( STATUS_PENDING );
324 if (res && (res->replied || cancel))
326 if (res->replied)
328 ret = res->result;
329 set_error( res->error );
331 queue->send_result = res->send_next;
332 res->sender = NULL;
333 if (!res->receiver) free( res );
334 if (!queue->send_result || !queue->send_result->replied)
335 change_queue_bits( queue, 0, QS_SMRESULT );
337 return ret;
340 /* empty a message list and free all the messages */
341 static void empty_msg_list( struct message_list *list )
343 struct message *msg = list->first;
344 while (msg)
346 struct message *next = msg->next;
347 free_message( msg );
348 msg = next;
352 /* cleanup all pending results when deleting a queue */
353 static void cleanup_results( struct msg_queue *queue )
355 struct message_result *result, *next;
357 result = queue->send_result;
358 while (result)
360 next = result->send_next;
361 result->sender = NULL;
362 if (!result->receiver) free( result );
363 result = next;
366 while (queue->recv_result) reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1 );
369 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
371 struct msg_queue *queue = (struct msg_queue *)obj;
372 struct process *process = entry->thread->process;
374 /* a thread can only wait on its own queue */
375 if (entry->thread->queue != queue)
377 set_error( STATUS_ACCESS_DENIED );
378 return 0;
380 /* if waiting on the main process queue, set the idle event */
381 if (process->queue == queue)
383 if (process->idle_event) set_event( process->idle_event );
385 add_queue( obj, entry );
386 return 1;
389 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
391 struct msg_queue *queue = (struct msg_queue *)obj;
392 struct process *process = entry->thread->process;
394 remove_queue( obj, entry );
396 assert( entry->thread->queue == queue );
398 /* if waiting on the main process queue, reset the idle event */
399 if (process->queue == queue)
401 if (process->idle_event) reset_event( process->idle_event );
405 static void msg_queue_dump( struct object *obj, int verbose )
407 struct msg_queue *queue = (struct msg_queue *)obj;
408 fprintf( stderr, "Msg queue bits=%x mask=%x\n",
409 queue->wake_bits, queue->wake_mask );
412 static int msg_queue_signaled( struct object *obj, struct thread *thread )
414 struct msg_queue *queue = (struct msg_queue *)obj;
415 return is_signaled( queue );
418 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
420 struct msg_queue *queue = (struct msg_queue *)obj;
421 queue->wake_mask = 0;
422 queue->changed_mask = 0;
423 return 0; /* Not abandoned */
426 static void msg_queue_destroy( struct object *obj )
428 struct msg_queue *queue = (struct msg_queue *)obj;
429 struct timer *timer = queue->first_timer;
430 int i;
432 cleanup_results( queue );
433 for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
435 while (timer)
437 struct timer *next = timer->next;
438 free( timer );
439 timer = next;
441 if (queue->timeout) remove_timeout_user( queue->timeout );
444 /* set the next timer to expire */
445 static void set_next_timer( struct msg_queue *queue, struct timer *timer )
447 if (queue->timeout)
449 remove_timeout_user( queue->timeout );
450 queue->timeout = NULL;
452 if ((queue->next_timer = timer))
453 queue->timeout = add_timeout_user( &timer->when, timer_callback, queue );
455 /* set/clear QS_TIMER bit */
456 if (queue->next_timer == queue->first_timer)
457 change_queue_bits( queue, 0, QS_TIMER );
458 else
459 change_queue_bits( queue, QS_TIMER, 0 );
462 /* callback for the next timer expiration */
463 static void timer_callback( void *private )
465 struct msg_queue *queue = private;
467 queue->timeout = NULL;
468 /* move on to the next timer */
469 set_next_timer( queue, queue->next_timer->next );
472 /* link a timer at its rightful place in the queue list */
473 static void link_timer( struct msg_queue *queue, struct timer *timer )
475 struct timer *pos = queue->next_timer;
477 while (pos && time_before( &pos->when, &timer->when )) pos = pos->next;
479 if (pos) /* insert before pos */
481 if ((timer->prev = pos->prev)) timer->prev->next = timer;
482 else queue->first_timer = timer;
483 timer->next = pos;
484 pos->prev = timer;
486 else /* insert at end */
488 timer->next = NULL;
489 timer->prev = queue->last_timer;
490 if (queue->last_timer) queue->last_timer->next = timer;
491 else queue->first_timer = timer;
492 queue->last_timer = timer;
494 /* check if we replaced the next timer */
495 if (pos == queue->next_timer) set_next_timer( queue, timer );
498 /* remove a timer from the queue timer list */
499 static void unlink_timer( struct msg_queue *queue, struct timer *timer )
501 if (timer->next) timer->next->prev = timer->prev;
502 else queue->last_timer = timer->prev;
503 if (timer->prev) timer->prev->next = timer->next;
504 else queue->first_timer = timer->next;
505 /* check if we removed the next timer */
506 if (queue->next_timer == timer) set_next_timer( queue, timer->next );
507 else if (queue->next_timer == queue->first_timer) change_queue_bits( queue, 0, QS_TIMER );
510 /* restart an expired timer */
511 static void restart_timer( struct msg_queue *queue, struct timer *timer )
513 struct timeval now;
514 unlink_timer( queue, timer );
515 gettimeofday( &now, 0 );
516 while (!time_before( &now, &timer->when )) add_timeout( &timer->when, timer->rate );
517 link_timer( queue, timer );
520 /* find an expired timer matching the filtering parameters */
521 static struct timer *find_expired_timer( struct msg_queue *queue, handle_t win,
522 unsigned int get_first, unsigned int get_last,
523 int remove )
525 struct timer *timer;
526 for (timer = queue->first_timer; (timer && timer != queue->next_timer); timer = timer->next)
528 if (win && timer->win != win) continue;
529 if (timer->msg >= get_first && timer->msg <= get_last)
531 if (remove) restart_timer( queue, timer );
532 return timer;
535 return NULL;
538 /* kill a timer */
539 static int kill_timer( struct msg_queue *queue, handle_t win, unsigned int msg, unsigned int id )
541 struct timer *timer;
543 for (timer = queue->first_timer; timer; timer = timer->next)
545 if (timer->win != win || timer->msg != msg || timer->id != id) continue;
546 unlink_timer( queue, timer );
547 free( timer );
548 return 1;
550 return 0;
553 /* add a timer */
554 static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
556 struct timer *timer = mem_alloc( sizeof(*timer) );
557 if (timer)
559 timer->rate = rate;
560 gettimeofday( &timer->when, 0 );
561 add_timeout( &timer->when, rate );
562 link_timer( queue, timer );
564 return timer;
567 /* remove all messages and timers belonging to a certain window */
568 static void cleanup_window( struct msg_queue *queue, handle_t win )
570 struct timer *timer;
571 struct message *msg;
572 int i;
574 /* remove timers */
575 timer = queue->first_timer;
576 while (timer)
578 struct timer *next = timer->next;
579 if (timer->win == win)
581 unlink_timer( queue, timer );
582 free( timer );
584 timer = next;
587 /* remove messages */
588 for (i = 0; i < NB_MSG_KINDS; i++)
590 msg = queue->msg_list[i].first;
591 while (msg)
593 struct message *next = msg->next;
594 if (msg->win == win) remove_queue_message( queue, msg, i );
595 msg = next;
600 /* get the message queue of the current thread */
601 DECL_HANDLER(get_msg_queue)
603 struct msg_queue *queue = get_current_queue();
605 req->handle = 0;
606 if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
610 /* increment the message queue paint count */
611 DECL_HANDLER(inc_queue_paint_count)
613 struct msg_queue *queue;
614 struct thread *thread = get_thread_from_id( req->id );
616 if (!thread) return;
618 if ((queue = thread->queue))
620 if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
622 if (queue->paint_count)
623 change_queue_bits( queue, QS_PAINT, 0 );
624 else
625 change_queue_bits( queue, 0, QS_PAINT );
627 else set_error( STATUS_INVALID_PARAMETER );
629 release_object( thread );
634 /* set the current message queue wakeup mask */
635 DECL_HANDLER(set_queue_mask)
637 struct msg_queue *queue = get_current_queue();
639 if (queue)
641 queue->wake_mask = req->wake_mask;
642 queue->changed_mask = req->changed_mask;
643 req->wake_bits = queue->wake_bits;
644 req->changed_bits = queue->changed_bits;
645 if (is_signaled( queue ))
647 /* if skip wait is set, do what would have been done in the subsequent wait */
648 if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
649 else wake_up( &queue->obj, 0 );
655 /* get the current message queue status */
656 DECL_HANDLER(get_queue_status)
658 struct msg_queue *queue = current->queue;
659 if (queue)
661 req->wake_bits = queue->wake_bits;
662 req->changed_bits = queue->changed_bits;
663 if (req->clear) queue->changed_bits = 0;
665 else req->wake_bits = req->changed_bits = 0;
669 /* send a message to a thread queue */
670 DECL_HANDLER(send_message)
672 struct message *msg;
673 struct msg_queue *send_queue = get_current_queue();
674 struct msg_queue *recv_queue;
675 struct thread *thread = get_thread_from_id( req->id );
677 if (!thread) return;
679 if (!(recv_queue = thread->queue))
681 set_error( STATUS_INVALID_PARAMETER );
682 release_object( thread );
683 return;
686 if ((msg = mem_alloc( sizeof(*msg) )))
688 msg->type = req->type;
689 msg->win = req->win;
690 msg->msg = req->msg;
691 msg->wparam = req->wparam;
692 msg->lparam = req->lparam;
693 msg->x = req->x;
694 msg->y = req->y;
695 msg->time = req->time;
696 msg->info = req->info;
697 msg->result = NULL;
698 switch(req->kind)
700 case SEND_MESSAGE:
701 send_message( send_queue, recv_queue, msg );
702 break;
703 case POST_MESSAGE:
704 append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
705 change_queue_bits( recv_queue, QS_POSTMESSAGE, 0 );
706 break;
707 case COOKED_HW_MESSAGE:
708 case RAW_HW_MESSAGE:
709 if (msg->msg == WM_MOUSEMOVE && merge_message( &recv_queue->msg_list[req->kind], msg ))
711 free( msg );
713 else
715 append_message( &recv_queue->msg_list[req->kind], msg );
716 change_queue_bits( recv_queue, get_hardware_msg_bit(msg), 0 );
718 break;
719 default:
720 free( msg );
721 set_error( STATUS_INVALID_PARAMETER );
722 break;
725 release_object( thread );
728 /* store a message contents into the request buffer; helper for get_message */
729 inline static void put_req_message( struct get_message_request *req, const struct message *msg )
731 req->type = msg->type;
732 req->win = msg->win;
733 req->msg = msg->msg;
734 req->wparam = msg->wparam;
735 req->lparam = msg->lparam;
736 req->x = msg->x;
737 req->y = msg->y;
738 req->time = msg->time;
739 req->info = msg->info;
742 /* return a message to the application, removing it from the queue if needed */
743 static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
744 struct message *msg, enum message_kind kind )
746 req->kind = kind;
747 put_req_message( req, msg );
748 /* raw messages always get removed */
749 if ((kind == RAW_HW_MESSAGE) || (req->flags & GET_MSG_REMOVE))
751 queue->last_msg = NULL;
752 remove_queue_message( queue, msg, kind );
754 else /* remember it as the last returned message */
756 queue->last_msg = msg;
757 queue->last_msg_kind = kind;
762 inline static struct message *find_matching_message( const struct message_list *list, handle_t win,
763 unsigned int first, unsigned int last )
765 struct message *msg;
767 for (msg = list->first; msg; msg = msg->next)
769 /* check against the filters */
770 if (msg->msg == WM_QUIT) break; /* WM_QUIT is never filtered */
771 if (win && msg->win && msg->win != win) continue;
772 if (msg->msg < first) continue;
773 if (msg->msg > last) continue;
774 break; /* found one */
776 return msg;
780 /* get a message from the current queue */
781 DECL_HANDLER(get_message)
783 struct timer *timer;
784 struct message *msg;
785 struct msg_queue *queue = get_current_queue();
787 if (!queue) return;
789 /* first check for sent messages */
790 if ((msg = queue->msg_list[SEND_MESSAGE].first))
792 req->kind = SEND_MESSAGE;
793 put_req_message( req, msg );
794 receive_message( queue, msg );
795 return;
797 if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */
799 /* if requested, remove the last returned but not yet removed message */
800 if ((req->flags & GET_MSG_REMOVE_LAST) && queue->last_msg)
801 remove_queue_message( queue, queue->last_msg, queue->last_msg_kind );
802 queue->last_msg = NULL;
804 /* clear changed bits so we can wait on them if we don't find a message */
805 queue->changed_bits = 0;
807 /* then check for posted messages */
808 if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], req->get_win,
809 req->get_first, req->get_last )))
811 return_message_to_app( queue, req, msg, POST_MESSAGE );
812 return;
815 /* then check for cooked hardware messages */
816 if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], req->get_win,
817 req->get_first, req->get_last )))
819 return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
820 return;
823 /* then check for any raw hardware message */
824 if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
826 return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
827 return;
830 /* now check for WM_PAINT */
831 if ((queue->wake_bits & QS_PAINT) &&
832 (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
834 req->kind = POST_MESSAGE;
835 req->type = 0;
836 req->win = 0;
837 req->msg = WM_PAINT;
838 req->wparam = 0;
839 req->lparam = 0;
840 req->x = 0;
841 req->y = 0;
842 req->time = 0;
843 req->info = 0;
844 return;
847 /* now check for timer */
848 if ((timer = find_expired_timer( queue, req->get_win, req->get_first,
849 req->get_last, (req->flags & GET_MSG_REMOVE) )))
851 req->kind = POST_MESSAGE;
852 req->type = 0;
853 req->win = timer->win;
854 req->msg = timer->msg;
855 req->wparam = timer->id;
856 req->lparam = timer->lparam;
857 req->x = 0;
858 req->y = 0;
859 req->time = 0;
860 req->info = 0;
861 return;
864 done:
865 set_error( STATUS_PENDING ); /* FIXME */
869 /* reply to a sent message */
870 DECL_HANDLER(reply_message)
872 if (current->queue && current->queue->recv_result)
873 reply_message( current->queue, req->result, 0, req->remove );
874 else
875 set_error( STATUS_ACCESS_DENIED );
879 /* retrieve the reply for the last message sent */
880 DECL_HANDLER(get_message_reply)
882 if (current->queue) req->result = get_message_reply( current->queue, req->cancel );
883 else set_error( STATUS_ACCESS_DENIED );
887 /* check if we are processing a sent message */
888 DECL_HANDLER(in_send_message)
890 int flags = 0;
892 if (current->queue)
894 struct message_result *result = current->queue->recv_result;
895 if (result)
897 flags |= ISMEX_SEND; /* FIXME */
898 if (result->replied || !result->sender) flags |= ISMEX_REPLIED;
901 req->flags = flags;
905 /* cleanup a queue when a window is deleted */
906 DECL_HANDLER(cleanup_window_queue)
908 if (current->queue) cleanup_window( current->queue, req->win );
912 /* set a window timer */
913 DECL_HANDLER(set_win_timer)
915 struct timer *timer;
916 struct msg_queue *queue = get_current_queue();
918 if (!queue) return;
920 /* remove it if it existed already */
921 if (req->win) kill_timer( queue, req->win, req->msg, req->id );
923 if ((timer = set_timer( queue, req->rate )))
925 timer->win = req->win;
926 timer->msg = req->msg;
927 timer->id = req->id;
928 timer->lparam = req->lparam;
932 /* kill a window timer */
933 DECL_HANDLER(kill_win_timer)
935 struct msg_queue *queue = current->queue;
937 if (!queue || !kill_timer( queue, req->win, req->msg, req->id ))
938 set_error( STATUS_INVALID_PARAMETER );