source: mainline/uspace/srv/hid/display/seat.c@ 9242ad9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9242ad9 was 9242ad9, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Switch to double-arrow cursors when pointer is above resize areas

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 * Copyright (c) 2019 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/**
33 * @file Display server seat
34 */
35
36#include <adt/list.h>
37#include <errno.h>
38#include <gfx/color.h>
39#include <gfx/render.h>
40#include <stdlib.h>
41#include "client.h"
42#include "cursor.h"
43#include "display.h"
44#include "seat.h"
45#include "window.h"
46
47/** Create seat.
48 *
49 * @param display Parent display
50 * @param rseat Place to store pointer to new seat.
51 * @return EOK on success, ENOMEM if out of memory
52 */
53errno_t ds_seat_create(ds_display_t *display, ds_seat_t **rseat)
54{
55 ds_seat_t *seat;
56
57 seat = calloc(1, sizeof(ds_seat_t));
58 if (seat == NULL)
59 return ENOMEM;
60
61 ds_display_add_seat(display, seat);
62 seat->pntpos.x = 0;
63 seat->pntpos.y = 0;
64
65 seat->cursor = display->cursor[dcurs_arrow];
66
67 *rseat = seat;
68 return EOK;
69}
70
71/** Destroy seat.
72 *
73 * @param seat Seat
74 */
75void ds_seat_destroy(ds_seat_t *seat)
76{
77 ds_display_remove_seat(seat);
78 free(seat);
79}
80
81/** Set seat focus to a window.
82 *
83 * @param seat Seat
84 * @param wnd Window to focus
85 */
86void ds_seat_set_focus(ds_seat_t *seat, ds_window_t *wnd)
87{
88 if (seat->focus != NULL)
89 ds_window_post_unfocus_event(seat->focus);
90
91 seat->focus = wnd;
92
93 if (wnd != NULL) {
94 ds_window_post_focus_event(wnd);
95 ds_window_bring_to_top(wnd);
96 }
97}
98
99/** Evacuate focus from window.
100 *
101 * If seat's focus is @a wnd, it will be set to a different window.
102 *
103 * @param seat Seat
104 * @param wnd Window to evacuate focus from
105 */
106void ds_seat_evac_focus(ds_seat_t *seat, ds_window_t *wnd)
107{
108 ds_window_t *nwnd;
109
110 if (seat->focus == wnd) {
111 nwnd = ds_display_next_window(wnd);
112 if (nwnd == NULL)
113 nwnd = ds_display_first_window(wnd->display);
114 if (nwnd == wnd)
115 nwnd = NULL;
116
117 ds_seat_set_focus(seat, nwnd);
118 }
119}
120
121/** Post keyboard event to the seat's focused window.
122 *
123 * @param seat Seat
124 * @param event Event
125 *
126 * @return EOK on success or an error code
127 */
128errno_t ds_seat_post_kbd_event(ds_seat_t *seat, kbd_event_t *event)
129{
130 ds_window_t *dwindow;
131 bool alt_or_shift;
132
133 alt_or_shift = event->mods & (KM_SHIFT | KM_ALT);
134 if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_TAB) {
135 /* On Alt-Tab or Shift-Tab, switch focus to next window */
136 ds_seat_evac_focus(seat, seat->focus);
137 return EOK;
138 }
139
140 dwindow = seat->focus;
141 if (dwindow == NULL)
142 return EOK;
143
144 return ds_window_post_kbd_event(dwindow, event);
145}
146
147/** Draw seat pointer
148 *
149 * @param seat Seat
150 *
151 * @return EOK on success or an error code
152 */
153static errno_t ds_seat_draw_pointer(ds_seat_t *seat)
154{
155 return ds_cursor_paint(seat->cursor, &seat->pntpos);
156}
157
158/** Clear seat pointer
159 *
160 * @param seat Seat
161 *
162 * @return EOK on success or an error code
163 */
164static errno_t ds_seat_clear_pointer(ds_seat_t *seat)
165{
166 gfx_rect_t rect;
167
168 /* Get rectangle covered by cursor */
169 ds_cursor_get_rect(seat->cursor, &seat->pntpos, &rect);
170
171 /* Repaint it */
172 return ds_display_paint(seat->display, &rect);
173}
174
175/** Post pointing device event to the seat
176 *
177 * Update pointer position and generate position event.
178 *
179 * @param seat Seat
180 * @param event Event
181 *
182 * @return EOK on success or an error code
183 */
184#include <stdio.h>
185errno_t ds_seat_post_ptd_event(ds_seat_t *seat, ptd_event_t *event)
186{
187 ds_display_t *disp = seat->display;
188 gfx_coord2_t npos;
189 ds_window_t *wnd;
190 pos_event_t pevent;
191 errno_t rc;
192
193 wnd = ds_display_window_by_pos(seat->display, &seat->pntpos);
194
195 /* Focus window on button press */
196 if (event->type == PTD_PRESS && event->btn_num == 1) {
197 if (wnd != NULL) {
198 ds_seat_set_focus(seat, wnd);
199 }
200 }
201
202 if (event->type == PTD_PRESS || event->type == PTD_RELEASE) {
203 pevent.pos_id = 0;
204 pevent.type = (event->type == PTD_PRESS) ?
205 POS_PRESS : POS_RELEASE;
206 pevent.btn_num = event->btn_num;
207 pevent.hpos = seat->pntpos.x;
208 pevent.vpos = seat->pntpos.y;
209
210 rc = ds_seat_post_pos_event(seat, &pevent);
211 if (rc != EOK)
212 return rc;
213 }
214
215 if (event->type == PTD_MOVE) {
216 gfx_coord2_add(&seat->pntpos, &event->dmove, &npos);
217 gfx_coord2_clip(&npos, &disp->rect, &npos);
218
219 (void) ds_seat_clear_pointer(seat);
220 seat->pntpos = npos;
221
222 pevent.pos_id = 0;
223 pevent.type = POS_UPDATE;
224 pevent.btn_num = 0;
225 pevent.hpos = seat->pntpos.x;
226 pevent.vpos = seat->pntpos.y;
227
228 rc = ds_seat_post_pos_event(seat, &pevent);
229 if (rc != EOK)
230 return rc;
231
232 (void) ds_seat_draw_pointer(seat);
233 }
234
235 if (event->type == PTD_ABS_MOVE) {
236 /*
237 * Project input device area onto display area. Technically
238 * we probably want to project onto the area of a particular
239 * display device. The tricky part is figuring out which
240 * display device the input device is associated with.
241 */
242 gfx_coord2_project(&event->apos, &event->abounds,
243 &disp->rect, &npos);
244
245 gfx_coord2_clip(&npos, &disp->rect, &npos);
246
247 (void) ds_seat_clear_pointer(seat);
248 seat->pntpos = npos;
249
250 pevent.pos_id = 0;
251 pevent.type = POS_UPDATE;
252 pevent.btn_num = 0;
253 pevent.hpos = seat->pntpos.x;
254 pevent.vpos = seat->pntpos.y;
255
256 rc = ds_seat_post_pos_event(seat, &pevent);
257 if (rc != EOK)
258 return rc;
259
260 (void) ds_seat_draw_pointer(seat);
261 }
262
263 return EOK;
264}
265
266/** Post position event to seat.
267 *
268 * Deliver event to relevant windows.
269 *
270 * @param seat Seat
271 * @param event Position event
272 */
273errno_t ds_seat_post_pos_event(ds_seat_t *seat, pos_event_t *event)
274{
275 ds_window_t *wnd;
276 errno_t rc;
277
278 wnd = ds_display_window_by_pos(seat->display, &seat->pntpos);
279 if (wnd != NULL) {
280 /* Moving over a window */
281 seat->cursor = wnd->cursor;
282
283 rc = ds_window_post_pos_event(wnd, event);
284 if (rc != EOK)
285 return rc;
286 } else {
287 /* Not over a window */
288 seat->cursor = seat->display->cursor[dcurs_arrow];
289 }
290
291 if (seat->focus != wnd) {
292 rc = ds_window_post_pos_event(seat->focus, event);
293 if (rc != EOK)
294 return rc;
295 }
296
297 return EOK;
298}
299
300/** @}
301 */
Note: See TracBrowser for help on using the repository browser.