source: mainline/uspace/srv/hid/display/ievent.c

Last change on this file was 6fbd1f9, checked in by Jiri Svoboda <jiri@…>, 9 months ago

Combine successive move/abs. move events in display server

Helps avoid the cursor lagging if re-drawing cannot keep up
with the rate of move events.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2024 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup display
30 * @{
31 */
32/** @file Input event queue
33 */
34
35#include <adt/list.h>
36#include <errno.h>
37#include <fibril_synch.h>
38#include <io/kbd_event.h>
39#include <stdlib.h>
40#include "display.h"
41#include "ievent.h"
42
43/** Post keyboard event to input event queue.
44 *
45 * @param disp Display
46 * @param kbd Keyboard event
47 *
48 * @return EOK on success or an error code
49 */
50errno_t ds_ievent_post_kbd(ds_display_t *disp, kbd_event_t *kbd)
51{
52 ds_ievent_t *ievent;
53
54 ievent = calloc(1, sizeof(ds_ievent_t));
55 if (ievent == NULL)
56 return ENOMEM;
57
58 ievent->display = disp;
59 ievent->etype = det_kbd;
60 ievent->ev.kbd = *kbd;
61
62 list_append(&ievent->lievents, &disp->ievents);
63 fibril_condvar_signal(&disp->ievent_cv);
64
65 return EOK;
66}
67
68/** Post pointing device event to input event queue.
69 *
70 * @param disp Display
71 * @param kbd Keyboard event
72 *
73 * @return EOK on success or an error code
74 */
75errno_t ds_ievent_post_ptd(ds_display_t *disp, ptd_event_t *ptd)
76{
77 ds_ievent_t *ievent;
78 ds_ievent_t *prev;
79 link_t *link;
80
81 ievent = calloc(1, sizeof(ds_ievent_t));
82 if (ievent == NULL)
83 return ENOMEM;
84
85 link = list_last(&disp->ievents);
86 if (link != NULL) {
87 prev = list_get_instance(link, ds_ievent_t, lievents);
88 if (prev->etype == det_ptd && prev->ev.ptd.pos_id ==
89 ptd->pos_id) {
90 /*
91 * Previous event is also a pointing device event
92 * and it is from the same device.
93 */
94 if (prev->ev.ptd.type == PTD_MOVE &&
95 ptd->type == PTD_MOVE) {
96 /* Both events are relative move events */
97 gfx_coord2_add(&ptd->dmove, &prev->ev.ptd.dmove,
98 &prev->ev.ptd.dmove);
99 return EOK;
100 } else if (prev->ev.ptd.type == PTD_ABS_MOVE &&
101 ptd->type == PTD_ABS_MOVE) {
102 /* Both events are absolute move events */
103 prev->ev.ptd.apos = ptd->apos;
104 prev->ev.ptd.abounds = ptd->abounds;
105 return EOK;
106 }
107 }
108 }
109
110 ievent->display = disp;
111 ievent->etype = det_ptd;
112 ievent->ev.ptd = *ptd;
113
114 list_append(&ievent->lievents, &disp->ievents);
115 fibril_condvar_signal(&disp->ievent_cv);
116
117 return EOK;
118}
119
120/** Input event processing fibril.
121 *
122 * @param arg Argument (ds_display_t *)
123 * @return EOK success
124 */
125static errno_t ds_ievent_fibril(void *arg)
126{
127 ds_display_t *disp = (ds_display_t *)arg;
128 ds_ievent_t *ievent;
129 link_t *link;
130
131 fibril_mutex_lock(&disp->lock);
132
133 while (!disp->ievent_quit) {
134 while (list_empty(&disp->ievents))
135 fibril_condvar_wait(&disp->ievent_cv, &disp->lock);
136
137 link = list_first(&disp->ievents);
138 assert(link != NULL);
139 list_remove(link);
140 ievent = list_get_instance(link, ds_ievent_t, lievents);
141
142 switch (ievent->etype) {
143 case det_kbd:
144 (void)ds_display_post_kbd_event(disp, &ievent->ev.kbd);
145 break;
146 case det_ptd:
147 (void)ds_display_post_ptd_event(disp, &ievent->ev.ptd);
148 break;
149 }
150 }
151
152 /* Signal to ds_ievent_fini() that the event processing fibril quit */
153 disp->ievent_done = true;
154 fibril_condvar_signal(&disp->ievent_cv);
155 fibril_mutex_unlock(&disp->lock);
156
157 return EOK;
158}
159
160/** Initialize input event processing.
161 *
162 * @param disp Display
163 * @return EOK on success or an error code
164 */
165errno_t ds_ievent_init(ds_display_t *disp)
166{
167 assert(disp->ievent_fid == 0);
168
169 disp->ievent_fid = fibril_create(ds_ievent_fibril, (void *)disp);
170 if (disp->ievent_fid == 0)
171 return ENOMEM;
172
173 fibril_add_ready(disp->ievent_fid);
174 return EOK;
175}
176
177/** Deinitialize input event processing.
178 *
179 * @param disp Display
180 */
181void ds_ievent_fini(ds_display_t *disp)
182{
183 ds_ievent_t *ievent;
184 link_t *link;
185
186 if (disp->ievent_fid == 0)
187 return;
188
189 /* Signal event processing fibril to quit. */
190 fibril_mutex_lock(&disp->lock);
191 disp->ievent_quit = true;
192 fibril_condvar_signal(&disp->ievent_cv);
193
194 /* Wait for event processing fibril to quit. */
195 while (!disp->ievent_done)
196 fibril_condvar_wait(&disp->ievent_cv, &disp->lock);
197
198 /* Remove all events from the queue. */
199 while (!list_empty(&disp->ievents)) {
200 link = list_first(&disp->ievents);
201 assert(link != NULL);
202 list_remove(link);
203 ievent = list_get_instance(link, ds_ievent_t, lievents);
204 free(ievent);
205 }
206
207 fibril_mutex_unlock(&disp->lock);
208
209 fibril_detach(disp->ievent_fid);
210 disp->ievent_fid = 0;
211}
212
213/** @}
214 */
Note: See TracBrowser for help on using the repository browser.