diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-11-29 20:59:18 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-11-29 20:59:18 +1100 |
commit | fa0e71e0ee22ec9401732d9ac8b3c1d1fd9d2c31 (patch) | |
tree | a09ecc26c051c7859226e3ccf4d00045be8e1e11 | |
parent | d575e2b4fd8249e0ae584b0b6401ff6b8dd7d2c4 (diff) |
Add mouse enter/leave events for pixmaps/windows.
The current "target" is the one under the mouse and also
receives mouse movements and button down events. However,
once the button has been pressed in a window, all subsequent
mouse events will be sent to that window (and no mouse leave
will be generated) until the button has been released.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | twin.h | 34 | ||||
-rw-r--r-- | twin_screen.c | 80 |
2 files changed, 82 insertions, 32 deletions
@@ -159,9 +159,10 @@ typedef struct _twin_screen { */ twin_pixmap_t *active; /* - * pointer down for this window + * this pixmap is target of mouse events */ - twin_pixmap_t *pointer; + twin_pixmap_t *target; + twin_bool_t clicklock; /* * mouse image (optional) */ @@ -317,14 +318,27 @@ extern twin_font_t twin_Default_Font_Roman; */ typedef enum _twin_event_kind { - TwinEventButtonDown, TwinEventButtonUp, TwinEventMotion, - TwinEventKeyDown, TwinEventKeyUp, TwinEventUcs4, - TwinEventActivate, TwinEventDeactivate, - TwinEventPaint, - TwinEventShow, - TwinEventQueryGeometry, - TwinEventConfigure, - TwinEventDestroy, + /* Mouse */ + TwinEventButtonDown = 0x0001, + TwinEventButtonUp = 0x0002, + TwinEventMotion = 0x0003, + TwinEventEnter = 0x0004, + TwinEventLeave = 0x0005, + + /* keyboard */ + TwinEventKeyDown = 0x0101, + TwinEventKeyUp = 0x0102, + TwinEventUcs4 = 0x0103, + + /* Focus */ + TwinEventActivate = 0x0201, + TwinEventDeactivate = 0x0202, + + /* Widgets */ + TwinEventPaint = 0x1001, + TwinEventQueryGeometry = 0x1002, + TwinEventConfigure = 0x1003, + TwinEventDestroy = 0x1004, } twin_event_kind_t; typedef struct _twin_event { diff --git a/twin_screen.c b/twin_screen.c index 8de8007..b2cc6dd 100644 --- a/twin_screen.c +++ b/twin_screen.c @@ -323,44 +323,80 @@ twin_screen_update_cursor(twin_screen_t *screen, } } -twin_bool_t -twin_screen_dispatch (twin_screen_t *screen, - twin_event_t *event) +static void _twin_adj_mouse_evt(twin_event_t *event, twin_pixmap_t *pixmap) +{ + event->u.pointer.x = event->u.pointer.screen_x - pixmap->x; + event->u.pointer.y = event->u.pointer.screen_y - pixmap->y; +} + +twin_bool_t twin_screen_dispatch (twin_screen_t *screen, + twin_event_t *event) { - twin_pixmap_t *pixmap; + twin_pixmap_t *pixmap, *ntarget; switch (event->kind) { case TwinEventMotion: case TwinEventButtonDown: case TwinEventButtonUp: + /* update mouse cursor */ twin_screen_update_cursor(screen, event->u.pointer.screen_x, event->u.pointer.screen_y); - pixmap = screen->pointer; - if (!pixmap) - { - for (pixmap = screen->top; pixmap; pixmap = pixmap->down) - if (!twin_pixmap_transparent (pixmap, - event->u.pointer.screen_x, - event->u.pointer.screen_y)) - { - break; - } - if (event->kind == TwinEventButtonDown) - screen->pointer = pixmap; - } + + /* if target is tracking the mouse, check for mouse up, if not, + * just pass the event along + */ + pixmap = screen->target; + if (screen->clicklock && event->kind != TwinEventButtonUp) + goto mouse_passup; + + /* if event is mouse up, stop tracking if any */ if (event->kind == TwinEventButtonUp) - screen->pointer = NULL; - if (pixmap) - { - event->u.pointer.x = event->u.pointer.screen_x - pixmap->x; - event->u.pointer.y = event->u.pointer.screen_y - pixmap->y; + screen->clicklock = 0; + + /* check who the mouse is over now */ + for (ntarget = screen->top; ntarget; ntarget = ntarget->down) + if (!twin_pixmap_transparent (ntarget, + event->u.pointer.screen_x, + event->u.pointer.screen_y)) + break; + + /* ah, somebody new ... send leave/enter events and set new target */ + if (pixmap != ntarget) { + twin_event_t evt; + + if (pixmap) { + evt = *event; + evt.kind = TwinEventLeave; + _twin_adj_mouse_evt (&evt, pixmap); + twin_pixmap_dispatch (pixmap, &evt); + } + + pixmap = screen->target = ntarget; + + if (pixmap) { + evt = *event; + _twin_adj_mouse_evt (&evt, pixmap); + evt.kind = TwinEventEnter; + twin_pixmap_dispatch (pixmap, &evt); + } } + + /* check for new click locking */ + if (pixmap && event->kind == TwinEventButtonDown) + screen->clicklock = 1; + + mouse_passup: + /* adjust event to pixmap coordinates before passing up */ + if (pixmap) + _twin_adj_mouse_evt (event, pixmap); break; + case TwinEventKeyDown: case TwinEventKeyUp: case TwinEventUcs4: pixmap = screen->active; break; + default: pixmap = NULL; break; |