libxputty 0.1
Loading...
Searching...
No Matches
xwidget-mswin.c
Go to the documentation of this file.
1/* vim:ts=4:sw=4:et:
2 *
3 * 0BSD
4 *
5 * BSD Zero Clause License
6 *
7 * Copyright (c) 2019 Hermann Meyer
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted.
11
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
13 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
15 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18 * PERFORMANCE OF THIS SOFTWARE.
19 *
20 */
21
22#ifdef _WIN32 //PlatformWrappers
23
24#include <windowsx.h>
25
26#include "xwidget.h"
27#include "xwidget_private.h"
28#include "xasprintf.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34TCHAR szMainUIClassName[] = TEXT("xputtyMainUI____0123456789ABCDEF");
35TCHAR szWidgetUIClassName[] = TEXT("xputtyWidgetUI__0123456789ABCDEF");
36
37// forward declarations
38void SetClientSize(HWND hwnd, int clientWidth, int clientHeight);
39BOOL SetMouseTracking(HWND hwnd, BOOL enable);
40LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
41LRESULT onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam );
42
43/*---------------------------------------------------------------------
44-----------------------------------------------------------------------
45 internal helper functions
46-----------------------------------------------------------------------
47----------------------------------------------------------------------*/
48
49void debug_lasterror(const char *prefix, const char *prefix2) {
50 LPSTR msg = NULL;
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);
56 if (size) {
57 debug_print("%s%s:ERR=%8.8lx (%ld): %s\n",prefix?prefix:"",prefix2?prefix2:"",err,err,msg);
58 LocalFree(msg);
59 } else {
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);
63 }
64}
65
66/*---------------------------------------------------------------------
67 codepage conversion
68----------------------------------------------------------------------*/
69
70// general codepage conversion
71char *convert_cp(DWORD cp_from, DWORD cp_to, char *s_from) {
72 char *s_to = NULL;
73 int flags = MB_PRECOMPOSED; // | MB_ERR_INVALID_CHARS;
74 // prepare conversion to WideChar (using cp_from) - get required space
75 size_t size = MultiByteToWideChar(cp_from, flags, s_from, -1, NULL, 0);
76 if (size) {
77 // convert Ansi to WideChar (pwc)
78 wchar_t *pwc= (wchar_t*)malloc(size*2);
79 size_t size_wc = MultiByteToWideChar(cp_from, flags, s_from, -1, pwc, size);
80 if (size_wc) {
81 // prepare conversion to cp_to - get required space
82 flags = 0;
83 size = WideCharToMultiByte(cp_to, flags, pwc, size_wc, NULL, 0, NULL, NULL);
84 if (size) {
85 // convert WideChar (pwc) to Ansi using cp_to
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);
89 }
90 }
91 free(pwc);
92 }
93 // needs to be free()d by caller
94 return s_to;
95}
96
97/*---------------------------------------------------------------------
98-----------------------------------------------------------------------
99 common functions (required)
100-----------------------------------------------------------------------
101----------------------------------------------------------------------*/
102
103// convert active codepage to utf8
104char *utf8_from_locale(char *localestr) {
105 return (convert_cp(GetACP(), CP_UTF8, localestr));
106}
107
108// convert utf8 to active codepage
109char *locale_from_utf8(char *utf8str) {
110 return (convert_cp(CP_UTF8, GetACP(), utf8str));
111}
112
113Display *os_open_display(char *display_name) {
114 // nothing to do on MSWin
115 return (Display *)1;
116}
117
119 // nothing to do on MSWin
120}
121
123 // mswin automatically sends WM_DESTROY to all child windows
124 // floating windows need to be handled manually
125 if (w && (IsWindow(w->widget))) {
126 //debug_print("os_destroy_window:DestroyWindow:hwnd=%p\n",(w)?w->widget:NULL);
127 DestroyWindow(w->widget);
128 } else {
129 debug_print("os_destroy_window:DestroyWindow:NOTFOUND:hwnd=%p\n",(w)?w->widget:NULL);
130 }
131}
132
134 if (flag & IS_WIDGET) return HWND_DESKTOP; // no decorated
135 else return (HWND)-1; // decorated
136}
137
138void os_translate_coords(Widget_t *w, Window from_window, Window to_window,
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);
142 *to_x = Point.x;
143 *to_y = Point.y;
144}
145
147 RECT WindowRect;
148 RECT ClientRect;
149 POINT Point;
150 Widget_t *parent = (Widget_t *)w_->parent;
151
152 if (GetWindowRect(w_->widget, &WindowRect) \
153 && GetClientRect(w_->widget, &ClientRect)) {
154 Point.x = WindowRect.left; // WindowRect has correct coords, but wrong width/height
155 Point.y = WindowRect.top; // ClientRect has correct width/height, but top/left == 0
156 ScreenToClient(parent->widget, &Point); // "parent" is intentional (coords are relative to owner widget)
157 metrics->x = Point.x;
158 metrics->y = Point.y;
159 metrics->width = ClientRect.right - ClientRect.left;
160 metrics->height = ClientRect.bottom - ClientRect.top;
161 }
162 metrics->visible = IsWindowVisible(w_->widget);
163}
164
165// values are checked on WM_SIZE
166void os_set_window_min_size(Widget_t *w, int min_width, int min_height,
167 int base_width, int base_height) {
168 w->metrics_min.width = min_width;
169 w->metrics_min.height = min_height;
170}
171
172void os_move_window(Display *dpy, Widget_t *w, int x, int y) {
173 SetWindowPos(w->widget, NULL, //hWnd, hWndInsertAfter
174 x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER); //X, Y, width, height, uFlags
175}
176
177void os_resize_window(Display *dpy, Widget_t *w, int x, int y) {
178 SetWindowPos(w->widget, NULL, //hWnd, hWndInsertAfter
179 0, 0, x, y, SWP_NOMOVE|SWP_NOZORDER); //X, Y, width, height, uFlags
180}
181
182void os_get_surface_size(cairo_surface_t *surface, int *width, int *height) {
183 *width = cairo_image_surface_get_width(surface);
184 *height = cairo_image_surface_get_height(surface);
185}
186
187void os_set_widget_surface_size(Widget_t *w, int width, int height) {
188 // image_surface cant be resized (only xlib_surface can)
189 cairo_destroy(w->cr);
190 cairo_surface_destroy(w->surface);
191 w->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
192 w->cr = cairo_create(w->surface);
193}
194
196 int x, int y, int width, int height) {
197 // Event callbacks already start during CreateWindow(),
198 // so prepare childlist before that call on MSWin
199 // (on Linux, adding to childlist starts message events)
201 // prepare window class
202 WNDCLASS wndclass = {0};
203 HINSTANCE hInstance = NULL;
204
205 snprintf(szMainUIClassName+16, 16, "%p", WndProc);
206 snprintf(szWidgetUIClassName+16, 16, "%p", WndProc);
207
208 // create a permanent surface for drawing (see onPaint() event)
209 w->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
210
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;
216 wndclass.lpszClassName = szMainUIClassName;
217 wndclass.cbWndExtra = sizeof(w); // reserve space for SetWindowLongPtr
218 RegisterClass(&wndclass);
219 // TODO: pass window style (mainwindow,childwidget,popup,...) to create_window()
220 // _WIN32 doesnt allow changing the style afterwards, as it is done in xmenu.cpp
221 // (this also removes duplicate code for window/widget creation).
222 // For the current situation it is sufficient to set popup style if parent is HWND_DESKTOP.
223 DWORD dwStyle = 0;
224 DWORD dwExStyle = 0;
225 // dwExStyle:
226 // WS_EX_APPWINDOW - force(!) taskbar icon
227 // WS_EX_CONTROLPARENT - contains children, uses tab+cursor nav.
228 // WS_EX_NOPARENTNOTIFY - no PARENTNOTIFY on create/destroy
229 // WS_EX_TOOLWINDOW - no taskbar icon
230 // WS_EX_TOPMOST - above all others
231 if (win == (HWND)-1) {
232 // Dialogs with border
233 dwStyle = WS_OVERLAPPEDWINDOW;
234 dwExStyle = WS_EX_CONTROLPARENT | WS_EX_ACCEPTFILES;
235 win = HWND_DESKTOP;
236 // include border widths
237 RECT Rect = {0};
238 BOOL bMenu = false;
239 Rect.right = width;
240 Rect.bottom = height;
241 if (AdjustWindowRectEx(&Rect, dwStyle, bMenu, dwExStyle)) {
242 width = Rect.right - Rect.left;
243 height = Rect.bottom - Rect.top;
244 }
245 } else {
246 if (win == HWND_DESKTOP) {
247 // Floating without border (popup, tooltip)
248 dwStyle = WS_POPUP;
249 dwExStyle = WS_EX_TOPMOST | WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW;
250 } else {
251 // Embedded widget
252 dwStyle = WS_CHILD;
253 dwExStyle = WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW;
254 }
255 }
256 // create the window
257 w->widget = CreateWindowEx(dwExStyle, szMainUIClassName,
258 TEXT("Draw Surface"), // lpWindowName
259 dwStyle, // dwStyle
260 CW_USEDEFAULT, CW_USEDEFAULT, // X, Y
261 width, height, // nWidth, nHeight
262 win, // hWndParent (no embeddeding takes place yet)
263 NULL, hInstance, (LPVOID)w); // hMenu, hInstance, lpParam
264 SetParent(w->widget, win); // embed into parentWindow
265 SetMouseTracking(w->widget, true); // for receiving WM_MOUSELEAVE
266
267 os_set_window_min_size(w, width/2, height/2, width, height);
268}
269
271 int x, int y, int width, int height) {
272 // Event callbacks already start during CreateWindow(),
273 // so prepare childlist before that call on MSWin
274 // (on Linux, adding to childlist starts message events)
276 // prepare window class
277 WNDCLASS wndclass = {0};
278 HINSTANCE hInstance = NULL;
279
280 // create a permanent surface for drawing (see onPaint() event)
281 w->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
282
283 wndclass.style = CS_DBLCLKS;
284 wndclass.lpfnWndProc = WndProc;
285 wndclass.hInstance = hInstance;
286 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
287 wndclass.hbrBackground = NULL;
288 wndclass.lpszClassName = szWidgetUIClassName;
289 wndclass.cbWndExtra = sizeof(w); // reserve space for SetWindowLongPtr
290 RegisterClass(&wndclass);
291 // create the window
292 DWORD dwExStyle = WS_EX_CONTROLPARENT;
293 w->widget = CreateWindowEx(dwExStyle, szWidgetUIClassName,
294 TEXT("Draw Surface"), // lpWindowName
295 WS_CHILD, // dwStyle
296 x, y, // X, Y
297 width, height, // nWidth, nHeight
298 parent->widget, // hWndParent (no embeddeding takes place yet)
299 NULL, hInstance, (LPVOID)w); // hMenu, hInstance, lpParam
300
301 SetParent(w->widget, parent->widget); // embed into parentWindow
302 SetMouseTracking(w->widget, true); // for receiving WM_MOUSELEAVE
303}
304
305void os_set_title(Widget_t *w, const char *title) {
306 if (title)
307 SetWindowText(w->widget, title);
308}
309
311 ShowWindow(w->widget, SW_SHOW);
312}
313
315 ShowWindow(w->widget, SW_HIDE);
316}
317
319 POINT pt;
320 if (GetCursorPos(&pt)) {
321 SetWindowPos(w->widget, NULL, //hWnd, hWndInsertAfter
322 pt.x+10, pt.y-10, 0, 0,
323 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_SHOWWINDOW); //X, Y, width, height, uFlags
324 }
325}
326
328 RedrawWindow(w->widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW);
329}
330
331void os_widget_event_loop(void *w_, void* event, Xputty *main, void* user_data) {
332 // nothing to do
333}
334
335void os_send_configure_event(Widget_t *w,int x, int y, int width, int height) {
336 // STUB
337}
338
340 // STUB
341}
342
344 // STUB
345}
346
348 // STUB
349}
350
352 // STUB
353 return 0;
354}
355
357 // STUB
358}
359
361 // STUB
362}
363
365 // STUB
366}
367
369 return GetSystemMetrics(SM_CYSCREEN);
370}
371
373 return GetSystemMetrics(SM_CXSCREEN);
374}
375
377 char *pPath = NULL;
378 asprintf(&pPath, "%s%s", getenv("HOMEDRIVE"), getenv("HOMEPATH"));
379 assert(pPath != NULL);
380 fprintf(stderr, "%s\n", pPath);
381 return pPath;
382}
383
384bool os_is_directory(const char *filename) {
385 DWORD attribs = GetFileAttributes(filename);
386 return ((attribs != INVALID_FILE_ATTRIBUTES) && // check if a valid file
387 ((attribs & FILE_ATTRIBUTE_DIRECTORY) != 0) && // file is a directory
388 ((attribs & FILE_ATTRIBUTE_HIDDEN) == 0) && // file is not hidden
389 ((attribs & FILE_ATTRIBUTE_SYSTEM) == 0)); // file is not system
390}
391
392void os_transparent_draw(void *w_, void *user_data) {
393 Widget_t *w = (Widget_t *)w_;
394 // transparent_draw(w, user_data);
395 RedrawWindow(w->widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
396}
397
398void os_adjustment_callback(void *w_, void *user_data) {
399 Widget_t *w = (Widget_t *)w_;
400 // transparent_draw(w, user_data);
401 RedrawWindow(w->widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
402}
403
404bool os_get_keyboard_input(Widget_t *w, XKeyEvent *key, char *buf, size_t bufsize) {
405 char ansibuf[2];
406 ansibuf[0] = (char)key->vk;
407 ansibuf[1] = 0;
408 char *utf8 = utf8_from_locale(ansibuf);
409 int l=min(bufsize, strlen(utf8));
410 strncpy(buf, utf8, l);
411 buf[l] = 0;
412 free(utf8);
413 return key->vk_is_final_char; // for only feeding readily processed chars into input widgets
414}
415
417 // Pixmap stuff not implemented at all
418}
419
421 if (w) {
422 WPARAM wParam = (WPARAM)get_toplevel_widget(w->app)->widget;
423 DWORD msg = os_register_wm_delete_window(w);
424 SendMessage(w->widget, msg, wParam, 0); // WM_DELETE_WINDOW
425 }
426 // UnregisterClass silently fails, if there are still more windows of this class
427 if (UnregisterClass(szMainUIClassName, NULL)) {
428 debug_print("UnregisterMainClass:%s:OK\n", szMainUIClassName);
429 } else
430 debug_lasterror("UnregisterMainClass:", szMainUIClassName);
431
432 if (UnregisterClass(szWidgetUIClassName, NULL)) {
433 debug_print("UnregisterWidgetClass:%s:OK\n", szWidgetUIClassName);
434 } else
435 debug_lasterror("UnregisterWidgetClass" ,szWidgetUIClassName);
436
437}
438
440 // who invokes this?
441 WPARAM wParam = (WPARAM)w->widget;
442 DWORD msg = os_register_widget_destroy(w);
443 SendMessage(w->widget, msg, wParam, 0); // WIDGET_DESTROY
444}
445
447 Atom msg = WM_USER + 01;
448 //Atom msg = RegisterWindowMessage("XPUTTY_WM_DELETE_WINDOW");
449 return msg;
450}
451
453 Atom msg = WM_USER + 02 ;
454 //Atom msg = RegisterWindowMessage("XPUTTY_WIDGET_DESTROY");
455 return msg;
456}
457
458void os_main_run(Xputty *main) {
459 MSG msg;
460 BOOL bRet;
461 while( main->run && (bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
462 if (bRet == -1) {
463 return; // error
464 } else {
465 TranslateMessage(&msg);
466 DispatchMessage(&msg);
467 }
468 }
469}
470
472 // messageloop already polled by plugin host
473}
474
475void os_init_dnd(Xputty *main) {
476 // DND not implemented for win32
477}
478
479/*---------------------------------------------------------------------
480-----------------------------------------------------------------------
481 private functions
482-----------------------------------------------------------------------
483----------------------------------------------------------------------*/
484
485/*------------- the event loop ---------------*/
486
487void build_xkey_event(XKeyEvent *ev, UINT msg, WPARAM wParam, LPARAM lParam) {
488 UINT uVirtKey = (UINT)wParam;
489 UINT uScanCode = (UINT)(HIWORD(lParam) & 0x1FF);
490 BYTE lpKeyState[256];
491 if (GetKeyboardState(lpKeyState)) {
492 //https://stackoverflow.com/questions/42667205/maximum-number-of-characters-output-from-win32-tounicode-toascii
493 // required size for the return buffer isn't exactly clear, maybe 255, so 1K should be a safe guess
494 WCHAR lpChar[1024];
495 UINT uFlags = 0x04; // 1=menu is active, 4=dont change anything
496 if (msg == WM_CHAR) {
497 ev->vk = uVirtKey;
498 ev->vk_is_final_char = 1;
499 } else {
500 ToUnicode(uVirtKey, uScanCode, lpKeyState, lpChar, 2, uFlags);
501 ev->vk = lpChar[0];
502 ev->vk_is_final_char = 0;
503 }
504 }
505 // handle special characters (only in KEYUP/DOWN?)
506 switch (uScanCode) {
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;
528 default:
529 if (ev->vk == 0xfc) //'ü'
530 ev->keycode = XK_udiaeresis;
531 else if (ev->vk == 0xdc) //'Ü'
532 ev->keycode = XK_dead_diaeresis;
533 else
534 ev->keycode = ev->vk;
535 }
536}
537
538void HandleFiles(WPARAM wParam, Widget_t * wid)
539{
540 // DragQueryFile() takes a LPWSTR for the name so we need a TCHAR string
541 TCHAR szName[MAX_PATH];
542
543 // Here we cast the wParam as a HDROP handle to pass into the next functions
544 HDROP hDrop = (HDROP)wParam;
545
546 int count = DragQueryFile(hDrop, 0xFFFFFFFF, szName, MAX_PATH);
547
548 // Here we go through all the files that were drag and dropped then display them
549 for(int i = 0; i < count; i++) {
550 DragQueryFile(hDrop, i, szName, MAX_PATH);
551
552 // Bring up a message box that displays the current file being processed
553 // MessageBox(GetForegroundWindow(), szName, "Current file received", MB_OK);
554 char *dndfile = utf8_from_locale(szName);
555 wid->func.dnd_notify_callback(wid, (void*)&dndfile);
556 free(dndfile);
557 }
558
559 DragFinish(hDrop);
560}
561
562LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
563{
564 POINT pt;
565 XButtonEvent xbutton;
566 XMotionEvent xmotion;
567 XKeyEvent xkey;
568 void *user_data = NULL;
569
570 // be aware: "wid" can be NULL during window creation (esp. if there is a debugger attached)
571 Widget_t *wid = (Widget_t *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
572 Xputty *main = wid ? wid-> app : NULL;
573
574 xbutton.window = hwnd;
575 xbutton.x = GET_X_LPARAM(lParam);
576 xbutton.y = GET_Y_LPARAM(lParam);
577 xmotion.window = hwnd;
578 xmotion.x = GET_X_LPARAM(lParam);
579 xmotion.y = GET_Y_LPARAM(lParam);
580
581 switch (msg) {
582 case WM_CREATE:
583 debug_print("WM:WM_CREATE:hwnd=%p:wid=%p",hwnd,wid);
584 {
585 CREATESTRUCT *pCreate = (CREATESTRUCT *)lParam;
586 wid = (Widget_t *)pCreate->lpCreateParams;
587 // CreateWindowEx() hasnt returned yet, so wid->widget is not set
588 wid->widget = hwnd;
589 // make "wid" available in messageloop events via GetWindowLongPtr()
590 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wid);
591 }
592 return 0;
593
594 // MSWin only: React to close requests
595 case WM_CLOSE:
596 // standalone
597 if (hwnd == main->childlist->childs[0]->widget) {
598 // is main window: end application
599 PostQuitMessage(0); // end messageloop (continuing to main_quit())
600 } else // is sub window (menu, dialog, ...): close
601 DestroyWindow(hwnd);
602 return 0;
603 case WM_DESTROY:
604 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
605 return 0;
606
607 // X11:ConfigureNotify
608 case WM_SIZE:
609 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
610 else {
611 if(wid->app->hold_grab && wid != wid->app->hold_grab) {
613 wid->app->hold_grab = NULL;
614 }
615 // Limit window size:
616 // The plugin doesnt receive WM_MINMAXINFO or WM_SIZING.
617 // SWP_NOSIZE in WM_WINDOWPOSCHANGING cant handle width/height separately.
618 // Setting the client size afterwards turned out to be the best working option so far.
619 // Plugin: Limits the "zoom" (as the hosts window can always become smaller)
620 // Standalone: Limits the window size
621 int width = LOWORD(lParam);
622 int height = HIWORD(lParam);
623 if ((width < wid->metrics_min.width)
624 || (height < wid->metrics_min.height)) {
625 SetClientSize(hwnd, max(width, wid->metrics_min.width),
626 max(height, wid->metrics_min.height));
627 return 0;
628 }
629 // Resize handler
630 if (!wid->func.configure_callback) return 0;
631 wid->func.configure_callback(wid, user_data);
632 // widgets recive the call to os_transparent_draw via the configure_notify_callback
633 // windows have the CS_HREDRAW | CS_VREDRAW flags set so that they be redrawn by the system
634 return 0;
635 }
636
637 case WM_MOVE:
638 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
639 if(wid->app->hold_grab && wid != wid->app->hold_grab) {
641 wid->app->hold_grab = NULL;
642 }
643 // X11:Expose
644 case WM_PAINT:
645 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
646 if (!(wid->crb)) {
647 debug_print("WM_PAINT:BAILOUT:wid->crb==NULL\n");
648 return 0;
649 }
650 return onPaint(hwnd, wParam, lParam); // not possible on mswin: (only fetch the last expose event)
651
652 // MSWin only: Allow keyboard input
653 case WM_ACTIVATE:
654 SetFocus(hwnd);
655 return 0;
656 case WM_MOUSEACTIVATE:
657 SetFocus(hwnd);
658 return MA_ACTIVATE;
659
660 // X11:ButtonPress
661 case WM_LBUTTONDOWN:
662 case WM_RBUTTONDOWN:
663 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
664 SetCapture(hwnd); // also receive WM_MOUSEMOVE from outside this window
665
666 if (msg == WM_LBUTTONDOWN)
667 xbutton.button = Button1;
668 else
669 xbutton.button = Button3;
670 if (wid->state == 4) break;
671 if (wid->flags & HAS_TOOLTIP) hide_tooltip(wid);
672 _button_press(wid, &xbutton, user_data);
673 debug_print("Widget_t ButtonPress %i\n", xbutton.button);
674 return 0;
675 case WM_MOUSEWHEEL:
676 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
677 // opposed to X11, WM_MOUSEWHEEL doesnt contain mouse coordinates
678 {
679 DWORD pos = GetMessagePos();
680 pt.x = GET_X_LPARAM(pos);
681 pt.y = GET_Y_LPARAM(pos);
682 if (ScreenToClient(hwnd, &pt)) {
683 wid->pos_x = pt.x;
684 wid->pos_y = pt.y;
685 }
686 }
687 if (GET_WHEEL_DELTA_WPARAM(wParam) <= 0) {
688 xbutton.button = Button5;
689 _button_press(wid, &xbutton, user_data);
690 } else {
691 xbutton.button = Button4;
692 _button_press(wid, &xbutton, user_data);
693 }
694 // forward WM_MOUSEWHEEL from menuitem to viewport (with slider)
695 // (viewport lies below menuitem, so doesnt receive WM_MOUSEWHEEL)
696 if(wid->app->hold_grab) {
697 Widget_t *view_port = wid->app->hold_grab->childlist->childs[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);
701 }
702 return 0;
703 // X11:ButtonRelease
704 case WM_LBUTTONDBLCLK:
705 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
706 xbutton.button = Button1;
707 wid->func.double_click_callback(wid, &xbutton, user_data);
708 return 0;
709 case WM_LBUTTONUP:
710 case WM_RBUTTONUP:
711 ReleaseCapture();
712 if (msg == WM_LBUTTONUP)
713 xbutton.button = Button1;
714 else
715 xbutton.button = Button3;
716 _check_grab(wid, &xbutton, wid->app);
717 _check_submenu(wid, &xbutton, main);
718 if (wid->state == 4) break;
719 _has_pointer(wid, &xbutton);
720 if(wid->flags & HAS_POINTER) wid->state = 1;
721 else wid->state = 0;
722 _check_enum(wid, &xbutton);
723 wid->func.button_release_callback((void*)wid, &xbutton, user_data);
724 debug_print("Widget_t ButtonRelease %i\n", xbutton.button);
725 return 0;
726
727 // X11:KeyPress and X11:KeyRelease
728 // The resulting character (e.g. from dead-key combinations) cannot be
729 // determined from WM_KEYUP or WM_KEYDOWN: WM_CHAR has to be used instead.
730 // To workaround that, WM_CHAR fires key_press- and key_release_event()
731 // after another, with the flag "->vk_is_final_char" set, so the client
732 // code can differentiate between real KEYUP/DOWN and fake CHAR events.
733 case WM_CHAR:
734 case WM_KEYDOWN:
735 case WM_KEYUP:
736 build_xkey_event(&xkey, msg, wParam, lParam);
737 // X11:KeyPress
738 if (msg != WM_KEYUP) { // WM_KEYDOWN and WM_CHAR: key_press_callback()
739 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
740 if (wid->state == 4) return 0;
741 // on Linux, retrigger check happens in KeyRelease (WM_KEYUP)
742 unsigned short is_retriggered = 0;
743 if(wid->flags & NO_AUTOREPEAT) {
744 if ((HIWORD(lParam) & KF_REPEAT) == KF_REPEAT)
745 is_retriggered = 1;
746 }
747 if (!is_retriggered) {
748 _check_keymap(wid, xkey);
749 wid->func.key_press_callback((void *)wid, &xkey, user_data);
750 debug_print("Widget_t KeyPress %x\n", xkey.keycode);
751 }
752 }
753 //X11:KeyRelease
754 if (msg != WM_KEYDOWN) { // WM_KEYUP and WM_CHAR: key_release_callback()
755 if (wid->state == 4) return 0;
756 // On MSWin, the REPEAT flag is always set for WM_KEYUP,
757 // so the retrigger check has to take place in WM_KEYDOWN instead
758 wid->func.key_release_callback((void *)wid, &xkey, user_data);
759 debug_print("Widget_t KeyRelease %x\n", xkey.keycode);
760 }
761 return 0;
762
763 // X11:LeaveNotify (X11:EnterNotify: see WM_MOUSEMOVE)
764 case WM_MOUSELEAVE:
765 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
766 // xputty -> xwidget: handled by "ButtonPress" event on Linux
767
768 bool is_item = false;
769 GetCursorPos(&pt);
770 Window win_cur = WindowFromPoint(pt);
771 if(wid->app->submenu != NULL) {
772 if (childlist_has_child(wid->app->submenu->childlist)) {
773 Widget_t *slider = wid->app->submenu->childlist->childs[1];
774 if (win_cur == slider->widget) {
775 return 0;
776 }
777 Widget_t *view_port = wid->app->submenu->childlist->childs[0];
778 int i = view_port->childlist->elem-1;
779 for(;i>-1;i--) {
780 Widget_t *w = view_port->childlist->childs[i];
781 if (win_cur == w->widget) {
782 is_item = True;
783 break;
784 }
785 }
786 }
787 }
788 if(wid->app->hold_grab != NULL && wid->app->hold_grab->flags & IS_POPUP) {
789 if (childlist_has_child(wid->app->hold_grab->childlist)) {
790 Widget_t *slider = wid->app->hold_grab->childlist->childs[1];
791 if (win_cur == slider->widget) {
792 return 0;
793 }
794 Widget_t *view_port = wid->app->hold_grab->childlist->childs[0];
795 int i = view_port->childlist->elem-1;
796 for(;i>-1;i--) {
797 Widget_t *w = view_port->childlist->childs[i];
798 if (win_cur == w->widget) {
799 is_item = True;
800 break;
801 }
802 }
803 if (win_cur == view_port->widget) is_item = True;
804 }
805 if (!is_item && (wParam & MK_LBUTTON || wParam & MK_RBUTTON)) {
806 ReleaseCapture();
807 widget_hide(wid->app->hold_grab);
808 wid->app->hold_grab = NULL;
809 }
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);
812 }
813
814/*
815 // close popup menu if cursor moves out of widget
816 if(wid->app->hold_grab != NULL) {
817 GetCursorPos(&pt);
818 Window win_cur = WindowFromPoint(pt);
819 bool is_item = false;
820 // still inside viewport? (finds menu entries in popup window)
821 Widget_t *view_port = wid->app->hold_grab->childlist->childs[0];
822 if (view_port) { // should never be NULL, but who knows :)
823 int i = view_port->childlist->elem-1;
824 for(;i>-1;i--) {
825 Widget_t *w = view_port->childlist->childs[i];
826 if (win_cur == w->widget) {
827 is_item = true;
828 break;
829 }
830 }
831 if (view_port && win_cur == view_port->widget) is_item = true; // inside slider area?
832 }
833 // still inside combobox? (finds combobox-button)
834 Widget_t *menu = NULL;
835 menu = (Widget_t *)wid->app->hold_grab->parent_struct;
836 if (menu) { // can be NULL if not contained in combobox
837 int i = menu->childlist->elem-1;
838 for(;i>-1;i--) {
839 Widget_t *w = menu->childlist->childs[i];
840 if (win_cur == w->widget) {
841 is_item = true;
842 break;
843 }
844 }
845 if (menu && win_cur == menu->widget) is_item = true; // inside combobox textarea?
846 }
847 if (!is_item) {
848 ReleaseCapture();
849 widget_hide(wid->app->hold_grab);
850 wid->app->hold_grab = NULL;
851 }
852 }
853*/
854 // for emulating X11:EnterNotify
855 wid->mouse_inside = false;
856
857 if (wid->state == 4) break;
858 //if(!(xev->xcrossing.state & Button1Mask)) {
859 if (!(GetAsyncKeyState(VK_LBUTTON) & 0x8000)) {
860 wid->state = 0;
861 wid->flags &= ~HAS_FOCUS;
862 wid->func.leave_callback((void*)wid, user_data);
863 // if (!(wid->flags & IS_WINDOW))
864 // RedrawWindow(hwnd, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW);
865 }
866 if (wid->flags & HAS_TOOLTIP) hide_tooltip(wid);
867 debug_print("Widget_t LeaveNotify:hwnd=%p",hwnd);
868
869 return 0;
870
871 // X11:MotionNotify
872 case WM_MOUSEMOVE:
873 if (!wid) return DefWindowProc(hwnd, msg, wParam, lParam);
874 if (!wid->mouse_inside) {
875 // emulate X11:EnterNotify
876 int ch = childlist_has_child(main->childlist);
877 if (ch) {
878 int i = ch;
879 for(;i>0;i--) {
880 if (main->childlist->childs[i-1] != wid) {
881 if (main->childlist->childs[i-1]->mouse_inside) {
882 main->childlist->childs[i-1]->mouse_inside = false;
883 if (main->childlist->childs[i-1]->state != 4) {
884 main->childlist->childs[i-1]->state = 0;
885 //RedrawWindow(main->childlist->childs[i-1]->widget, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW);
886 }
887 }
888 }
889 }
890 }
891 wid->mouse_inside = true;
892 wid->flags |= HAS_FOCUS;
893 if (wid->state == 4) break;
894
895 //if(!(xev->xcrossing.state & Button1Mask)) {
896 if (!(wParam & MK_LBUTTON)) {
897 wid->state = 1;
898 wid->func.enter_callback((void*)wid, user_data);
899 // if (!(wid->flags & IS_WINDOW))
900 // RedrawWindow(hwnd, NULL, NULL, RDW_NOERASE | RDW_INVALIDATE | RDW_UPDATENOW);
901 if (wid->flags & HAS_TOOLTIP) show_tooltip(wid);
902 else _hide_all_tooltips(wid);
903 }
904 debug_print("Widget_t EnterNotify:hwnd=%p",hwnd);
905
906 SetMouseTracking(hwnd, true); // for receiving (next) WM_MOUSELEAVE
907 }
908 // hovering, etc.
909 if (wid->state == 4) return 0;
910 if (wParam & MK_LBUTTON) // TODO: why is this if() required here, but not on linux?
911 adj_set_motion_state(wid, xmotion.x, xmotion.y);
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 );
914 return 0;
915
916 case WM_DROPFILES:
917 HandleFiles(wParam, wid);
918 break;
919
920 // X11:ClientMessage: not implemented (could be done with WM_USER / RegisterWindowMessage())
921 case WM_USER + 01: // WM_DELETE_WINDOW
922 // xwidget -> xputty (main_run())
923 if (wid) {
924 if (hwnd == main->childlist->childs[0]->widget) { // main window (this is not invoked for any other window?)
925 main->run = false;
926 destroy_widget(wid, main);
927 } else {
928 int i = childlist_find_widget(main->childlist, (Window)wParam);
929 if(i<1) return 0;
930 Widget_t *w = main->childlist->childs[i];
931 if(w->flags & HIDE_ON_DELETE) widget_hide(w);
932 else { destroy_widget(main->childlist->childs[i],main);
933 }
934 }
935 }
936 return 1;
937 // X11:ClientMessage:WIDGET_DESTROY
938 case WM_USER + 02: // WIDGET_DESTROY
939 //os_widget_event_loop()
940 if (wid) {
941 int ch = childlist_has_child(wid->childlist);
942 if (ch) {
943 int i = ch;
944 for(;i>0;i--) {
945 quit_widget(wid->childlist->childs[i-1]);
946 }
947 quit_widget(wid);
948 } else {
949 destroy_widget(wid,wid->app);
950 }
951 return 0;
952 }
953 return 2;
954
955 default:
956 return DefWindowProc(hwnd, msg, wParam, lParam);
957 }
958 return 0;
959}
960
961LRESULT onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam ) {
962 PAINTSTRUCT ps ;
963 Widget_t *w = (Widget_t *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
964
965 // The cairo_win32_surface should only exist between BeginPaint()/EndPaint(),
966 // otherwise it becomes unusable once the HDC of the owner window changes
967 // (what can happen anytime, e.g. on resize).
968 // Therefore, w->surface is created as a simple cairo_image_surface,
969 // that can exist throughout the plugins lifetime (exception: see resize_event())
970 // and is copied to a win32_surface in the onPaint() event (see WM_PAINT).
971
972 // draw onto the image surface first
973 transparent_draw(w, NULL);
974
975 // prepare to update window
976 HDC hdc = BeginPaint(hwnd, &ps );
977
978 // create the cairo surface and context
979 cairo_surface_t *surface = cairo_win32_surface_create (hdc);
980 cairo_t *cr = cairo_create (surface);
981 // copy contents of the (permanent) image_surface to the win32_surface
982 cairo_set_source_surface(cr, w->surface, 0.0, 0.0);
983 cairo_paint(cr);
984
985 // cleanup
986 cairo_destroy (cr);
987 cairo_surface_destroy (surface);
988
989 EndPaint( hwnd, &ps );
990 return 0 ;
991}
992
993/*---------------------------------------------------------------------
994---------------------------------------------------------------------*/
995
996void SetClientSize(HWND hwnd, int clientWidth, int clientHeight) {
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) ;
1005 }
1006}
1007
1008// WM_MOUSELEAVE is only reported ONCE after calling TrackMouseEvent(TME_LEAVE)
1009BOOL SetMouseTracking(HWND hwnd, BOOL enable) {
1010 TRACKMOUSEEVENT tme;
1011
1012 tme.cbSize = sizeof(tme);
1013 tme.dwFlags = TME_LEAVE;
1014 if (!enable)
1015 tme.dwFlags |= TME_CANCEL;
1016 tme.hwndTrack = hwnd;
1017 tme.dwHoverTime = HOVER_DEFAULT;
1018 return TrackMouseEvent(&tme);
1019}
1020
1021/*---------------------------------------------------------------------
1022---------------------------------------------------------------------*/
1023
1024
1025#ifdef __cplusplus
1026}
1027#endif
1028
1029#endif /* _WIN32 */
Widget_t ** childs
Definition xchildlist.h:51
evfunc button_release_callback
Definition xwidget.h:101
xevfunc configure_callback
Definition xwidget.h:86
evfunc double_click_callback
Definition xwidget.h:102
xevfunc dnd_notify_callback
Definition xwidget.h:97
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
Widget_t - struct to hold the basic Widget_t info.
Definition xwidget.h:457
bool mouse_inside
Definition xwidget.h:528
void * parent
Definition xwidget.h:471
Window widget
Definition xwidget.h:469
int pos_y
Definition xwidget.h:515
cairo_surface_t * surface
Definition xwidget.h:483
Metrics_t metrics_min
Definition xwidget.h:530
cairo_t * crb
Definition xwidget.h:489
int state
Definition xwidget.h:511
Childlist_t * childlist
Definition xwidget.h:499
int pos_x
Definition xwidget.h:513
long long flags
Definition xwidget.h:461
cairo_t * cr
Definition xwidget.h:485
Func_t func
Definition xwidget.h:481
Xputty * app
Definition xwidget.h:465
bool vk_is_final_char
int button
int keycode
WORD vk
Window window
Xputty - the main struct. It should be declared before any other call to a Xputty function....
Definition xputty.h:228
bool run
Definition xputty.h:256
Widget_t * hold_grab
Definition xputty.h:238
Childlist_t * childlist
Definition xputty.h:230
Widget_t * submenu
Definition xputty.h:242
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,...)
Definition xasprintf.c:36
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...
Definition xchildlist.c:42
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
Definition xchildlist.c:79
int childlist_has_child(Childlist_t *childlist)
childlist_has_child - check if a Widget_t Childlist_t contain a child
Definition xchildlist.c:89
XID Pixmap
XID Display
unsigned long int Atom
HWND Window
void os_widget_show(Widget_t *w)
os_widget_show - Show a Widget_t
void os_main_run(Xputty *main)
os_main_run - start the event loop
void os_widget_hide(Widget_t *w)
os_widget_hide - Hide a Widget_t
void os_destroy_window(Widget_t *w)
os_destroy_window - destroy a widget (close and remove from processing)
void os_init_dnd(Xputty *main)
os_init_dnd - register a Widget_t for handling drag and drop events only implemented on linux
void os_set_widget_surface_size(Widget_t *w, int width, int height)
os_set_widget_surface_size - set the size of a Widget_t cairo surface
void os_send_button_press_event(Widget_t *w)
os_send_button_press_event - Send a button press event to a Widget_t see XButtonEvent
int os_grab_pointer(Widget_t *w)
os_grab_pointer - grab the mouse pointer. Works only on linux
char * utf8_from_locale(char *localestr)
utf8_from_locale - convert active codepage to utf8 must be freed by the caller
int os_get_screen_width(Widget_t *w)
os_get_screen_width - Get the width of the used Display
void os_resize_window(Display *dpy, Widget_t *w, int x, int y)
os_resize_window - Resize a Widget_t
char * os_get_home_dir()
os_get_home_dir - get the users home directory
void os_send_button_release_event(Widget_t *w)
os_send_button_release_event - Send a button release event to a Widget_t see XButtonEvent
Window os_get_root_window(Xputty *main, int flag)
os_get_root_window - get a pointer to the root window (desktop)
void SetClientSize(HWND hwnd, int clientWidth, int clientHeight)
void HandleFiles(WPARAM wParam, Widget_t *wid)
void os_run_embedded(Xputty *main)
os_run_embedded - the event handling when run embedded on windows all messges goes into WndProc,...
void debug_lasterror(const char *prefix, const char *prefix2)
void os_translate_coords(Widget_t *w, Window from_window, Window to_window, int from_x, int from_y, int *to_x, int *to_y)
os_translate_coords - get x,y related to destination Window
void os_send_systray_message(Widget_t *w)
os_send_send_systray_message - Send a systray event to a Widget_t only working on Linux for now
void build_xkey_event(XKeyEvent *ev, UINT msg, WPARAM wParam, LPARAM lParam)
void os_send_configure_event(Widget_t *w, int x, int y, int width, int height)
os_send_configure_event - Send a configure event to a Widget_t
void os_set_title(Widget_t *w, const char *title)
os_set_title - Set the title of a Widget_t
Atom os_register_widget_destroy(Widget_t *wid)
os_register_widget_destroy - Get the needed Atom to send a widget destroy message
void os_quit(Widget_t *w)
os_quit - quit the main loop and free all used memory
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
void os_set_input_mask(Widget_t *w)
os_set_input_mask - set the Event mask to a Widget_t only work on linux, stub on Windows
void os_show_tooltip(Widget_t *wid, Widget_t *w)
os_show_tooltip - Show a tooltip of a Widget_t
Atom os_register_wm_delete_window(Widget_t *wid)
os_register_wm_delete_window - Get the needed Atom to send a widget delete message
void os_free_pixmap(Widget_t *w, Pixmap pixmap)
os_free_pixmap - Free the memory used by a Pixmap only Linux, stub otherwise
void os_move_window(Display *dpy, Widget_t *w, int x, int y)
os_move_window - Move a Widget_t
void os_widget_event_loop(void *w_, void *event, Xputty *main, void *user_data)
os_widget_event_loop - the Widget_t event loop on windows all messges goes into WndProc,...
char * convert_cp(DWORD cp_from, DWORD cp_to, char *s_from)
bool os_is_directory(const char *filename)
os_is directory - check if a given path is a directory or a file
void os_quit_widget(Widget_t *w)
os_quit_widget - remove a Widget_t from the main loop and free it's used memory
void os_set_transient_for_hint(Widget_t *parent, Widget_t *w)
os_set_ transient_for_hint - set a Widget_t transient to a other Widget_t only work on linux,...
void os_transparent_draw(void *w_, void *user_data)
os_transparent_draw - Draw the Widget_t to the back buffer
bool os_get_keyboard_input(Widget_t *w, XKeyEvent *key, char *buf, size_t bufsize)
os_ get_keyboard_input - Get the Keyboard input and convert it to utf8
void os_set_window_min_size(Widget_t *w, int min_width, int min_height, int base_width, int base_height)
os_set_window_min_size - Set the min and base size of a Widget_t
void os_create_widget_window_and_surface(Widget_t *w, Xputty *app, Widget_t *parent, int x, int y, int width, int height)
os_create_main_widget_and_surface - create a Widget_t with a acairo surface this function is used mai...
int os_get_screen_height(Widget_t *w)
os_get_screen_height - Get the height of the used Display
void os_create_main_window_and_surface(Widget_t *w, Xputty *app, Window win, int x, int y, int width, int height)
os_create_main_window_and_surface - create a Widget_t with a acairo surface this function is used mai...
void os_close_display(Display *dpy)
os_close_display - Close connection to the used display
void os_adjustment_callback(void *w_, void *user_data)
os_adjustment_callback - called when a adjustment value have changed used internal for redraw the Wid...
void os_expose_widget(Widget_t *w)
os_expose_widget - Draw the the back buffer to the Widget_t surface
TCHAR szMainUIClassName[]
char * locale_from_utf8(char *utf8str)
locale_from_utf8 - convert utf8 to active codepage must be freed by the caller
Display * os_open_display(char *display_name)
os_open_display - Connect to the display to use
void os_get_window_metrics(Widget_t *w_, Metrics_t *metrics)
os_get_window_metrics - Get the Merics_t struct related to a Widget_t
TCHAR szWidgetUIClassName[]
void os_set_window_attrb(Widget_t *w)
os_set_window_attrb - set the attribute mask to a Widget_t only work on linux, stub on Windows
BOOL SetMouseTracking(HWND hwnd, BOOL enable)
LRESULT onPaint(HWND hwnd, WPARAM wParam, LPARAM lParam)
void os_get_surface_size(cairo_surface_t *surface, int *width, int *height)
os_get_surface_size - get the size of the cairo surface
This file contains definitions and structs used on all platforms. Platform specific definitions are l...
void quit_widget(Widget_t *w)
quit_widget - remove a widget from the processing loop
Definition xwidget.c:530
Widget_t * get_toplevel_widget(Xputty *main)
*get_toplevel_widget - get pointer to the top level Widget_t
Definition xwidget.c:441
void show_tooltip(Widget_t *wid)
show_tooltip - check if a Widget_t have a tooltip, and show it, if a tooltip is available.
Definition xwidget.c:419
@ IS_WIDGET
Definition xwidget.h:388
@ HIDE_ON_DELETE
Definition xwidget.h:412
@ HAS_POINTER
Definition xwidget.h:402
@ NO_AUTOREPEAT
Definition xwidget.h:408
@ HAS_TOOLTIP
Definition xwidget.h:404
@ HAS_FOCUS
Definition xwidget.h:400
@ IS_POPUP
Definition xwidget.h:392
void hide_tooltip(Widget_t *wid)
hide_tooltip - check if a Widget_t have a tooltip, and hide it, if a tooltip is mapped.
Definition xwidget.c:430
void widget_hide(Widget_t *w)
widget_hide - unmap/hide a Widget_t
Definition xwidget.c:368
void transparent_draw(void *wid, void *user_data)
transparent_draw - copy parent surface to child surface you usaualy didn't need to call this,...
Definition xwidget.c:449
void destroy_widget(Widget_t *w, Xputty *main)
destroy_widget - destroy a widget When a Widget_t receive a destroy_widget() call,...
Definition xwidget.c:86
This file contains private function definitions used on all platforms.
void _hide_all_tooltips(Widget_t *wid)
_hide_all_tooltips - hide all active tooltips
void _check_enum(Widget_t *wid, XButtonEvent *xbutton)
_check_enum - internal check if Adjustment_t is of type CL_ENUM and handle events acordingly
void _check_grab(Widget_t *wid, XButtonEvent *xbutton, Xputty *main)
_check_grab - internal check if a Widgt_t holds a grab when a BUTTON_PRESS event occur....
void _button_press(Widget_t *wid, XButtonEvent *xbutton, void *user_data)
_button_press - internal check which button is pressed (BUTTON_PRESS)
void _check_submenu(Widget_t *wid, XButtonEvent *xbutton, Xputty *main)
_check_submenu - internal check if a Widgt_t is a submenu when a BUTTON_PRESS event occur....
void _check_keymap(void *w_, XKeyEvent xkey)
_check_keymap - check if key is in map, send requests if so
void _has_pointer(Widget_t *w, XButtonEvent *button)
_has_pointer - check if the widget has the pointer