38void SetClientSize(HWND hwnd,
int clientWidth,
int clientHeight);
40LRESULT CALLBACK
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
41LRESULT
onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam );
51 DWORD err = GetLastError();
52 size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
53 |FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
54 NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
55 (LPSTR)&msg, 0, NULL);
57 debug_print(
"%s%s:ERR=%8.8lx (%ld): %s\n",prefix?prefix:
"",prefix2?prefix2:
"",err,err,msg);
60 DWORD fmt_err = GetLastError();
61 debug_print(
"%s%s:ERROR:FormatMessage for ERR=%8.8lx (%ld) returned %8.8lx (%ld)\n",
62 (prefix ? prefix :
""), (prefix2 ? prefix2 :
""), err, err, fmt_err, fmt_err);
71char *
convert_cp(DWORD cp_from, DWORD cp_to,
char *s_from) {
73 int flags = MB_PRECOMPOSED;
75 size_t size = MultiByteToWideChar(cp_from, flags, s_from, -1, NULL, 0);
78 wchar_t *pwc= (
wchar_t*)malloc(size*2);
79 size_t size_wc = MultiByteToWideChar(cp_from, flags, s_from, -1, pwc, size);
83 size = WideCharToMultiByte(cp_to, flags, pwc, size_wc, NULL, 0, NULL, NULL);
86 s_to = (
char*)malloc(size+1);
87 memset(s_to, 0 , size+1);
88 size = WideCharToMultiByte(cp_to, flags, pwc, size_wc, s_to, size, NULL, NULL);
105 return (
convert_cp(GetACP(), CP_UTF8, localestr));
110 return (
convert_cp(CP_UTF8, GetACP(), utf8str));
125 if (w && (IsWindow(w->
widget))) {
129 debug_print(
"os_destroy_window:DestroyWindow:NOTFOUND:hwnd=%p\n",(w)?w->
widget:NULL);
134 if (flag &
IS_WIDGET)
return HWND_DESKTOP;
135 else return (HWND)-1;
139 int from_x,
int from_y,
int *to_x,
int *to_y) {
140 POINT Point = {from_x, from_y};
141 MapWindowPoints(from_window, to_window, &Point, 1);
152 if (GetWindowRect(w_->
widget, &WindowRect) \
153 && GetClientRect(w_->
widget, &ClientRect)) {
154 Point.x = WindowRect.left;
155 Point.y = WindowRect.top;
156 ScreenToClient(parent->
widget, &Point);
157 metrics->
x = Point.x;
158 metrics->
y = Point.y;
159 metrics->
width = ClientRect.right - ClientRect.left;
160 metrics->
height = ClientRect.bottom - ClientRect.top;
167 int base_width,
int base_height) {
173 SetWindowPos(w->
widget, NULL,
174 x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
178 SetWindowPos(w->
widget, NULL,
179 0, 0, x, y, SWP_NOMOVE|SWP_NOZORDER);
183 *width = cairo_image_surface_get_width(surface);
184 *height = cairo_image_surface_get_height(surface);
189 cairo_destroy(w->
cr);
190 cairo_surface_destroy(w->
surface);
191 w->
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
196 int x,
int y,
int width,
int height) {
202 WNDCLASS wndclass = {0};
203 HINSTANCE hInstance = NULL;
209 w->
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
211 wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
212 wndclass.lpfnWndProc =
WndProc;
213 wndclass.hInstance = hInstance;
214 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
215 wndclass.hbrBackground = NULL;
217 wndclass.cbWndExtra =
sizeof(w);
218 RegisterClass(&wndclass);
231 if (win == (HWND)-1) {
233 dwStyle = WS_OVERLAPPEDWINDOW;
234 dwExStyle = WS_EX_CONTROLPARENT | WS_EX_ACCEPTFILES;
240 Rect.bottom = height;
241 if (AdjustWindowRectEx(&Rect, dwStyle, bMenu, dwExStyle)) {
242 width = Rect.right - Rect.left;
243 height = Rect.bottom - Rect.top;
246 if (win == HWND_DESKTOP) {
249 dwExStyle = WS_EX_TOPMOST | WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW;
253 dwExStyle = WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW;
258 TEXT(
"Draw Surface"),
260 CW_USEDEFAULT, CW_USEDEFAULT,
263 NULL, hInstance, (LPVOID)w);
264 SetParent(w->
widget, win);
271 int x,
int y,
int width,
int height) {
277 WNDCLASS wndclass = {0};
278 HINSTANCE hInstance = NULL;
281 w->
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
283 wndclass.style = CS_DBLCLKS;
284 wndclass.lpfnWndProc =
WndProc;
285 wndclass.hInstance = hInstance;
286 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
287 wndclass.hbrBackground = NULL;
289 wndclass.cbWndExtra =
sizeof(w);
290 RegisterClass(&wndclass);
292 DWORD dwExStyle = WS_EX_CONTROLPARENT;
294 TEXT(
"Draw Surface"),
299 NULL, hInstance, (LPVOID)w);
307 SetWindowText(w->
widget, title);
311 ShowWindow(w->
widget, SW_SHOW);
315 ShowWindow(w->
widget, SW_HIDE);
320 if (GetCursorPos(&pt)) {
321 SetWindowPos(w->
widget, NULL,
322 pt.x+10, pt.y-10, 0, 0,
323 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_SHOWWINDOW);
328 RedrawWindow(w->
widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW);
369 return GetSystemMetrics(SM_CYSCREEN);
373 return GetSystemMetrics(SM_CXSCREEN);
378 asprintf(&pPath,
"%s%s", getenv(
"HOMEDRIVE"), getenv(
"HOMEPATH"));
379 assert(pPath != NULL);
380 fprintf(stderr,
"%s\n", pPath);
385 DWORD attribs = GetFileAttributes(filename);
386 return ((attribs != INVALID_FILE_ATTRIBUTES) &&
387 ((attribs & FILE_ATTRIBUTE_DIRECTORY) != 0) &&
388 ((attribs & FILE_ATTRIBUTE_HIDDEN) == 0) &&
389 ((attribs & FILE_ATTRIBUTE_SYSTEM) == 0));
395 RedrawWindow(w->
widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
401 RedrawWindow(w->
widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
406 ansibuf[0] = (char)key->
vk;
409 int l=min(bufsize, strlen(utf8));
410 strncpy(buf, utf8, l);
424 SendMessage(w->
widget, msg, wParam, 0);
441 WPARAM wParam = (WPARAM)w->
widget;
443 SendMessage(w->
widget, msg, wParam, 0);
447 Atom msg = WM_USER + 01;
453 Atom msg = WM_USER + 02 ;
461 while( main->
run && (bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
465 TranslateMessage(&msg);
466 DispatchMessage(&msg);
488 UINT uVirtKey = (UINT)wParam;
489 UINT uScanCode = (UINT)(HIWORD(lParam) & 0x1FF);
490 BYTE lpKeyState[256];
491 if (GetKeyboardState(lpKeyState)) {
496 if (msg == WM_CHAR) {
500 ToUnicode(uVirtKey, uScanCode, lpKeyState, lpChar, 2, uFlags);
507 case 0x0029: ev->
keycode = XK_dead_circumflex;
break;
508 case 0x000e: ev->
keycode = XK_BackSpace;
break;
509 case 0x000f: ev->
keycode = XK_Tab;
break;
510 case 0x001c: ev->
keycode = XK_Return;
break;
511 case 0x0147: ev->
keycode = XK_Home;
break;
512 case 0x014b: ev->
keycode = XK_Left;
break;
513 case 0x0148: ev->
keycode = XK_Up;
break;
514 case 0x014d: ev->
keycode = XK_Right;
break;
515 case 0x0150: ev->
keycode = XK_Down;
break;
516 case 0x014f: ev->
keycode = XK_End;
break;
517 case 0x0152: ev->
keycode = XK_Insert;
break;
518 case 0x011c: ev->
keycode = XK_KP_Enter;
break;
519 case 0x0047: ev->
keycode = XK_KP_Home;
break;
520 case 0x004b: ev->
keycode = XK_KP_Left;
break;
521 case 0x0048: ev->
keycode = XK_KP_Up;
break;
522 case 0x004d: ev->
keycode = XK_KP_Right;
break;
523 case 0x0050: ev->
keycode = XK_KP_Down;
break;
524 case 0x004f: ev->
keycode = XK_KP_End;
break;
525 case 0x0052: ev->
keycode = XK_KP_Insert;
break;
526 case 0x004e: ev->
keycode = XK_KP_Add;
break;
527 case 0x004a: ev->
keycode = XK_KP_Subtract;
break;
531 else if (ev->
vk == 0xdc)
532 ev->
keycode = XK_dead_diaeresis;
541 TCHAR szName[MAX_PATH];
544 HDROP hDrop = (HDROP)wParam;
546 int count = DragQueryFile(hDrop, 0xFFFFFFFF, szName, MAX_PATH);
549 for(
int i = 0; i < count; i++) {
550 DragQueryFile(hDrop, i, szName, MAX_PATH);
562LRESULT CALLBACK
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
568 void *user_data = NULL;
572 Xputty *main = wid ? wid-> app : NULL;
575 xbutton.
x = GET_X_LPARAM(lParam);
576 xbutton.
y = GET_Y_LPARAM(lParam);
578 xmotion.
x = GET_X_LPARAM(lParam);
579 xmotion.
y = GET_Y_LPARAM(lParam);
583 debug_print(
"WM:WM_CREATE:hwnd=%p:wid=%p",hwnd,wid);
585 CREATESTRUCT *pCreate = (CREATESTRUCT *)lParam;
586 wid = (
Widget_t *)pCreate->lpCreateParams;
590 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wid);
604 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
609 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
621 int width = LOWORD(lParam);
622 int height = HIWORD(lParam);
623 if ((width < wid->metrics_min.width)
624 || (height < wid->metrics_min.height)) {
638 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
645 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
647 debug_print(
"WM_PAINT:BAILOUT:wid->crb==NULL\n");
650 return onPaint(hwnd, wParam, lParam);
656 case WM_MOUSEACTIVATE:
663 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
666 if (msg == WM_LBUTTONDOWN)
670 if (wid->
state == 4)
break;
673 debug_print(
"Widget_t ButtonPress %i\n", xbutton.
button);
676 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
679 DWORD pos = GetMessagePos();
680 pt.x = GET_X_LPARAM(pos);
681 pt.y = GET_Y_LPARAM(pos);
682 if (ScreenToClient(hwnd, &pt)) {
687 if (GET_WHEEL_DELTA_WPARAM(wParam) <= 0) {
698 if (hwnd != view_port->
widget)
699 SendMessage(view_port->
widget, msg, wParam, lParam);
700 RedrawWindow(view_port->
widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW);
704 case WM_LBUTTONDBLCLK:
705 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
712 if (msg == WM_LBUTTONUP)
718 if (wid->
state == 4)
break;
724 debug_print(
"Widget_t ButtonRelease %i\n", xbutton.
button);
738 if (msg != WM_KEYUP) {
739 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
740 if (wid->state == 4)
return 0;
742 unsigned short is_retriggered = 0;
744 if ((HIWORD(lParam) & KF_REPEAT) == KF_REPEAT)
747 if (!is_retriggered) {
749 wid->func.key_press_callback((
void *)wid, &xkey, user_data);
750 debug_print(
"Widget_t KeyPress %x\n", xkey.
keycode);
754 if (msg != WM_KEYDOWN) {
755 if (wid->state == 4)
return 0;
758 wid->func.key_release_callback((
void *)wid, &xkey, user_data);
759 debug_print(
"Widget_t KeyRelease %x\n", xkey.
keycode);
765 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
768 bool is_item =
false;
770 Window win_cur = WindowFromPoint(pt);
771 if(wid->app->submenu != NULL) {
774 if (win_cur == slider->
widget) {
781 if (win_cur == w->
widget) {
788 if(wid->app->hold_grab != NULL && wid->app->hold_grab->flags &
IS_POPUP) {
791 if (win_cur == slider->
widget) {
798 if (win_cur == w->
widget) {
803 if (win_cur == view_port->
widget) is_item = True;
805 if (!is_item && (wParam & MK_LBUTTON || wParam & MK_RBUTTON)) {
808 wid->app->hold_grab = NULL;
810 }
else if(wid->app->hold_grab != NULL && ((wid->app->hold_grab->flags &
IS_POPUP) == 0)) {
811 wid->app->hold_grab->func.button_press_callback(wid->app->hold_grab, &xbutton, NULL);
855 wid->mouse_inside =
false;
857 if (wid->state == 4)
break;
859 if (!(GetAsyncKeyState(VK_LBUTTON) & 0x8000)) {
861 wid->flags &= ~HAS_FOCUS;
862 wid->func.leave_callback((
void*)wid, user_data);
867 debug_print(
"Widget_t LeaveNotify:hwnd=%p",hwnd);
873 if (!wid)
return DefWindowProc(hwnd, msg, wParam, lParam);
874 if (!wid->mouse_inside) {
891 wid->mouse_inside =
true;
893 if (wid->state == 4)
break;
896 if (!(wParam & MK_LBUTTON)) {
898 wid->func.enter_callback((
void*)wid, user_data);
904 debug_print(
"Widget_t EnterNotify:hwnd=%p",hwnd);
909 if (wid->state == 4)
return 0;
910 if (wParam & MK_LBUTTON)
912 wid->func.motion_callback((
void*)wid, &xmotion, user_data);
913 debug_print(
"Widget_t MotionNotify x = %li Y = %li hwnd=%p\n",pt.x,pt.y,hwnd );
956 return DefWindowProc(hwnd, msg, wParam, lParam);
961LRESULT
onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
976 HDC hdc = BeginPaint(hwnd, &ps );
979 cairo_surface_t *surface = cairo_win32_surface_create (hdc);
980 cairo_t *cr = cairo_create (surface);
982 cairo_set_source_surface(cr, w->
surface, 0.0, 0.0);
987 cairo_surface_destroy (surface);
989 EndPaint( hwnd, &ps );
997 if (IsWindow(hwnd)) {
998 DWORD dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE) ;
999 DWORD dwExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE) ;
1000 HMENU menu = GetMenu(hwnd) ;
1001 RECT rc = {0, 0, clientWidth, clientHeight} ;
1002 AdjustWindowRectEx(&rc, dwStyle, menu ? TRUE : FALSE, dwExStyle);
1003 SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
1004 SWP_NOZORDER | SWP_NOMOVE) ;
1010 TRACKMOUSEEVENT tme;
1012 tme.cbSize =
sizeof(tme);
1013 tme.dwFlags = TME_LEAVE;
1015 tme.dwFlags |= TME_CANCEL;
1016 tme.hwndTrack = hwnd;
1017 tme.dwHoverTime = HOVER_DEFAULT;
1018 return TrackMouseEvent(&tme);
evfunc button_release_callback
xevfunc configure_callback
evfunc double_click_callback
xevfunc dnd_notify_callback
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
Xputty - the main struct. It should be declared before any other call to a Xputty function....
void adj_set_motion_state(void *w, float x, float y)
adj_set_motion_state - internal use to set value and state of the Adjustment_t on mouse pointer movme...
Multiplatform implementation of asprintf() from: https://stackoverflow.com/questions/40159892/using-a...
int asprintf(char *strp[], const char *fmt,...)
void childlist_add_child(Childlist_t *childlist, Widget_t *child)
childlist_add_child - internal use to add a child to the Childlist_t You usually didn't need to cal...
int childlist_find_widget(Childlist_t *childlist, Window child_window)
childlist_find_widget - find a child Widget_t in a the childlist by given the Window id
int childlist_has_child(Childlist_t *childlist)
childlist_has_child - check if a Widget_t Childlist_t contain a child