comparison gtk4/dw.c @ 2321:52ca7647f665

GTK4: Implement pointer grabbing using Xlib and center message boxes.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 17 Feb 2021 03:52:41 +0000
parents 829228de003f
children ebcaedfa7ff4
comparison
equal deleted inserted replaced
2320:829228de003f 2321:52ca7647f665
56 * ... 56 * ...
57 */ 57 */
58 #ifndef _DW_SINGLE_THREADED 58 #ifndef _DW_SINGLE_THREADED
59 #define DW_FUNCTION_DEFINITION(func, rettype, ...) gboolean _##func(void **_args); \ 59 #define DW_FUNCTION_DEFINITION(func, rettype, ...) gboolean _##func(void **_args); \
60 rettype API func(__VA_ARGS__) { 60 rettype API func(__VA_ARGS__) {
61 #define DW_FUNCTION_ADD_PARAM void **_args = alloca(sizeof(void *)*2); \
62 _args[0] = (void *)pthread_getspecific(_dw_event_key); \
63 _args[1] = (void *)NULL;
61 #define DW_FUNCTION_ADD_PARAM1(param1) void **_args = alloca(sizeof(void *)*3); \ 64 #define DW_FUNCTION_ADD_PARAM1(param1) void **_args = alloca(sizeof(void *)*3); \
62 _args[0] = (void *)pthread_getspecific(_dw_event_key); \ 65 _args[0] = (void *)pthread_getspecific(_dw_event_key); \
63 _args[1] = (void *)NULL; \ 66 _args[1] = (void *)NULL; \
64 _args[2] = (void *)&param1; 67 _args[2] = (void *)&param1;
65 #define DW_FUNCTION_ADD_PARAM2(param1, param2) void **_args = alloca(sizeof(void *)*4); \ 68 #define DW_FUNCTION_ADD_PARAM2(param1, param2) void **_args = alloca(sizeof(void *)*4); \
1613 GtkWidget *dialog; 1616 GtkWidget *dialog;
1614 int response; 1617 int response;
1615 va_list args; 1618 va_list args;
1616 char outbuf[1025] = {0}; 1619 char outbuf[1025] = {0};
1617 DWDialog *tmp = dw_dialog_new(NULL); 1620 DWDialog *tmp = dw_dialog_new(NULL);
1621 ULONG width, height;
1618 1622
1619 va_start(args, format); 1623 va_start(args, format);
1620 vsnprintf(outbuf, 1024, format, args); 1624 vsnprintf(outbuf, 1024, format, args);
1621 va_end(args); 1625 va_end(args);
1622 1626
1640 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", outbuf); 1644 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", outbuf);
1641 if(flags & DW_MB_YESNOCANCEL) 1645 if(flags & DW_MB_YESNOCANCEL)
1642 gtk_dialog_add_button(GTK_DIALOG(dialog), "Cancel", GTK_RESPONSE_CANCEL); 1646 gtk_dialog_add_button(GTK_DIALOG(dialog), "Cancel", GTK_RESPONSE_CANCEL);
1643 gtk_widget_show(GTK_WIDGET(dialog)); 1647 gtk_widget_show(GTK_WIDGET(dialog));
1644 g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(_dw_dialog_response), (gpointer)tmp); 1648 g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(_dw_dialog_response), (gpointer)tmp);
1649 /* Center the dialog on the screen since there is no parent */
1650 dw_window_get_pos_size((HWND)dialog, NULL, NULL, &width, &height);
1651 dw_window_set_pos((HWND)dialog, (dw_screen_width() - width)/2, (dw_screen_height() - height)/2);
1645 response = DW_POINTER_TO_INT(dw_dialog_wait(tmp)); 1652 response = DW_POINTER_TO_INT(dw_dialog_wait(tmp));
1646 if(GTK_IS_WINDOW(dialog)) 1653 if(GTK_IS_WINDOW(dialog))
1647 gtk_window_destroy(GTK_WINDOW(dialog)); 1654 gtk_window_destroy(GTK_WINDOW(dialog));
1648 switch(response) 1655 switch(response)
1649 { 1656 {
2289 /* TODO */ 2296 /* TODO */
2290 return 0; 2297 return 0;
2291 } 2298 }
2292 2299
2293 /* 2300 /*
2294 * Captures the mouse input to this window.
2295 * Parameters:
2296 * handle: Handle to receive mouse input.
2297 */
2298 void dw_window_capture(HWND handle)
2299 {
2300 /* TODO: See if this is possible in GTK4 */
2301 }
2302
2303 /*
2304 * Changes the appearance of the mouse pointer. 2301 * Changes the appearance of the mouse pointer.
2305 * Parameters: 2302 * Parameters:
2306 * handle: Handle to widget for which to change. 2303 * handle: Handle to widget for which to change.
2307 * cursortype: ID of the pointer you want. 2304 * cursortype: ID of the pointer you want.
2308 */ 2305 */
2328 gtk_widget_set_cursor(GTK_WIDGET(handle), NULL); 2325 gtk_widget_set_cursor(GTK_WIDGET(handle), NULL);
2329 DW_FUNCTION_RETURN_NOTHING; 2326 DW_FUNCTION_RETURN_NOTHING;
2330 } 2327 }
2331 2328
2332 /* 2329 /*
2330 * Captures the mouse input to this window.
2331 * Parameters:
2332 * handle: Handle to receive mouse input.
2333 */
2334 #ifndef GDK_WINDOWING_X11
2335 void dw_window_capture(HWND handle)
2336 {
2337 }
2338 #else
2339 static Display *_DWXGrabbedDisplay = NULL;
2340
2341 DW_FUNCTION_DEFINITION(dw_window_capture, void, HWND handle)
2342 DW_FUNCTION_ADD_PARAM1(handle)
2343 DW_FUNCTION_NO_RETURN(dw_window_capture)
2344 DW_FUNCTION_RESTORE_PARAM1(handle, HWND)
2345 {
2346 if(_DWXGrabbedDisplay == NULL && handle && GTK_IS_WINDOW(handle))
2347 {
2348 GdkSurface *surface = gtk_native_get_surface(GTK_NATIVE(handle));
2349
2350 if(surface)
2351 {
2352 if(XGrabPointer(GDK_SURFACE_XDISPLAY(surface), GDK_SURFACE_XID(surface), FALSE,
2353 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
2354 GrabModeAsync, GrabModeAsync, None, None, CurrentTime) == GrabSuccess)
2355 _DWXGrabbedDisplay = GDK_SURFACE_XDISPLAY(surface);
2356
2357 }
2358 }
2359 DW_FUNCTION_RETURN_NOTHING;
2360 }
2361 #endif
2362
2363 /*
2333 * Releases previous mouse capture. 2364 * Releases previous mouse capture.
2334 */ 2365 */
2366 #ifndef GDK_WINDOWING_X11
2335 void dw_window_release(void) 2367 void dw_window_release(void)
2336 { 2368 {
2337 /* TODO: See if this is possible in GTK4 */ 2369 }
2338 } 2370 #else
2371 DW_FUNCTION_DEFINITION(dw_window_release, void)
2372 DW_FUNCTION_ADD_PARAM
2373 DW_FUNCTION_NO_RETURN(dw_window_release)
2374 {
2375 if(_DWXGrabbedDisplay)
2376 {
2377 XUngrabPointer(_DWXGrabbedDisplay, CurrentTime);
2378 _DWXGrabbedDisplay = NULL;
2379 }
2380 DW_FUNCTION_RETURN_NOTHING;
2381 }
2382 #endif
2339 2383
2340 /* Window creation flags that will cause the window to have decorations */ 2384 /* Window creation flags that will cause the window to have decorations */
2341 #define _DW_DECORATION_FLAGS (DW_FCF_CLOSEBUTTON|DW_FCF_SYSMENU|DW_FCF_TITLEBAR|DW_FCF_MINMAX|DW_FCF_SIZEBORDER|DW_FCF_BORDER|DW_FCF_DLGBORDER) 2385 #define _DW_DECORATION_FLAGS (DW_FCF_CLOSEBUTTON|DW_FCF_SYSMENU|DW_FCF_TITLEBAR|DW_FCF_MINMAX|DW_FCF_SIZEBORDER|DW_FCF_BORDER|DW_FCF_DLGBORDER)
2342 2386
2343 /* 2387 /*
6862 /* Try with various extentions */ 6906 /* Try with various extentions */
6863 while(_dw_image_exts[i] && !pixmap->pixbuf) 6907 while(_dw_image_exts[i] && !pixmap->pixbuf)
6864 { 6908 {
6865 strcpy(file, filename); 6909 strcpy(file, filename);
6866 strcat(file, _dw_image_exts[i]); 6910 strcat(file, _dw_image_exts[i]);
6867 if(access(file, 04 ) == 0) 6911 if(access(file, 04) == 0)
6868 pixmap->pixbuf = gdk_pixbuf_new_from_file(file, NULL); 6912 pixmap->pixbuf = gdk_pixbuf_new_from_file(file, NULL);
6869 i++; 6913 i++;
6870 } 6914 }
6871 } 6915 }
6872 else 6916 else
8581 DW_FUNCTION_NO_RETURN(dw_window_get_pos_size) 8625 DW_FUNCTION_NO_RETURN(dw_window_get_pos_size)
8582 DW_FUNCTION_RESTORE_PARAM5(handle, HWND, x, long *, y, long *, width, ULONG *, height, ULONG *) 8626 DW_FUNCTION_RESTORE_PARAM5(handle, HWND, x, long *, y, long *, width, ULONG *, height, ULONG *)
8583 { 8627 {
8584 if(handle && GTK_IS_WIDGET(handle)) 8628 if(handle && GTK_IS_WIDGET(handle))
8585 { 8629 {
8630 GtkRequisition size;
8631
8632 /* If the widget hasn't been shown, it returns 0 so use this as backup */
8633 gtk_widget_get_preferred_size(GTK_WIDGET(handle), NULL, &size);
8634
8586 if(width) 8635 if(width)
8636 {
8587 *width = (ULONG)gtk_widget_get_width(GTK_WIDGET(handle)); 8637 *width = (ULONG)gtk_widget_get_width(GTK_WIDGET(handle));
8638 if(!*width)
8639 *width = (ULONG)size.width;
8640 }
8588 if(height) 8641 if(height)
8642 {
8589 *height = (ULONG)gtk_widget_get_height(GTK_WIDGET(handle)); 8643 *height = (ULONG)gtk_widget_get_height(GTK_WIDGET(handle));
8644 if(!*height)
8645 *height = (ULONG)size.height;
8646 }
8590 8647
8591 #ifdef GDK_WINDOWING_X11 8648 #ifdef GDK_WINDOWING_X11
8592 { 8649 {
8593 GdkSurface *surface = gtk_native_get_surface(GTK_NATIVE(handle)); 8650 GdkSurface *surface = gtk_native_get_surface(GTK_NATIVE(handle));
8594 8651