diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 6320dd1..2d1db43 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -39,6 +39,7 @@ struct _MwLLHandler { void (*down)(MwLL handle, void* data); void (*resize)(MwLL handle, void* data); void (*close)(MwLL handle, void* data); + void (*move)(MwLL handle, void* data); }; #ifdef __cplusplus diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index bb6362b..e4ac548 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -74,7 +74,7 @@ struct _MwWidget { MwClass widget_class; int pressed; - MwPoint pressed_point; + MwPoint mouse_point; int close; jmp_buf before_step; @@ -88,6 +88,7 @@ struct _MwWidget { struct _MwMenu { char* name; + int keep; MwWidget wsub; MwMenu* sub; }; diff --git a/src/backend/x11.c b/src/backend/x11.c index c39e0c3..f97f6bf 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -1,7 +1,7 @@ /* $Id$ */ #include -static unsigned long mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask; +static unsigned long mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask; static void create_pixmap(MwLL handle) { XWindowAttributes attr; @@ -175,6 +175,12 @@ void MwLLNextEvent(MwLL handle) { if(ev.xclient.data.l[0] == (long)handle->wm_delete) { MwLLDispatch(handle, close, NULL); } + } else if(ev.type == MotionNotify) { + MwPoint p; + p.x = ev.xmotion.x; + p.y = ev.xmotion.y; + + MwLLDispatch(handle, move, &p); } if(render) { int x, y; diff --git a/src/core.c b/src/core.c index e962ed9..533ba5b 100644 --- a/src/core.c +++ b/src/core.c @@ -22,11 +22,11 @@ static void lluphandler(MwLL handle, void* data) { } static void lldownhandler(MwLL handle, void* data) { - MwWidget h = (MwWidget)handle->user; - MwPoint* p = data; - h->pressed = 1; - h->pressed_point.x = p->x; - h->pressed_point.y = p->y; + MwWidget h = (MwWidget)handle->user; + MwPoint* p = data; + h->pressed = 1; + h->mouse_point.x = p->x; + h->mouse_point.y = p->y; } static void llresizehandler(MwLL handle, void* data) { @@ -49,6 +49,13 @@ static void llclosehandler(MwLL handle, void* data) { h->close = 1; } +static void llmovehandler(MwLL handle, void* data) { + MwWidget h = (MwWidget)handle->user; + MwPoint* p = data; + h->mouse_point.x = p->x; + h->mouse_point.y = p->y; +} + MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height) { MwWidget h = malloc(sizeof(*h)); @@ -72,6 +79,7 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, h->lowlevel->handler->down = lldownhandler; h->lowlevel->handler->resize = llresizehandler; h->lowlevel->handler->close = llclosehandler; + h->lowlevel->handler->move = llmovehandler; if(parent != NULL) arrput(parent->children, h); diff --git a/src/widget/menu.c b/src/widget/menu.c index d2e748c..c63b5c2 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -79,6 +79,7 @@ static void draw(MwWidget handle) { int tw = MwTextWidth(handle, m->sub[i]->name + incr); int th = MwTextHeight(handle, m->sub[i]->name + incr); int oldx = p.x; + int in_area; if(incr) { p.x = MwGetInteger(handle, MwNwidth) - tw - 10; @@ -90,7 +91,8 @@ static void draw(MwWidget handle) { r.width = tw + 10; r.height = th + 10; - if(handle->pressed && r.x <= handle->pressed_point.x && r.y <= handle->pressed_point.y && handle->pressed_point.x <= (int)(r.x + r.width) && handle->pressed_point.y <= (int)(r.y + r.height)) { + in_area = (r.x <= handle->mouse_point.x && r.y <= handle->mouse_point.y && handle->mouse_point.x <= (int)(r.x + r.width) && handle->mouse_point.y <= (int)(r.y + r.height)) ? 1 : 0; + if(handle->pressed && in_area) { MwDrawFrame(handle, &r, base, 0); if(m->sub[i]->wsub == NULL && arrlen(m->sub[i]->sub) > 0) { MwPoint p2; @@ -100,10 +102,24 @@ static void draw(MwWidget handle) { m->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0); MwSubMenuAppear(m->sub[i]->wsub, m->sub[i], &p2); + } else if(m->sub[i]->keep) { + MwDestroyWidget(m->sub[i]->wsub); + m->sub[i]->wsub = NULL; + m->sub[i]->keep = 0; } } else if(!handle->pressed && m->sub[i]->wsub != NULL) { + if(in_area) { + MwDrawFrame(handle, &r, base, 0); + m->sub[i]->keep = 1; + } else { + MwDestroyWidget(m->sub[i]->wsub); + m->sub[i]->wsub = NULL; + m->sub[i]->keep = 0; + } + } else if(m->sub[i]->keep && m->sub[i]->wsub != NULL) { MwDestroyWidget(m->sub[i]->wsub); m->sub[i]->wsub = NULL; + m->sub[i]->keep = 0; } MwDrawText(handle, &p, m->sub[i]->name + incr, 1, text); @@ -135,6 +151,7 @@ MwMenu MwMenuAdd(MwWidget handle, MwMenu menu, const char* name) { new->name = malloc(strlen(name) + 1); new->sub = NULL; new->wsub = NULL; + new->keep = 0; strcpy(new->name, name); diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 53638c7..e4e2511 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -101,6 +101,7 @@ void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point) { XChangeProperty(handle->lowlevel->display, handle->lowlevel->window, wndtype, 4, 32, PropModeReplace, (unsigned char*)&wndmenu, 1); XMapWindow(handle->lowlevel->display, handle->lowlevel->window); + XSetInputFocus(handle->lowlevel->display, handle->lowlevel->window, RevertToNone, CurrentTime); #endif handle->internal = menu;