HelenOS sources
This source file includes following definitions.
- ds_seat_create
- ds_seat_destroy
- ds_seat_load
- ds_seat_save
- ds_seat_set_focus
- ds_seat_set_popup
- ds_seat_evac_wnd_refs
- ds_seat_unfocus_wnd
- ds_seat_switch_focus
- ds_seat_post_kbd_event
- ds_seat_compute_cursor
- ds_seat_get_cursor
- ds_seat_set_client_cursor
- ds_seat_set_wm_cursor
- ds_seat_get_pointer_rect
- ds_seat_repaint_pointer
- ds_seat_post_ptd_event
- ds_seat_post_pos_event
- ds_seat_paint_pointer
- ds_seat_add_idevcfg
- ds_seat_remove_idevcfg
- ds_seat_first_idevcfg
- ds_seat_next_idevcfg
#include <adt/list.h>
#include <errno.h>
#include <gfx/color.h>
#include <gfx/render.h>
#include <sif.h>
#include <stdio.h>
#include <stdlib.h>
#include <str.h>
#include "client.h"
#include "cursor.h"
#include "display.h"
#include "idevcfg.h"
#include "seat.h"
#include "window.h"
static void ds_seat_get_pointer_rect(ds_seat_t *, gfx_rect_t *);
static errno_t ds_seat_repaint_pointer(ds_seat_t *, gfx_rect_t *);
errno_t ds_seat_create(ds_display_t *display, const char *name,
ds_seat_t **rseat)
{
ds_seat_t *seat;
ds_seat_t *s0;
s0 = ds_display_first_seat(display);
while (s0 != NULL) {
if (str_cmp(s0->name, name) == 0)
return EEXIST;
s0 = ds_display_next_seat(s0);
}
seat = calloc(1, sizeof(ds_seat_t));
if (seat == NULL)
return ENOMEM;
seat->name = str_dup(name);
if (seat->name == NULL) {
free(seat);
return ENOMEM;
}
list_initialize(&seat->idevcfgs);
ds_display_add_seat(display, seat);
seat->pntpos.x = 0;
seat->pntpos.y = 0;
seat->client_cursor = display->cursor[dcurs_arrow];
seat->wm_cursor = NULL;
seat->focus = ds_display_first_window(display);
*rseat = seat;
return EOK;
}
void ds_seat_destroy(ds_seat_t *seat)
{
ds_idevcfg_t *idevcfg;
idevcfg = ds_seat_first_idevcfg(seat);
while (idevcfg != NULL) {
ds_idevcfg_destroy(idevcfg);
idevcfg = ds_seat_first_idevcfg(seat);
}
if (seat->focus != NULL)
ds_window_post_unfocus_event(seat->focus);
ds_display_remove_seat(seat);
free(seat->name);
free(seat);
}
errno_t ds_seat_load(ds_display_t *display, sif_node_t *snode,
ds_seat_t **rseat)
{
const char *sid;
const char *name;
char *endptr;
unsigned long id;
errno_t rc;
sid = sif_node_get_attr(snode, "id");
if (sid == NULL)
return EIO;
name = sif_node_get_attr(snode, "name");
if (name == NULL)
return EIO;
id = strtoul(sid, &endptr, 10);
if (*endptr != '\0')
return EIO;
rc = ds_seat_create(display, name, rseat);
if (rc != EOK)
return EIO;
(*rseat)->id = id;
return EOK;
}
errno_t ds_seat_save(ds_seat_t *seat, sif_node_t *snode)
{
char *sid;
errno_t rc;
int rv;
rv = asprintf(&sid, "%lu", (unsigned long)seat->id);
if (rv < 0) {
rc = ENOMEM;
return rc;
}
rc = sif_node_set_attr(snode, "id", sid);
if (rc != EOK) {
free(sid);
return rc;
}
free(sid);
rc = sif_node_set_attr(snode, "name", seat->name);
if (rc != EOK)
return rc;
return EOK;
}
void ds_seat_set_focus(ds_seat_t *seat, ds_window_t *wnd)
{
errno_t rc;
if (wnd == seat->focus) {
return;
}
if (wnd != NULL) {
rc = ds_window_unminimize(wnd);
if (rc != EOK)
return;
}
if (seat->focus != NULL)
ds_window_post_unfocus_event(seat->focus);
seat->focus = wnd;
if (wnd != NULL) {
ds_window_post_focus_event(wnd);
ds_window_bring_to_top(wnd);
}
ds_seat_set_popup(seat, NULL);
}
void ds_seat_set_popup(ds_seat_t *seat, ds_window_t *wnd)
{
if (wnd == seat->popup)
return;
if (seat->popup != NULL) {
ds_client_post_close_event(seat->popup->client,
seat->popup);
}
seat->popup = wnd;
}
void ds_seat_evac_wnd_refs(ds_seat_t *seat, ds_window_t *wnd)
{
if (seat->focus == wnd)
ds_seat_set_focus(seat, NULL);
if (seat->popup == wnd)
ds_seat_set_popup(seat, NULL);
}
void ds_seat_unfocus_wnd(ds_seat_t *seat, ds_window_t *wnd)
{
ds_window_t *nwnd;
if (seat->focus != wnd)
return;
nwnd = ds_window_find_prev(wnd, ~(wndf_minimized | wndf_system));
if (nwnd == NULL) {
nwnd = ds_window_find_prev(wnd, ~wndf_minimized);
}
ds_seat_set_focus(seat, nwnd);
}
void ds_seat_switch_focus(ds_seat_t *seat)
{
ds_window_t *nwnd;
if (seat->focus != NULL) {
nwnd = ds_window_find_next(seat->focus, ~wndf_system);
} else {
nwnd = ds_display_first_window(seat->display);
}
if (nwnd != NULL)
ds_seat_set_focus(seat, nwnd);
}
errno_t ds_seat_post_kbd_event(ds_seat_t *seat, kbd_event_t *event)
{
ds_window_t *dwindow;
bool alt_or_shift;
alt_or_shift = event->mods & (KM_SHIFT | KM_ALT);
if (event->type == KEY_PRESS && alt_or_shift && event->key == KC_TAB) {
ds_seat_switch_focus(seat);
return EOK;
}
dwindow = seat->popup;
if (dwindow == NULL)
dwindow = seat->focus;
if (dwindow == NULL)
return EOK;
return ds_window_post_kbd_event(dwindow, event);
}
static ds_cursor_t *ds_seat_compute_cursor(ds_cursor_t *wmcurs, ds_cursor_t *ccurs)
{
if (wmcurs != NULL)
return wmcurs;
return ccurs;
}
static ds_cursor_t *ds_seat_get_cursor(ds_seat_t *seat)
{
return ds_seat_compute_cursor(seat->wm_cursor, seat->client_cursor);
}
static void ds_seat_set_client_cursor(ds_seat_t *seat, ds_cursor_t *cursor)
{
ds_cursor_t *old_cursor;
ds_cursor_t *new_cursor;
gfx_rect_t old_rect;
old_cursor = ds_seat_get_cursor(seat);
new_cursor = ds_seat_compute_cursor(seat->wm_cursor, cursor);
if (new_cursor != old_cursor) {
ds_seat_get_pointer_rect(seat, &old_rect);
seat->client_cursor = cursor;
ds_seat_repaint_pointer(seat, &old_rect);
} else {
seat->client_cursor = cursor;
}
}
void ds_seat_set_wm_cursor(ds_seat_t *seat, ds_cursor_t *cursor)
{
ds_cursor_t *old_cursor;
ds_cursor_t *new_cursor;
gfx_rect_t old_rect;
old_cursor = ds_seat_get_cursor(seat);
new_cursor = ds_seat_compute_cursor(cursor, seat->client_cursor);
if (new_cursor != old_cursor) {
ds_seat_get_pointer_rect(seat, &old_rect);
seat->wm_cursor = cursor;
ds_seat_repaint_pointer(seat, &old_rect);
} else {
seat->wm_cursor = cursor;
}
}
void ds_seat_get_pointer_rect(ds_seat_t *seat, gfx_rect_t *rect)
{
ds_cursor_t *cursor;
cursor = ds_seat_get_cursor(seat);
ds_cursor_get_rect(cursor, &seat->pntpos, rect);
}
static errno_t ds_seat_repaint_pointer(ds_seat_t *seat, gfx_rect_t *old_rect)
{
gfx_rect_t new_rect;
gfx_rect_t envelope;
errno_t rc;
ds_seat_get_pointer_rect(seat, &new_rect);
if (gfx_rect_is_incident(old_rect, &new_rect)) {
rc = ds_display_paint(seat->display, &new_rect);
if (rc != EOK)
return rc;
rc = ds_display_paint(seat->display, old_rect);
if (rc != EOK)
return rc;
} else {
gfx_rect_envelope(old_rect, &new_rect, &envelope);
rc = ds_display_paint(seat->display, &envelope);
if (rc != EOK)
return rc;
}
return EOK;
}
errno_t ds_seat_post_ptd_event(ds_seat_t *seat, ptd_event_t *event)
{
ds_display_t *disp = seat->display;
gfx_coord2_t npos;
gfx_rect_t old_rect;
ds_window_t *wnd;
pos_event_t pevent;
errno_t rc;
wnd = ds_display_window_by_pos(seat->display, &seat->pntpos);
if (event->type == PTD_PRESS && event->btn_num == 1) {
if (wnd != NULL && (wnd->flags & wndf_popup) == 0 &&
(wnd->flags & wndf_nofocus) == 0) {
ds_seat_set_focus(seat, wnd);
}
}
if (event->type == PTD_PRESS || event->type == PTD_RELEASE ||
event->type == PTD_DCLICK) {
pevent.pos_id = event->pos_id;
switch (event->type) {
case PTD_PRESS:
pevent.type = POS_PRESS;
break;
case PTD_RELEASE:
pevent.type = POS_RELEASE;
break;
case PTD_DCLICK:
pevent.type = POS_DCLICK;
break;
default:
assert(false);
}
pevent.btn_num = event->btn_num;
pevent.hpos = seat->pntpos.x;
pevent.vpos = seat->pntpos.y;
rc = ds_seat_post_pos_event(seat, &pevent);
if (rc != EOK)
return rc;
}
if (event->type == PTD_MOVE) {
gfx_coord2_add(&seat->pntpos, &event->dmove, &npos);
gfx_coord2_clip(&npos, &disp->rect, &npos);
ds_seat_get_pointer_rect(seat, &old_rect);
seat->pntpos = npos;
pevent.pos_id = event->pos_id;
pevent.type = POS_UPDATE;
pevent.btn_num = 0;
pevent.hpos = seat->pntpos.x;
pevent.vpos = seat->pntpos.y;
rc = ds_seat_post_pos_event(seat, &pevent);
if (rc != EOK)
return rc;
ds_seat_repaint_pointer(seat, &old_rect);
}
if (event->type == PTD_ABS_MOVE) {
gfx_coord2_project(&event->apos, &event->abounds,
&disp->rect, &npos);
gfx_coord2_clip(&npos, &disp->rect, &npos);
ds_seat_get_pointer_rect(seat, &old_rect);
seat->pntpos = npos;
pevent.pos_id = event->pos_id;
pevent.type = POS_UPDATE;
pevent.btn_num = 0;
pevent.hpos = seat->pntpos.x;
pevent.vpos = seat->pntpos.y;
rc = ds_seat_post_pos_event(seat, &pevent);
if (rc != EOK)
return rc;
ds_seat_repaint_pointer(seat, &old_rect);
}
return EOK;
}
errno_t ds_seat_post_pos_event(ds_seat_t *seat, pos_event_t *event)
{
ds_window_t *pwindow;
ds_window_t *cwindow;
errno_t rc;
pwindow = ds_display_window_by_pos(seat->display, &seat->pntpos);
cwindow = seat->popup;
if (cwindow == NULL)
cwindow = seat->focus;
if (event->type != POS_PRESS && cwindow != NULL &&
cwindow != pwindow) {
rc = ds_window_post_pos_event(cwindow, event);
if (rc != EOK)
return rc;
}
if (pwindow != NULL) {
ds_seat_set_client_cursor(seat, pwindow->cursor);
rc = ds_window_post_pos_event(pwindow, event);
if (rc != EOK)
return rc;
} else {
ds_seat_set_client_cursor(seat,
seat->display->cursor[dcurs_arrow]);
}
if (event->type == POS_PRESS && pwindow != seat->popup) {
ds_seat_set_popup(seat, NULL);
}
return EOK;
}
errno_t ds_seat_paint_pointer(ds_seat_t *seat, gfx_rect_t *rect)
{
ds_cursor_t *cursor;
cursor = ds_seat_get_cursor(seat);
return ds_cursor_paint(cursor, &seat->pntpos, rect);
}
void ds_seat_add_idevcfg(ds_seat_t *seat, ds_idevcfg_t *idevcfg)
{
assert(idevcfg->seat == NULL);
assert(!link_used(&idevcfg->lseatidcfgs));
idevcfg->seat = seat;
list_append(&idevcfg->lseatidcfgs, &seat->idevcfgs);
}
void ds_seat_remove_idevcfg(ds_idevcfg_t *idevcfg)
{
list_remove(&idevcfg->lseatidcfgs);
idevcfg->seat = NULL;
}
ds_idevcfg_t *ds_seat_first_idevcfg(ds_seat_t *seat)
{
link_t *link = list_first(&seat->idevcfgs);
if (link == NULL)
return NULL;
return list_get_instance(link, ds_idevcfg_t, lseatidcfgs);
}
ds_idevcfg_t *ds_seat_next_idevcfg(ds_idevcfg_t *idevcfg)
{
link_t *link = list_next(&idevcfg->lseatidcfgs, &idevcfg->seat->idevcfgs);
if (link == NULL)
return NULL;
return list_get_instance(link, ds_idevcfg_t, lseatidcfgs);
}
HelenOS homepage, sources at GitHub