diff --git a/GNUmakefile b/GNUmakefile index 7efb28f..621ade1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -35,7 +35,7 @@ L_LIBS = $(LIBS) L_OBJS = src/core.o src/default.o src/draw.o src/lowlevel.o src/font.o src/boldfont.o src/error.o src/unicode.o src/color.o src/messagebox.o src/directory.o src/string.o src/filechooser.o L_OBJS += external/ds.o external/image.o L_OBJS += src/widget/window.o src/widget/button.o src/widget/frame.o src/widget/menu.o src/widget/submenu.o src/widget/image.o src/widget/scrollbar.o src/widget/checkbox.o src/widget/label.o src/widget/entry.o src/widget/numberentry.o src/widget/viewport.o src/widget/listbox.o -L_OBJS += src/cursor/default.o src/cursor/cross.o src/cursor/text.o +L_OBJS += src/cursor/hidden.o src/cursor/default.o src/cursor/cross.o src/cursor/text.o L_OBJS += src/icon/question.o src/icon/warning.o src/icon/note.o src/icon/info.o src/icon/news.o src/icon/error.o src/icon/file.o src/icon/directory.o src/icon/back.o src/icon/forward.o src/icon/up.o src/icon/computer.o src/icon/search.o OOL_CXXFLAGS = $(DEPINC) $(CFLAGS) -std=c++98 -fPIC diff --git a/include/Mw/Core.h b/include/Mw/Core.h index c1bcc7b..2ac6711 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -237,6 +237,25 @@ MWDECL void MwForceRender2(MwWidget handle, void* ptr); */ MWDECL void MwAddTickList(MwWidget handle); +/*! + * %brief Focus the widget + * %param handle Widget + */ +MWDECL void MwFocus(MwWidget handle); + +/*! + * %brief Grabs the pointer + * %param handle Widget + * %param toggle Toggle + */ +MWDECL void MwGrabPointer(MwWidget handle, int toggle); + +/*! + * %brief Hides the cursor + * %param handle Widget + */ +MWDECL void MwHideCursor(MwWidget handle); + #ifdef __cplusplus } #endif diff --git a/include/Mw/Cursor.h b/include/Mw/Cursor.h index aec4e24..e64bb4a 100644 --- a/include/Mw/Cursor.h +++ b/include/Mw/Cursor.h @@ -44,6 +44,16 @@ MWDECL MwCursor MwCursorText; */ MWDECL MwCursor MwCursorTextMask; +/*! + * %brief Hidden cursor + */ +MWDECL MwCursor MwCursorHidden; + +/*! + * %brief Hidden cursor mask + */ +MWDECL MwCursor MwCursorHiddenMask; + #ifdef __cplusplus } #endif diff --git a/include/Mw/LowLevel.h b/include/Mw/LowLevel.h index 3722acf..256c6ce 100644 --- a/include/Mw/LowLevel.h +++ b/include/Mw/LowLevel.h @@ -42,7 +42,9 @@ enum MwLLKeyEnum { MwLLKeyLeft, MwLLKeyRight, MwLLKeyUp, - MwLLKeyDown + MwLLKeyDown, + MwLLKeyEnter, + MwLLKeyEscape }; enum MwLLMouseEnum { @@ -67,6 +69,8 @@ struct _MwLLHandler { void (*move)(MwLL handle, void* data); void (*key)(MwLL handle, void* data); void (*key_released)(MwLL handle, void* data); + void (*focus_in)(MwLL handle, void* data); + void (*focus_out)(MwLL handle, void* data); }; #ifdef __cplusplus @@ -117,6 +121,9 @@ MWDECL long MwLLGetTick(void); MWDECL void MwLLSetBackground(MwLL handle, MwLLColor color); +MWDECL void MwLLFocus(MwLL handle); +MWDECL void MwLLGrabPointer(MwLL handle, int toggle); + #ifdef __cplusplus } #endif diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index 4cfd16f..f1ebf8f 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -45,5 +45,7 @@ #define MwNkeyHandler "Ckey" /* int* (MwLLKeyEnum or character code) */ #define MwNkeyReleaseHandler "CkeyRelease" /* same as MwNkeyHandler */ #define MwNcloseHandler "Cclose" /* NULL */ +#define MwNfocusInHandler "CfocusIn" /* NULL */ +#define MwNfocusOutHandler "CfocusOut" /* NULL */ #endif diff --git a/src/backend/gdi.c b/src/backend/gdi.c index 2e6f217..0105a1b 100644 --- a/src/backend/gdi.c +++ b/src/backend/gdi.c @@ -91,7 +91,29 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { p.x = LOWORD(lp); p.y = HIWORD(lp); + if(u->ll->grabbed){ + RECT rc; + + GetClientRect(hWnd, &rc); + p.x -= (rc.right - rc.left) / 2; + p.y -= (rc.bottom - rc.top) / 2; + } + MwLLDispatch(u->ll, move, &p); + + if(u->ll->grabbed && (p.x != 0 || p.y != 0)){ + RECT rc; + POINT p; + + GetClientRect(hWnd, &rc); + + p.x = (rc.right - rc.left) / 2; + p.y = (rc.bottom - rc.top) / 2; + + MapWindowPoints(hWnd, HWND_DESKTOP, &p, 1); + + SetCursorPos(p.x, p.y); + } } else if(msg == WM_SIZE) { MwLLDispatch(u->ll, resize, NULL); } else if(msg == WM_ERASEBKGND) { @@ -108,12 +130,19 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int n = wp; MwLLDispatch(u->ll, key, &n); + }else if(msg == WM_SETFOCUS){ + MwLLDispatch(u->ll, focus_in, NULL); + }else if(msg == WM_KILLFOCUS){ + MwLLDispatch(u->ll, focus_out, NULL); } else if(msg == WM_KEYDOWN || msg == WM_KEYUP) { int n = -1; if(wp == VK_LEFT) n = MwLLKeyLeft; if(wp == VK_RIGHT) n = MwLLKeyRight; if(wp == VK_UP) n = MwLLKeyUp; if(wp == VK_DOWN) n = MwLLKeyDown; + if(wp == VK_RETURN) n = MwLLKeyEnter; + if(wp == VK_BACK) n = MwLLKeyBackSpace; + if(wp == VK_ESCAPE) n = MwLLKeyEscape; if(n != -1) { if(msg == WM_KEYDOWN) { MwLLDispatch(u->ll, key, &n); @@ -181,6 +210,7 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { RegisterClassEx(&wc); + r->grabbed = 0; r->copy_buffer = 1; r->hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->hWnd, 0, wc.hInstance, NULL); r->hInstance = wc.hInstance; @@ -556,3 +586,36 @@ void MwLLMakeBorderless(MwLL handle, int toggle) { long MwLLGetTick(void) { return GetTickCount(); } + +void MwLLFocus(MwLL handle){ + SetFocus(handle->hWnd); +} + +void MwLLGrabPointer(MwLL handle, int toggle){ + if(toggle){ + POINT p; + RECT rc; + + GetClientRect(handle->hWnd, &rc); + + rc.right -= rc.left; + rc.bottom -= rc.top; + + p.x = (rc.right - rc.left) / 2; + p.y = (rc.bottom - rc.top) / 2; + + MapWindowPoints(handle->hWnd, HWND_DESKTOP, &p, 1); + + handle->grabbed = 1; + + SetFocus(handle->hWnd); + + GetWindowRect(handle->hWnd, &rc); + ClipCursor(&rc); + + SetCursorPos(p.x, p.y); + }else{ + handle->grabbed = 0; + ClipCursor(NULL); + } +} diff --git a/src/backend/gdi.h b/src/backend/gdi.h index c6d11d4..c842f02 100644 --- a/src/backend/gdi.h +++ b/src/backend/gdi.h @@ -30,6 +30,8 @@ struct _MwLL { int copy_buffer; MwLLHandler handler; + + int grabbed; }; struct _MwLLColor { diff --git a/src/backend/x11.c b/src/backend/x11.c index 2fe7401..bfe67cc 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -20,7 +20,7 @@ enum mwm_hints_enum { MWM_FUNC_CLOSE = (1L << 5) }; -static unsigned long mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | KeymapNotify; +static unsigned long mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | KeymapNotify | FocusChangeMask; static void create_pixmap(MwLL handle) { XWindowAttributes attr; @@ -110,6 +110,8 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { r->width = width; r->height = height; + r->grabbed = 0; + r->colormap = DefaultColormap(r->display, XDefaultScreen(r->display)); r->wm_delete = XInternAtom(r->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(r->display, r->window, &r->wm_delete, 1); @@ -284,12 +286,28 @@ void MwLLNextEvent(MwLL handle) { if(ev.xclient.data.l[0] == (long)handle->wm_delete) { MwLLDispatch(handle, close, NULL); } + } else if(ev.type == FocusIn){ + MwLLDispatch(handle, focus_in, NULL); + } else if(ev.type == FocusOut){ + MwLLDispatch(handle, focus_out, NULL); } else if(ev.type == MotionNotify) { MwPoint p; + XWindowAttributes attr; + + XGetWindowAttributes(handle->display, handle->window, &attr); + p.x = ev.xmotion.x; p.y = ev.xmotion.y; + if(handle->grabbed){ + p.x -= attr.width / 2; + p.y -= attr.height / 2; + } + MwLLDispatch(handle, move, &p); + if(handle->grabbed && (p.x != 0 || p.y != 0)){ + XWarpPointer(handle->display, None, handle->window, 0, 0, 0, 0, attr.width / 2, attr.height / 2); + } } else if(ev.type == KeyPress || ev.type == KeyRelease) { int n = -1; char str[512]; @@ -325,6 +343,10 @@ void MwLLNextEvent(MwLL handle) { n = MwLLKeyUp; } else if(strcmp(str, "Down") == 0) { n = MwLLKeyDown; + } else if(strcmp(str, "Return") == 0){ + n = MwLLKeyEnter; + } else if(strcmp(str, "Escape") == 0){ + n = MwLLKeyEscape; } if(n != -1) { @@ -663,3 +685,21 @@ long MwLLGetTick(void) { return n; } + +void MwLLFocus(MwLL handle){ + XSetInputFocus(handle->display, handle->window, RevertToNone, CurrentTime); +} + +void MwLLGrabPointer(MwLL handle, int toggle){ + XWindowAttributes attr; + + XGetWindowAttributes(handle->display, handle->window, &attr); + + if(toggle){ + handle->grabbed = 1; + + XWarpPointer(handle->display, None, handle->window, 0, 0, 0, 0, attr.width / 2, attr.height / 2); + }else{ + handle->grabbed = 0; + } +} diff --git a/src/backend/x11.h b/src/backend/x11.h index 8fe9f5f..2d12a53 100644 --- a/src/backend/x11.h +++ b/src/backend/x11.h @@ -29,6 +29,8 @@ struct _MwLL { unsigned int height; MwLLHandler handler; + + int grabbed; }; struct _MwLLColor { diff --git a/src/core.c b/src/core.c index 1271ab4..434073b 100644 --- a/src/core.c +++ b/src/core.c @@ -90,6 +90,18 @@ static void llkeyrelhandler(MwLL handle, void* data) { MwDispatchUserHandler(h, MwNkeyReleaseHandler, data); } +static void llfocusinhandler(MwLL handle, void* data) { + MwWidget h = (MwWidget)handle->user; + + MwDispatchUserHandler(h, MwNfocusInHandler, data); +} + +static void llfocusouthandler(MwLL handle, void* data) { + MwWidget h = (MwWidget)handle->user; + + MwDispatchUserHandler(h, MwNfocusOutHandler, data); +} + 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)); @@ -127,6 +139,8 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, h->lowlevel->handler->move = llmovehandler; h->lowlevel->handler->key = llkeyhandler; h->lowlevel->handler->key_released = llkeyrelhandler; + h->lowlevel->handler->focus_in = llfocusinhandler; + h->lowlevel->handler->focus_out = llfocusouthandler; } if(parent != NULL) arrput(parent->children, h); @@ -400,6 +414,10 @@ void MwSetDefault(MwWidget handle) { inherit_text(handle, MwNforeground, MwDefaultForeground); } +void MwHideCursor(MwWidget handle){ + MwLLSetCursor(handle->lowlevel, &MwCursorHidden, &MwCursorHiddenMask); +} + void MwDispatchUserHandler(MwWidget handle, const char* key, void* handler_data) { int ind = shgeti(handle->handler, key); if(ind == -1) return; @@ -459,3 +477,11 @@ void MwAddTickList(MwWidget handle) { arrput(root->tick_list, handle); } + +void MwFocus(MwWidget handle){ + MwLLFocus(handle->lowlevel); +} + +void MwGrabPointer(MwWidget handle, int toggle){ + MwLLGrabPointer(handle->lowlevel, toggle); +} diff --git a/src/cursor/hidden.c b/src/cursor/hidden.c new file mode 100644 index 0000000..1dd4e2a --- /dev/null +++ b/src/cursor/hidden.c @@ -0,0 +1,40 @@ +/* $Id$ */ +#include +MwCursor MwCursorHidden = { + 1, 1, 0, -1, { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }}; +MwCursor MwCursorHiddenMask = { + 1, 1, 0, -1, { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }};