summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-29 20:59:18 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-29 20:59:18 +1100
commitfa0e71e0ee22ec9401732d9ac8b3c1d1fd9d2c31 (patch)
treea09ecc26c051c7859226e3ccf4d00045be8e1e11
parentd575e2b4fd8249e0ae584b0b6401ff6b8dd7d2c4 (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.h34
-rw-r--r--twin_screen.c80
2 files changed, 82 insertions, 32 deletions
diff --git a/twin.h b/twin.h
index b7fbe5b..c2603c6 100644
--- a/twin.h
+++ b/twin.h
@@ -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;