comparison gtk4/dw.c @ 2265:63bb97e94cd3

GTK4: More work on conversion... the amount of changes is really ridiculous. GTK4 is essentially a new system, almost everything has changed.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 29 Jan 2021 13:18:47 +0000
parents 5c981407b0f3
children bb0690c04413
comparison
equal deleted inserted replaced
2264:5c981407b0f3 2265:63bb97e94cd3
139 #endif 139 #endif
140 static void _dw_signal_disconnect(gpointer data, GClosure *closure); 140 static void _dw_signal_disconnect(gpointer data, GClosure *closure);
141 141
142 GObject *_DWObject = NULL; 142 GObject *_DWObject = NULL;
143 GApplication *_DWApp = NULL; 143 GApplication *_DWApp = NULL;
144 GMainLoop *_DWMainLoop = NULL;
144 static char _dw_app_id[_DW_APP_ID_SIZE+1] = { 0 }; 145 static char _dw_app_id[_DW_APP_ID_SIZE+1] = { 0 };
145 char *_DWDefaultFont = NULL; 146 char *_DWDefaultFont = NULL;
146 static char _dw_share_path[PATH_MAX+1] = { 0 }; 147 static char _dw_share_path[PATH_MAX+1] = { 0 };
147 148
148 typedef struct 149 typedef struct
1064 /* If that failed... just get the current directory */ 1065 /* If that failed... just get the current directory */
1065 if(!_dw_share_path[0] && !getcwd(_dw_share_path, PATH_MAX)) 1066 if(!_dw_share_path[0] && !getcwd(_dw_share_path, PATH_MAX))
1066 _dw_share_path[0] = '/'; 1067 _dw_share_path[0] = '/';
1067 1068
1068 gtk_init(); 1069 gtk_init();
1070
1071 _DWMainLoop = g_main_loop_new(NULL, FALSE);
1072 g_main_loop_ref(_DWMainLoop);
1069 1073
1070 pthread_key_create(&_dw_fg_color_key, NULL); 1074 pthread_key_create(&_dw_fg_color_key, NULL);
1071 pthread_key_create(&_dw_bg_color_key, NULL); 1075 pthread_key_create(&_dw_bg_color_key, NULL);
1072 1076
1073 _dw_init_thread(); 1077 _dw_init_thread();
1102 /* 1106 /*
1103 * Runs a message loop for Dynamic Windows. 1107 * Runs a message loop for Dynamic Windows.
1104 */ 1108 */
1105 void API dw_main(void) 1109 void API dw_main(void)
1106 { 1110 {
1107 gtk_main(); 1111 g_main_loop_run(_DWMainLoop);
1108 } 1112 }
1109 1113
1110 /* 1114 /*
1111 * Causes running dw_main() to return. 1115 * Causes running dw_main() to return.
1112 */ 1116 */
1113 void API dw_main_quit(void) 1117 void API dw_main_quit(void)
1114 { 1118 {
1115 gtk_main_quit(); 1119 g_main_loop_quit(_DWMainLoop);
1116 } 1120 }
1117 1121
1118 /* 1122 /*
1119 * Runs a message loop for Dynamic Windows, for a period of milliseconds. 1123 * Runs a message loop for Dynamic Windows, for a period of milliseconds.
1120 * Parameters: 1124 * Parameters:
1135 1139
1136 while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds) 1140 while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds)
1137 { 1141 {
1138 if(orig == (pthread_t)-1) 1142 if(orig == (pthread_t)-1)
1139 _dw_thread = curr; 1143 _dw_thread = curr;
1140 if(curr == _dw_thread && gtk_events_pending()) 1144 if(curr == _dw_thread && g_main_context_pending(NULL))
1141 gtk_main_iteration(); 1145 g_main_context_iteration(NULL, FALSE);
1142 else 1146 else
1143 _dw_msleep(1); 1147 _dw_msleep(1);
1144 if(orig == (pthread_t)-1) 1148 if(orig == (pthread_t)-1)
1145 _dw_thread = orig; 1149 _dw_thread = orig;
1146 gettimeofday(&tv, NULL); 1150 gettimeofday(&tv, NULL);
1158 pthread_t orig = _dw_thread; 1162 pthread_t orig = _dw_thread;
1159 pthread_t curr = pthread_self(); 1163 pthread_t curr = pthread_self();
1160 1164
1161 if(_dw_thread == (pthread_t)-1) 1165 if(_dw_thread == (pthread_t)-1)
1162 _dw_thread = curr; 1166 _dw_thread = curr;
1163 if(curr == _dw_thread && gtk_events_pending()) 1167 if(curr == _dw_thread && g_main_context_pending(NULL))
1164 gtk_main_iteration(); 1168 g_main_context_iteration(NULL, FALSE);
1165 else 1169 else
1166 sched_yield(); 1170 sched_yield();
1167 if(orig == (pthread_t)-1) 1171 if(orig == (pthread_t)-1)
1168 _dw_thread = orig; 1172 _dw_thread = orig;
1169 } 1173 }
1209 */ 1213 */
1210 int dw_dialog_dismiss(DWDialog *dialog, void *result) 1214 int dw_dialog_dismiss(DWDialog *dialog, void *result)
1211 { 1215 {
1212 dialog->result = result; 1216 dialog->result = result;
1213 if(dialog->method) 1217 if(dialog->method)
1214 gtk_main_quit(); 1218 g_main_loop_quit(_DWMainLoop);
1215 else 1219 else
1216 dw_event_post(dialog->eve); 1220 dw_event_post(dialog->eve);
1217 dialog->done = TRUE; 1221 dialog->done = TRUE;
1218 return 0; 1222 return 0;
1219 } 1223 }
1225 * dialog: Pointer to a dialog struct aquired by dw_dialog_new). 1229 * dialog: Pointer to a dialog struct aquired by dw_dialog_new).
1226 */ 1230 */
1227 void *dw_dialog_wait(DWDialog *dialog) 1231 void *dw_dialog_wait(DWDialog *dialog)
1228 { 1232 {
1229 void *tmp; 1233 void *tmp;
1230 int newprocess = 0;
1231 1234
1232 if(!dialog) 1235 if(!dialog)
1233 return NULL; 1236 return NULL;
1234 1237
1235 /* _dw_thread will be -1 if dw_main hasn't been run yet. */
1236 if(_dw_thread == (pthread_t)-1)
1237 {
1238 _dw_thread = pthread_self();
1239 newprocess = 1;
1240 _dw_gdk_threads_enter();
1241 }
1242
1243 if(pthread_self() == _dw_thread) 1238 if(pthread_self() == _dw_thread)
1244 { 1239 {
1245 dialog->method = TRUE; 1240 dialog->method = TRUE;
1246 gtk_main(); 1241 g_main_loop_run(_DWMainLoop);
1247 } 1242 }
1248 else 1243 else
1249 { 1244 {
1250 dialog->method = FALSE; 1245 dialog->method = FALSE;
1251 dw_event_wait(dialog->eve, -1); 1246 dw_event_wait(dialog->eve, -1);
1252 }
1253
1254 if(newprocess)
1255 {
1256 _dw_thread = (pthread_t)-1;
1257 _dw_gdk_threads_leave();
1258 } 1247 }
1259 1248
1260 dw_event_close(&dialog->eve); 1249 dw_event_close(&dialog->eve);
1261 tmp = dialog->result; 1250 tmp = dialog->result;
1262 free(dialog); 1251 free(dialog);
1321 GTK_DIALOG_MODAL, gtkicon, gtkbuttons, "%s", title); 1310 GTK_DIALOG_MODAL, gtkicon, gtkbuttons, "%s", title);
1322 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", outbuf); 1311 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", outbuf);
1323 if(flags & DW_MB_YESNOCANCEL) 1312 if(flags & DW_MB_YESNOCANCEL)
1324 gtk_dialog_add_button(GTK_DIALOG(dialog), "Cancel", GTK_RESPONSE_CANCEL); 1313 gtk_dialog_add_button(GTK_DIALOG(dialog), "Cancel", GTK_RESPONSE_CANCEL);
1325 response = gtk_dialog_run(GTK_DIALOG(dialog)); 1314 response = gtk_dialog_run(GTK_DIALOG(dialog));
1326 gtk_widget_destroy(dialog); 1315 if(GTK_IS_WINDOW(dialog))
1316 gtk_window_destroy(GTK_WINDOW(dialog));
1327 switch(response) 1317 switch(response)
1328 { 1318 {
1329 case GTK_RESPONSE_OK: 1319 case GTK_RESPONSE_OK:
1330 return DW_MB_RETURN_OK; 1320 return DW_MB_RETURN_OK;
1331 case GTK_RESPONSE_CANCEL: 1321 case GTK_RESPONSE_CANCEL:
1354 int dw_window_minimize(HWND handle) 1344 int dw_window_minimize(HWND handle)
1355 { 1345 {
1356 if(!handle) 1346 if(!handle)
1357 return 0; 1347 return 0;
1358 1348
1359 gtk_window_iconify( GTK_WINDOW(handle) ); 1349 gtk_window_minimize(GTK_WINDOW(handle));
1360 return 0; 1350 return 0;
1361 } 1351 }
1362 1352
1363 /* 1353 /*
1364 * Makes the window topmost. 1354 * Makes the window topmost.
1365 * Parameters: 1355 * Parameters:
1366 * handle: The window handle to make topmost. 1356 * handle: The window handle to make topmost.
1367 */ 1357 */
1368 int dw_window_raise(HWND handle) 1358 int dw_window_raise(HWND handle)
1369 { 1359 {
1370 if(!handle) 1360 /* TODO: See if this is possible in GTK4 */
1371 return 0; 1361 return DW_ERROR_UNKNOWN;
1372
1373 gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(handle)));
1374 return 0;
1375 } 1362 }
1376 1363
1377 /* 1364 /*
1378 * Makes the window bottommost. 1365 * Makes the window bottommost.
1379 * Parameters: 1366 * Parameters:
1380 * handle: The window handle to make bottommost. 1367 * handle: The window handle to make bottommost.
1381 */ 1368 */
1382 int dw_window_lower(HWND handle) 1369 int dw_window_lower(HWND handle)
1383 { 1370 {
1384 if(!handle) 1371 /* TODO: See if this is possible in GTK4 */
1385 return 0; 1372 return DW_ERROR_UNKNOWN;
1386
1387 gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(handle)));
1388 return 0;
1389 } 1373 }
1390 1374
1391 /* 1375 /*
1392 * Makes the window visible. 1376 * Makes the window visible.
1393 * Parameters: 1377 * Parameters:
1394 * handle: The window handle to make visible. 1378 * handle: The window handle to make visible.
1395 */ 1379 */
1396 int dw_window_show(HWND handle) 1380 int dw_window_show(HWND handle)
1397 { 1381 {
1398 GtkWidget *defaultitem;
1399
1400 if (!handle) 1382 if (!handle)
1401 return 0; 1383 return 0;
1402 1384
1403 gtk_widget_show(handle); 1385 if(GTK_IS_WIDGET(handle))
1404 { 1386 gtk_widget_show(handle);
1405 GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(handle)); 1387 if(GTK_IS_WINDOW(handle))
1406 if (window && gtk_widget_get_mapped(handle)) 1388 {
1407 { 1389 GtkWidget *defaultitem;
1408 int width = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(handle), "_dw_width")); 1390
1409 int height = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(handle), "_dw_height")); 1391 gtk_window_unminimize(GTK_WINDOW(handle));
1410
1411 /* If we had a size request before shown */
1412 if (width || height)
1413 {
1414 /* Call the size function again now that we are realized */
1415 dw_window_set_size(handle, width, height);
1416 /* Clear out the data so we don't do it again */
1417 g_object_set_data(G_OBJECT(handle), "_dw_width", NULL);
1418 g_object_set_data(G_OBJECT(handle), "_dw_height", NULL);
1419 }
1420
1421 /* If we had a position request before shown */
1422 if (g_object_get_data(G_OBJECT(handle), "_dw_pos"))
1423 {
1424 int x = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(handle), "_dw_x"));
1425 int y = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(handle), "_dw_y"));
1426
1427 /* Call the position function again now that we are realized */
1428 dw_window_set_pos(handle, x, y);
1429 /* Clear out the data so we don't do it again */
1430 g_object_set_data(G_OBJECT(handle), "_dw_pos", NULL);
1431 }
1432
1433 gdk_window_raise(window);
1434 gdk_display_flush(gdk_display_get_default());
1435 gdk_window_show(window);
1436 gdk_display_flush(gdk_display_get_default());
1437 }
1438 defaultitem = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_defaultitem"); 1392 defaultitem = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_defaultitem");
1439 if (defaultitem) 1393 if (defaultitem)
1440 gtk_widget_grab_focus(defaultitem); 1394 gtk_widget_grab_focus(defaultitem);
1441 } 1395 }
1442 return 0; 1396 return 0;
1464 int dw_window_destroy(HWND handle) 1418 int dw_window_destroy(HWND handle)
1465 { 1419 {
1466 if(!handle) 1420 if(!handle)
1467 return 0; 1421 return 0;
1468 1422
1469 if(GTK_IS_WIDGET(handle)) 1423 if(GTK_IS_WINDOW(handle))
1424 gtk_window_destroy(GTK_WINDOW(handle));
1425 else if(GTK_IS_WIDGET(handle))
1470 { 1426 {
1471 GtkWidget *box, *handle2 = handle; 1427 GtkWidget *box, *handle2 = handle;
1472 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_eventbox"); 1428 GtkWidget *eventbox = (GtkWidget *)g_object_get_data(G_OBJECT(handle), "_dw_eventbox");
1473 1429
1474 /* Handle the invisible event box if it exists */ 1430 /* Handle the invisible event box if it exists */
1516 } 1472 }
1517 /* Finally destroy the widget, make sure it is still 1473 /* Finally destroy the widget, make sure it is still
1518 * a valid widget if it got removed from the grid. 1474 * a valid widget if it got removed from the grid.
1519 */ 1475 */
1520 if(GTK_IS_WIDGET(handle2)) 1476 if(GTK_IS_WIDGET(handle2))
1521 gtk_widget_destroy(handle2); 1477 g_object_unref(G_OBJECT(handle2));
1522 } 1478 }
1523 return 0; 1479 return 0;
1524 } 1480 }
1525 1481
1526 /* Causes entire window to be invalidated and redrawn. 1482 /* Causes entire window to be invalidated and redrawn.
1537 * handle: The window handle to destroy. 1493 * handle: The window handle to destroy.
1538 * newparent: The window's new parent window. 1494 * newparent: The window's new parent window.
1539 */ 1495 */
1540 void dw_window_reparent(HWND handle, HWND newparent) 1496 void dw_window_reparent(HWND handle, HWND newparent)
1541 { 1497 {
1542 gdk_window_reparent(gtk_widget_get_window(GTK_WIDGET(handle)), newparent ? gtk_widget_get_window(GTK_WIDGET(newparent)) : gdk_get_default_root_window(), 0, 0); 1498 if(GTK_IS_WIDGET(handle) && GTK_IS_WIDGET(newparent))
1499 gtk_widget_set_parent(GTK_WIDGET(handle), GTK_WIDGET(newparent));
1543 } 1500 }
1544 1501
1545 /* 1502 /*
1546 * Sets the default font used on text based widgets. 1503 * Sets the default font used on text based widgets.
1547 * Parameters: 1504 * Parameters:
1565 char *newfont = NULL; 1522 char *newfont = NULL;
1566 1523
1567 if(font) 1524 if(font)
1568 { 1525 {
1569 char *name = strchr(font, '.'); 1526 char *name = strchr(font, '.');
1570 #if GTK_CHECK_VERSION(3,20,0)
1571 char *Italic = strstr(font, " Italic"); 1527 char *Italic = strstr(font, " Italic");
1572 char *Bold = strstr(font, " Bold"); 1528 char *Bold = strstr(font, " Bold");
1573 #endif
1574 1529
1575 /* Detect Dynamic Windows style font name... 1530 /* Detect Dynamic Windows style font name...
1576 * Format: ##.Fontname 1531 * Format: ##.Fontname
1577 * and convert to CSS or Pango syntax 1532 * and convert to CSS or Pango syntax
1578 */ 1533 */
1579 if(name && (name++) && isdigit(*font)) 1534 if(name && (name++) && isdigit(*font))
1580 { 1535 {
1581 int size = atoi(font); 1536 int size = atoi(font);
1582 #if GTK_CHECK_VERSION(3,20,0)
1583 int len = (Italic ? (Bold ? (Italic > Bold ? (Bold - name) : (Italic - name)) : (Italic - name)) : (Bold ? (Bold - name) : strlen(name))); 1537 int len = (Italic ? (Bold ? (Italic > Bold ? (Bold - name) : (Italic - name)) : (Italic - name)) : (Bold ? (Bold - name) : strlen(name)));
1584 char *newname = alloca(len+1); 1538 char *newname = alloca(len+1);
1585 1539
1586 memset(newname, 0, len+1); 1540 memset(newname, 0, len+1);
1587 strncpy(newname, name, len); 1541 strncpy(newname, name, len);
1588 1542
1589 newfont = g_strdup_printf("%s normal %s %dpx \"%s\"", Italic ? "italic" : "normal", 1543 newfont = g_strdup_printf("%s normal %s %dpx \"%s\"", Italic ? "italic" : "normal",
1590 Bold ? "bold" : "normal", size, newname); 1544 Bold ? "bold" : "normal", size, newname);
1591 #else
1592 newfont = g_strdup_printf("%s %d", name, size);
1593 #endif
1594 } 1545 }
1595 } 1546 }
1596 return newfont; 1547 return newfont;
1597 } 1548 }
1598 1549
1617 gchar *scolor = gdk_rgba_to_string(color); 1568 gchar *scolor = gdk_rgba_to_string(color);
1618 gchar *css = g_strdup_printf ("* { %s: %s; }", element, scolor); 1569 gchar *css = g_strdup_printf ("* { %s: %s; }", element, scolor);
1619 1570
1620 provider = gtk_css_provider_new(); 1571 provider = gtk_css_provider_new();
1621 g_free(scolor); 1572 g_free(scolor);
1622 gtk_css_provider_load_from_data(provider, css, -1, NULL); 1573 gtk_css_provider_load_from_data(provider, css, -1);
1623 g_free(css); 1574 g_free(css);
1624 gtk_style_context_add_provider(scontext, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); 1575 gtk_style_context_add_provider(scontext, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1625 } 1576 }
1626 g_object_set_data(G_OBJECT(widget), dataname, (gpointer)provider); 1577 g_object_set_data(G_OBJECT(widget), dataname, (gpointer)provider);
1627 g_free(dataname); 1578 g_free(dataname);
1644 if(font) 1595 if(font)
1645 { 1596 {
1646 gchar *css = g_strdup_printf ("* { font: %s; }", font); 1597 gchar *css = g_strdup_printf ("* { font: %s; }", font);
1647 1598
1648 provider = gtk_css_provider_new(); 1599 provider = gtk_css_provider_new();
1649 gtk_css_provider_load_from_data(provider, css, -1, NULL); 1600 gtk_css_provider_load_from_data(provider, css, -1);
1650 g_free(css); 1601 g_free(css);
1651 gtk_style_context_add_provider(scontext, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); 1602 gtk_style_context_add_provider(scontext, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1652 } 1603 }
1653 g_object_set_data(G_OBJECT(widget), "_dw_font", (gpointer)provider); 1604 g_object_set_data(G_OBJECT(widget), "_dw_font", (gpointer)provider);
1654 } 1605 }
1676 { 1627 {
1677 GtkWidget *tmp = gtk_frame_get_label_widget(GTK_FRAME(handle)); 1628 GtkWidget *tmp = gtk_frame_get_label_widget(GTK_FRAME(handle));
1678 if(tmp) 1629 if(tmp)
1679 handle2 = tmp; 1630 handle2 = tmp;
1680 } 1631 }
1681 else if(GTK_IS_COMBO_BOX(handle) || GTK_IS_BUTTON(handle)) 1632 else if(GTK_IS_COMBO_BOX(handle))
1682 { 1633 {
1683 GtkWidget *tmp = gtk_bin_get_child(GTK_BIN(handle)); 1634 GtkWidget *tmp = gtk_combo_box_get_child(GTK_COMBO_BOX(handle));
1635 if(tmp)
1636 handle2 = tmp;
1637 }
1638 else if(GTK_IS_BUTTON(handle))
1639 {
1640 GtkWidget *tmp = gtk_button_get_child(GTK_BUTTON(handle));
1684 if(tmp) 1641 if(tmp)
1685 handle2 = tmp; 1642 handle2 = tmp;
1686 } 1643 }
1687 1644
1688 /* Free old font name if one is allocated */ 1645 /* Free old font name if one is allocated */
1757 } 1714 }
1758 } 1715 }
1759 g_free(fontname); 1716 g_free(fontname);
1760 } 1717 }
1761 } 1718 }
1762 gtk_widget_destroy(GTK_WIDGET(fd)); 1719 g_object_unref(G_OBJECT(fd));
1763 return retfont; 1720 return retfont;
1764 } 1721 }
1765 1722
1766 /* 1723 /*
1767 * Gets the font used by a specified window (widget) handle. 1724 * Gets the font used by a specified window (widget) handle.
1933 { 1890 {
1934 /* TODO */ 1891 /* TODO */
1935 return 0; 1892 return 0;
1936 } 1893 }
1937 1894
1938 #if GTK_CHECK_VERSION(3,20,0)
1939 static GdkSeat *_dw_grab_seat = NULL;
1940 #else
1941 static GdkDeviceManager *_dw_grab_manager = NULL;
1942 #endif
1943
1944 /* 1895 /*
1945 * Captures the mouse input to this window. 1896 * Captures the mouse input to this window.
1946 * Parameters: 1897 * Parameters:
1947 * handle: Handle to receive mouse input. 1898 * handle: Handle to receive mouse input.
1948 */ 1899 */
1949 void dw_window_capture(HWND handle) 1900 void dw_window_capture(HWND handle)
1950 { 1901 {
1951 _dw_grab_seat = gdk_display_get_default_seat(gtk_widget_get_display(handle)); 1902 /* TODO: See if this is possible in GTK4 */
1952 gdk_seat_grab (_dw_grab_seat,
1953 gtk_widget_get_window(handle),
1954 GDK_SEAT_CAPABILITY_ALL_POINTING,
1955 FALSE, NULL, NULL, NULL, NULL);
1956 } 1903 }
1957 1904
1958 /* 1905 /*
1959 * Changes the appearance of the mouse pointer. 1906 * Changes the appearance of the mouse pointer.
1960 * Parameters: 1907 * Parameters:
1961 * handle: Handle to widget for which to change. 1908 * handle: Handle to widget for which to change.
1962 * cursortype: ID of the pointer you want. 1909 * cursortype: ID of the pointer you want.
1963 */ 1910 */
1964 void dw_window_set_pointer(HWND handle, int pointertype) 1911 void dw_window_set_pointer(HWND handle, int pointertype)
1965 { 1912 {
1966 GdkCursor *cursor;
1967
1968 if(pointertype > 65535) 1913 if(pointertype > 65535)
1969 { 1914 {
1970 GdkPixbuf *pixbuf = _find_pixbuf(GINT_TO_POINTER(pointertype), NULL, NULL); 1915 GdkPixbuf *pixbuf = _find_pixbuf(GINT_TO_POINTER(pointertype), NULL, NULL);
1971 cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, 8, 8); 1916 GdkCursor *cursor = gdk_cursor_new_from_texture(gdk_texture_new_for_pixbuf(pixbuf), 0, 0, NULL);
1972 } 1917 if(cursor)
1973 else if(!pointertype) 1918 gtk_widget_set_cursor(GTK_WIDGET(handle), cursor);
1974 cursor = NULL; 1919 }
1920 if(pointertype == DW_POINTER_ARROW)
1921 gtk_widget_set_cursor_from_name(GTK_WIDGET(handle), "default");
1922 else if(pointertype == DW_POINTER_CLOCK)
1923 gtk_widget_set_cursor_from_name(GTK_WIDGET(handle), "wait");
1924 else if(pointertype == DW_POINTER_QUESTION)
1925 gtk_widget_set_cursor_from_name(GTK_WIDGET(handle), "help");
1975 else 1926 else
1976 cursor = gdk_cursor_new_for_display(gdk_display_get_default(), pointertype); 1927 gtk_widget_set_cursor(GTK_WIDGET(handle), NULL);
1977 if(handle && gtk_widget_get_window(handle))
1978 gdk_window_set_cursor(gtk_widget_get_window(handle), cursor);
1979 if(cursor)
1980 g_object_unref(cursor);
1981 } 1928 }
1982 1929
1983 /* 1930 /*
1984 * Releases previous mouse capture. 1931 * Releases previous mouse capture.
1985 */ 1932 */
1986 void dw_window_release(void) 1933 void dw_window_release(void)
1987 { 1934 {
1988 if(_dw_grab_seat) 1935 /* TODO: See if this is possible in GTK4 */
1989 gdk_seat_ungrab(_dw_grab_seat);
1990 _dw_grab_seat = NULL;
1991 } 1936 }
1992 1937
1993 /* 1938 /*
1994 * Create a new Window Frame. 1939 * Create a new Window Frame.
1995 * Parameters: 1940 * Parameters:
2004 1949
2005 { 1950 {
2006 GtkWidget *box = dw_box_new(DW_VERT, 0); 1951 GtkWidget *box = dw_box_new(DW_VERT, 0);
2007 GtkWidget *grid = gtk_grid_new(); 1952 GtkWidget *grid = gtk_grid_new();
2008 1953
2009 gtk_widget_show_all(grid); 1954 gtk_widget_show(grid);
2010 1955
2011 last_window = tmp = gtk_window_new(GTK_WINDOW_TOPLEVEL); 1956 last_window = tmp = gtk_window_new();
2012 1957
2013 gtk_window_set_title(GTK_WINDOW(tmp), title); 1958 gtk_window_set_title(GTK_WINDOW(tmp), title);
2014 gtk_window_set_resizable(GTK_WINDOW(tmp), (flStyle & DW_FCF_SIZEBORDER) ? TRUE : FALSE); 1959 gtk_window_set_resizable(GTK_WINDOW(tmp), (flStyle & DW_FCF_SIZEBORDER) ? TRUE : FALSE);
2015 1960
2016 gtk_widget_realize(tmp); 1961 gtk_widget_realize(tmp);
2017
2018 if(flStyle & DW_FCF_TITLEBAR)
2019 flags |= GDK_DECOR_TITLE;
2020
2021 if(flStyle & DW_FCF_MINMAX)
2022 flags |= GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE;
2023
2024 if(flStyle & DW_FCF_SIZEBORDER)
2025 flags |= GDK_DECOR_RESIZEH | GDK_DECOR_BORDER;
2026
2027 if(flStyle & (DW_FCF_BORDER | DW_FCF_DLGBORDER))
2028 flags |= GDK_DECOR_BORDER;
2029 1962
2030 if(flStyle & DW_FCF_FULLSCREEN) 1963 if(flStyle & DW_FCF_FULLSCREEN)
2031 gtk_window_fullscreen(GTK_WINDOW(tmp)); 1964 gtk_window_fullscreen(GTK_WINDOW(tmp));
2032 else 1965 else
2033 { 1966 {
2034 if(flStyle & DW_FCF_MAXIMIZE) 1967 if(flStyle & DW_FCF_MAXIMIZE)
2035 gtk_window_maximize(GTK_WINDOW(tmp)); 1968 gtk_window_maximize(GTK_WINDOW(tmp));
2036 1969
2037 if(flStyle & DW_FCF_MINIMIZE) 1970 if(flStyle & DW_FCF_MINIMIZE)
2038 gtk_window_iconify(GTK_WINDOW(tmp)); 1971 gtk_window_minimize(GTK_WINDOW(tmp));
2039 } 1972 }
2040 1973
2041 /* Either the CLOSEBUTTON or SYSMENU flags should make it deletable */ 1974 /* Either the CLOSEBUTTON or SYSMENU flags should make it deletable */
2042 gtk_window_set_deletable(GTK_WINDOW(tmp), (flStyle & (DW_FCF_CLOSEBUTTON | DW_FCF_SYSMENU)) ? TRUE : FALSE); 1975 gtk_window_set_deletable(GTK_WINDOW(tmp), (flStyle & (DW_FCF_CLOSEBUTTON | DW_FCF_SYSMENU)) ? TRUE : FALSE);
2043 1976
2044 gdk_window_set_decorations(gtk_widget_get_window(tmp), flags);
2045 if(!flags) 1977 if(!flags)
2046 gtk_window_set_decorated(GTK_WINDOW(tmp), FALSE); 1978 gtk_window_set_decorated(GTK_WINDOW(tmp), FALSE);
2047 1979
2048 if(hwndOwner)
2049 gdk_window_reparent(gtk_widget_get_window(GTK_WIDGET(tmp)), gtk_widget_get_window(GTK_WIDGET(hwndOwner)), 0, 0);
2050
2051 if(flStyle & DW_FCF_SIZEBORDER) 1980 if(flStyle & DW_FCF_SIZEBORDER)
2052 g_object_set_data(G_OBJECT(tmp), "_dw_size", GINT_TO_POINTER(1)); 1981 g_object_set_data(G_OBJECT(tmp), "_dw_size", GINT_TO_POINTER(1));
2053 1982
2054 gtk_grid_attach(GTK_GRID(grid), box, 0, 1, 1, 1); 1983 gtk_grid_attach(GTK_GRID(grid), box, 0, 1, 1, 1);
2055 gtk_container_add(GTK_CONTAINER(tmp), grid); 1984 gtk_window_set_child(GTK_WINDOW(tmp), grid);
2056 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box); 1985 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box);
2057 g_object_set_data(G_OBJECT(tmp), "_dw_grid", (gpointer)grid); 1986 g_object_set_data(G_OBJECT(tmp), "_dw_grid", (gpointer)grid);
2058 gtk_widget_add_events(GTK_WIDGET(tmp), GDK_PROPERTY_CHANGE_MASK);
2059 } 1987 }
2060 g_object_set_data(G_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle)); 1988 g_object_set_data(G_OBJECT(tmp), "_dw_style", GINT_TO_POINTER(flStyle));
2061 return tmp; 1989 return tmp;
2062 } 1990 }
2063 1991
2067 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). 1995 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
2068 * pad: Number of pixels to pad around the box. 1996 * pad: Number of pixels to pad around the box.
2069 */ 1997 */
2070 HWND dw_box_new(int type, int pad) 1998 HWND dw_box_new(int type, int pad)
2071 { 1999 {
2072 GtkWidget *tmp, *eventbox; 2000 GtkWidget *tmp;
2073 2001
2074 tmp = gtk_grid_new(); 2002 tmp = gtk_grid_new();
2075 eventbox = gtk_event_box_new();
2076
2077 gtk_widget_show(eventbox);
2078 g_object_set_data(G_OBJECT(tmp), "_dw_eventbox", (gpointer)eventbox);
2079 g_object_set_data(G_OBJECT(tmp), "_dw_boxtype", GINT_TO_POINTER(type)); 2003 g_object_set_data(G_OBJECT(tmp), "_dw_boxtype", GINT_TO_POINTER(type));
2080 g_object_set_data(G_OBJECT(tmp), "_dw_boxpad", GINT_TO_POINTER(pad)); 2004 g_object_set_data(G_OBJECT(tmp), "_dw_boxpad", GINT_TO_POINTER(pad));
2081 gtk_widget_show(tmp); 2005 gtk_widget_show(tmp);
2082 return tmp; 2006 return tmp;
2083 } 2007 }
2086 * Create a new scrollable Box to be packed. 2010 * Create a new scrollable Box to be packed.
2087 * Parameters: 2011 * Parameters:
2088 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal). 2012 * type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
2089 * pad: Number of pixels to pad around the box. 2013 * pad: Number of pixels to pad around the box.
2090 */ 2014 */
2091 HWND dw_scrollbox_new( int type, int pad ) 2015 HWND dw_scrollbox_new(int type, int pad)
2092 { 2016 {
2093 GtkWidget *tmp, *box, *eventbox; 2017 GtkWidget *tmp, *box;
2094 2018
2095 tmp = gtk_scrolled_window_new(NULL, NULL); 2019 tmp = gtk_scrolled_window_new();
2096 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (tmp), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); 2020 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tmp), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2097 2021
2098 box = gtk_grid_new(); 2022 box = gtk_grid_new();
2099 eventbox = gtk_event_box_new(); 2023
2100
2101 gtk_widget_show(eventbox);
2102 g_object_set_data(G_OBJECT(box), "_dw_eventbox", (gpointer)eventbox);
2103 g_object_set_data(G_OBJECT(box), "_dw_boxtype", GINT_TO_POINTER(type)); 2024 g_object_set_data(G_OBJECT(box), "_dw_boxtype", GINT_TO_POINTER(type));
2104 g_object_set_data(G_OBJECT(box), "_dw_boxpad", GINT_TO_POINTER(pad)); 2025 g_object_set_data(G_OBJECT(box), "_dw_boxpad", GINT_TO_POINTER(pad));
2105 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box); 2026 g_object_set_data(G_OBJECT(tmp), "_dw_boxhandle", (gpointer)box);
2106 2027
2107 gtk_container_add(GTK_CONTAINER(tmp), box); 2028 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(tmp), box);
2108 g_object_set_data(G_OBJECT(tmp), "_dw_user", box); 2029 g_object_set_data(G_OBJECT(tmp), "_dw_user", box);
2109 gtk_widget_show(box); 2030 gtk_widget_show(box);
2110 gtk_widget_show(tmp); 2031 gtk_widget_show(tmp);
2111 2032
2112 return tmp; 2033 return tmp;
2170 HWND dw_groupbox_new(int type, int pad, const char *title) 2091 HWND dw_groupbox_new(int type, int pad, const char *title)
2171 { 2092 {
2172 GtkWidget *tmp, *frame; 2093 GtkWidget *tmp, *frame;
2173 2094
2174 frame = gtk_frame_new(NULL); 2095 frame = gtk_frame_new(NULL);
2175 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
2176 gtk_frame_set_label(GTK_FRAME(frame), title && *title ? title : NULL); 2096 gtk_frame_set_label(GTK_FRAME(frame), title && *title ? title : NULL);
2177 2097
2178 tmp = gtk_grid_new(); 2098 tmp = gtk_grid_new();
2179 gtk_container_set_border_width(GTK_CONTAINER(tmp), pad); 2099 /* TODO: Fix this! gtk_container_set_border_width(GTK_CONTAINER(tmp), pad); */
2180 g_object_set_data(G_OBJECT(tmp), "_dw_boxtype", GINT_TO_POINTER(type)); 2100 g_object_set_data(G_OBJECT(tmp), "_dw_boxtype", GINT_TO_POINTER(type));
2181 g_object_set_data(G_OBJECT(tmp), "_dw_boxpad", GINT_TO_POINTER(pad)); 2101 g_object_set_data(G_OBJECT(tmp), "_dw_boxpad", GINT_TO_POINTER(pad));
2182 g_object_set_data(G_OBJECT(frame), "_dw_boxhandle", (gpointer)tmp); 2102 g_object_set_data(G_OBJECT(frame), "_dw_boxhandle", (gpointer)tmp);
2183 gtk_container_add(GTK_CONTAINER(frame), tmp); 2103 gtk_frame_set_child(GTK_FRAME(frame), tmp);
2184 gtk_widget_show(tmp); 2104 gtk_widget_show(tmp);
2185 gtk_widget_show(frame); 2105 gtk_widget_show(frame);
2186 if(_DWDefaultFont) 2106 if(_DWDefaultFont)
2187 dw_window_set_font(frame, _DWDefaultFont); 2107 dw_window_set_font(frame, _DWDefaultFont);
2188 return frame; 2108 return frame;
2231 * id: An ID to be used for getting the resource from the 2151 * id: An ID to be used for getting the resource from the
2232 * resource file. 2152 * resource file.
2233 */ 2153 */
2234 HMENUI dw_menu_new(unsigned long id) 2154 HMENUI dw_menu_new(unsigned long id)
2235 { 2155 {
2236 GtkAccelGroup *accel_group;
2237 HMENUI tmp; 2156 HMENUI tmp;
2238 2157
2239 tmp = gtk_menu_new(); 2158 tmp = gtk_menu_new();
2240 gtk_widget_show(tmp); 2159 gtk_widget_show(tmp);
2241 accel_group = gtk_accel_group_new();
2242 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id)); 2160 g_object_set_data(G_OBJECT(tmp), "_dw_id", GINT_TO_POINTER(id));
2243 g_object_set_data(G_OBJECT(tmp), "_dw_accel", (gpointer)accel_group);
2244 return tmp; 2161 return tmp;
2245 } 2162 }
2246 2163
2247 /* 2164 /*
2248 * Create a menubar on a window. 2165 * Create a menubar on a window.
2251 * If there is no box already packed into the "location", the menu will not appear 2168 * If there is no box already packed into the "location", the menu will not appear
2252 * so tell the user. 2169 * so tell the user.
2253 */ 2170 */
2254 HMENUI dw_menubar_new(HWND location) 2171 HMENUI dw_menubar_new(HWND location)
2255 { 2172 {
2256 GtkAccelGroup *accel_group;
2257 GtkWidget *box; 2173 GtkWidget *box;
2258 HMENUI tmp = 0; 2174 HMENUI tmp = 0;
2259 2175
2260 if(GTK_IS_WINDOW(location) && 2176 if(GTK_IS_WINDOW(location) &&
2261 (box = (GtkWidget *)g_object_get_data(G_OBJECT(location), "_dw_grid"))) 2177 (box = (GtkWidget *)g_object_get_data(G_OBJECT(location), "_dw_grid")))
2262 { 2178 {
2263 /* If there is an existing menu bar, remove it */ 2179 /* If there is an existing menu bar, remove it */
2264 GtkWidget *oldmenu = (GtkWidget *)g_object_get_data(G_OBJECT(location), "_dw_menubar"); 2180 GtkWidget *oldmenu = (GtkWidget *)g_object_get_data(G_OBJECT(location), "_dw_menubar");
2265 if(oldmenu) 2181 if(oldmenu && GTK_IS_WIDGET(oldmenu))
2266 gtk_widget_destroy(oldmenu); 2182 g_object_unref(G_OBJECT(oldmenu));
2267 /* Create a new menu bar */ 2183 /* Create a new menu bar */
2268 tmp = gtk_menu_bar_new(); 2184 tmp = gtk_menu_bar_new();
2269 gtk_widget_show(tmp); 2185 gtk_widget_show(tmp);
2270 accel_group = gtk_accel_group_new();
2271 g_object_set_data(G_OBJECT(tmp), "_dw_accel", (gpointer)accel_group);
2272 /* Save pointers to each other */ 2186 /* Save pointers to each other */
2273 g_object_set_data(G_OBJECT(location), "_dw_menubar", (gpointer)tmp); 2187 g_object_set_data(G_OBJECT(location), "_dw_menubar", (gpointer)tmp);
2274 g_object_set_data(G_OBJECT(tmp), "_dw_window", (gpointer)location); 2188 g_object_set_data(G_OBJECT(tmp), "_dw_window", (gpointer)location);
2275 gtk_grid_attach(GTK_GRID(box), tmp, 0, 0, 1, 1); 2189 gtk_grid_attach(GTK_GRID(box), tmp, 0, 0, 1, 1);
2276 } 2190 }
2291 /* If it is a menu bar, try to delete the reference to it */ 2205 /* If it is a menu bar, try to delete the reference to it */
2292 if(GTK_IS_MENU_BAR(*menu) && 2206 if(GTK_IS_MENU_BAR(*menu) &&
2293 (window = (GtkWidget *)g_object_get_data(G_OBJECT(*menu), "_dw_window"))) 2207 (window = (GtkWidget *)g_object_get_data(G_OBJECT(*menu), "_dw_window")))
2294 g_object_set_data(G_OBJECT(window), "_dw_menubar", NULL); 2208 g_object_set_data(G_OBJECT(window), "_dw_menubar", NULL);
2295 /* Actually destroy the menu */ 2209 /* Actually destroy the menu */
2296 gtk_widget_destroy(*menu); 2210 if(GTK_IS_WIDGET(*menu))
2211 g_object_unref(G_OBJECT(*menu));
2297 *menu = NULL; 2212 *menu = NULL;
2298 } 2213 }
2299 } 2214 }
2300 2215
2301 char _removetilde(char *dest, const char *src) 2216 char _removetilde(char *dest, const char *src)
2540 snprintf(numbuf, 24, "%lu", id); 2455 snprintf(numbuf, 24, "%lu", id);
2541 tmphandle = _find_submenu_id(menu, numbuf); 2456 tmphandle = _find_submenu_id(menu, numbuf);
2542 2457
2543 if(tmphandle) 2458 if(tmphandle)
2544 { 2459 {
2545 gtk_widget_destroy(tmphandle); 2460 if(GTK_IS_WIDGET(tmphandle))
2461 g_object_unref(G_OBJECT(tmphandle));
2546 g_object_set_data(G_OBJECT(menu), numbuf, NULL); 2462 g_object_set_data(G_OBJECT(menu), numbuf, NULL);
2547 ret = DW_ERROR_NONE; 2463 ret = DW_ERROR_NONE;
2548 } 2464 }
2549 return ret; 2465 return ret;
2550 } 2466 }
5583 if(gtk_dialog_run(GTK_DIALOG(cd)) == GTK_RESPONSE_OK) 5499 if(gtk_dialog_run(GTK_DIALOG(cd)) == GTK_RESPONSE_OK)
5584 { 5500 {
5585 gtk_color_chooser_get_rgba(cd, &color); 5501 gtk_color_chooser_get_rgba(cd, &color);
5586 retcolor = DW_RGB((int)(color.red * 255), (int)(color.green * 255), (int)(color.blue * 255)); 5502 retcolor = DW_RGB((int)(color.red * 255), (int)(color.green * 255), (int)(color.blue * 255));
5587 } 5503 }
5588 gtk_widget_destroy(GTK_WIDGET(cd)); 5504 if(GTK_IS_WIDGET(cd))
5505 g_object_unref(G_OBJECT(cd));
5589 return retcolor; 5506 return retcolor;
5590 } 5507 }
5591 5508
5592 /* Draw a point on a window (preferably a render window). 5509 /* Draw a point on a window (preferably a render window).
5593 * Parameters: 5510 * Parameters:
6449 * Parameters: 6366 * Parameters:
6450 * mutex: The handle to the mutex returned by dw_mutex_new(). 6367 * mutex: The handle to the mutex returned by dw_mutex_new().
6451 */ 6368 */
6452 void dw_mutex_lock(HMTX mutex) 6369 void dw_mutex_lock(HMTX mutex)
6453 { 6370 {
6454 /* If we are being called from an event handler we must release
6455 * the GTK mutex so we don't deadlock.
6456 */
6457 if(pthread_self() == _dw_thread)
6458 _dw_gdk_threads_leave();
6459
6460 pthread_mutex_lock(mutex); 6371 pthread_mutex_lock(mutex);
6461
6462 /* And of course relock it when we have acquired the mutext */
6463 if(pthread_self() == _dw_thread)
6464 _dw_gdk_threads_enter();
6465 } 6372 }
6466 6373
6467 /* 6374 /*
6468 * Tries to gain access to the semaphore. 6375 * Tries to gain access to the semaphore.
6469 * Parameters: 6376 * Parameters:
7148 /* 7055 /*
7149 * Cleanly terminates a DW session, should be signal handler safe. 7056 * Cleanly terminates a DW session, should be signal handler safe.
7150 */ 7057 */
7151 void dw_shutdown(void) 7058 void dw_shutdown(void)
7152 { 7059 {
7060 g_main_loop_unref(_DWMainLoop);
7153 } 7061 }
7154 7062
7155 /* 7063 /*
7156 * Cleanly terminates a DW session, should be signal handler safe. 7064 * Cleanly terminates a DW session, should be signal handler safe.
7157 * Parameters: 7065 * Parameters:
7158 * exitcode: Exit code reported to the operating system. 7066 * exitcode: Exit code reported to the operating system.
7159 */ 7067 */
7160 void dw_exit(int exitcode) 7068 void dw_exit(int exitcode)
7161 { 7069 {
7070 dw_shutdown();
7162 exit(exitcode); 7071 exit(exitcode);
7163 } 7072 }
7164 7073
7165 /* Internal function to get the recommended size of scrolled items */ 7074 /* Internal function to get the recommended size of scrolled items */
7166 void _get_scrolled_size(GtkWidget *item, gint *thiswidth, gint *thisheight) 7075 void _get_scrolled_size(GtkWidget *item, gint *thiswidth, gint *thisheight)
7527 /* Decrease the count by 1 */ 7436 /* Decrease the count by 1 */
7528 boxcount--; 7437 boxcount--;
7529 g_object_set_data(G_OBJECT(box), "_dw_boxcount", GINT_TO_POINTER(boxcount)); 7438 g_object_set_data(G_OBJECT(box), "_dw_boxcount", GINT_TO_POINTER(boxcount));
7530 } 7439 }
7531 /* If we haven't incremented the reference count... raise it before removal */ 7440 /* If we haven't incremented the reference count... raise it before removal */
7532 if(item && g_object_get_data(G_OBJECT(item), "_dw_padding")) 7441 if(item && g_object_get_data(G_OBJECT(item), "_dw_padding") && GTK_IS_WIDGET(item))
7533 gtk_widget_destroy(item); 7442 g_object_unref(G_OBJECT(item));
7534 else if(item) 7443 else if(item)
7535 { 7444 {
7536 if(!g_object_get_data(G_OBJECT(item), "_dw_refed")) 7445 if(!g_object_get_data(G_OBJECT(item), "_dw_refed"))
7537 { 7446 {
7538 g_object_ref(G_OBJECT(item)); 7447 g_object_ref(G_OBJECT(item));
7600 void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad) 7509 void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
7601 { 7510 {
7602 _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()"); 7511 _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()");
7603 } 7512 }
7604 7513
7605
7606 union extents_union { guchar **gu_extents; unsigned long **extents; };
7607 static GdkAtom extents_atom = 0;
7608 static time_t extents_time = 0;
7609
7610 static gboolean _dw_property_notify(GtkWidget *window, GdkEventProperty* event, GdkWindow *gdkwindow)
7611 {
7612 /* Check to see if we got a property change */
7613 if(event->state == GDK_PROPERTY_NEW_VALUE && event->atom == extents_atom && event->window == gdkwindow)
7614 extents_time = 0;
7615 return FALSE;
7616 }
7617
7618 /* Internal function to figure out the frame extents of an unmapped window */
7619 void _dw_get_frame_extents(GtkWidget *window, int *vert, int *horz)
7620 {
7621 if(gtk_window_get_decorated(GTK_WINDOW(window)))
7622 {
7623 const char *request = "_NET_REQUEST_FRAME_EXTENTS";
7624 unsigned long *extents = NULL;
7625 union extents_union eu;
7626 GdkAtom request_extents = gdk_atom_intern(request, FALSE);
7627 GdkWindow *gdkwindow = gtk_widget_get_window(window);
7628 GdkDisplay *display = gtk_widget_get_display(window);
7629
7630 if(!extents_atom)
7631 extents_atom = gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE);
7632
7633 /* Set some rational defaults.. just in case */
7634 *vert = 28;
7635 *horz = 12;
7636
7637 /* See if the current window manager supports _NET_REQUEST_FRAME_EXTENTS */
7638 if(gdk_x11_screen_supports_net_wm_hint(gdk_screen_get_default(), request_extents))
7639 {
7640 Display *xdisplay = GDK_DISPLAY_XDISPLAY(display);
7641 GdkWindow *root_window = gdk_get_default_root_window();
7642 Window xroot_window = GDK_WINDOW_XID(root_window);
7643 Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request);
7644 unsigned long window_id = GDK_WINDOW_XID(gdkwindow);
7645 XEvent xevent = {0};
7646 time_t currtime;
7647 gulong connid;
7648
7649 xevent.xclient.type = ClientMessage;
7650 xevent.xclient.message_type = extents_request_atom;
7651 xevent.xclient.display = xdisplay;
7652 xevent.xclient.window = window_id;
7653 xevent.xclient.format = 32;
7654
7655 /* Send the property request */
7656 XSendEvent(xdisplay, xroot_window, False,
7657 (SubstructureRedirectMask | SubstructureNotifyMask),
7658 &xevent);
7659
7660 /* Connect a signal to look for the property change */
7661 connid = g_signal_connect(G_OBJECT(window), "property_notify_event", G_CALLBACK(_dw_property_notify), gdkwindow);
7662
7663 /* Record the request time */
7664 time(&extents_time);
7665
7666 /* Look for the property notify event */
7667 do
7668 {
7669 dw_main_iteration();
7670 time(&currtime);
7671 }
7672 while(currtime - extents_time < 2);
7673
7674 /* Remove the signal handler now that we are done */
7675 g_signal_handler_disconnect(G_OBJECT(window), connid);
7676 }
7677
7678 /* Attempt to retrieve window's frame extents. */
7679 eu.extents = &extents;
7680 if(gdk_property_get(gdkwindow,
7681 extents_atom,
7682 gdk_atom_intern("CARDINAL", FALSE),
7683 0, sizeof(unsigned long)*4, FALSE,
7684 NULL, NULL, NULL, eu.gu_extents))
7685 {
7686 *horz = extents[0] + extents[1];
7687 *vert = extents[2] + extents[3];
7688 }
7689 }
7690 else
7691 *horz = *vert = 0;
7692 }
7693
7694 /* 7514 /*
7695 * Sets the size of a given window (widget). 7515 * Sets the size of a given window (widget).
7696 * Parameters: 7516 * Parameters:
7697 * handle: Window (widget) handle. 7517 * handle: Window (widget) handle.
7698 * width: New width in pixels. 7518 * width: New width in pixels.
7702 { 7522 {
7703 if(!handle) 7523 if(!handle)
7704 return; 7524 return;
7705 7525
7706 if(GTK_IS_WINDOW(handle)) 7526 if(GTK_IS_WINDOW(handle))
7707 { 7527 gtk_window_set_default_size(handle, width, height);
7708 GdkWindow *window = gtk_widget_get_window(handle);
7709 int cx = 0, cy = 0;
7710
7711 /* Window is mapped query the frame size directly */
7712 if(window && gtk_widget_get_mapped(handle))
7713 {
7714 GdkRectangle frame;
7715 gint gwidth, gheight;
7716
7717 /* Calculate the border size */
7718 gdk_window_get_frame_extents(window, &frame);
7719 gdk_window_get_geometry(window, NULL, NULL, &gwidth, &gheight);
7720
7721 cx = frame.width - gwidth;
7722 if(cx < 0)
7723 cx = 0;
7724 cy = frame.height - gheight;
7725 if(cy < 0)
7726 cy = 0;
7727 }
7728 else
7729 {
7730 /* Check if we have cached frame size values */
7731 if(!((cx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(handle), "_dw_frame_width"))) |
7732 (cy = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(handle), "_dw_frame_height")))))
7733 {
7734 /* If not try to ask the window manager for the estimated size...
7735 * and finally if all else fails, guess.
7736 */
7737 _dw_get_frame_extents(handle, &cy, &cx);
7738 /* Cache values for later use */
7739 g_object_set_data(G_OBJECT(handle), "_dw_frame_width", GINT_TO_POINTER(cx));
7740 g_object_set_data(G_OBJECT(handle), "_dw_frame_height", GINT_TO_POINTER(cy));
7741 }
7742 /* Save the size for when it is shown */
7743 g_object_set_data(G_OBJECT(handle), "_dw_width", GINT_TO_POINTER(width));
7744 g_object_set_data(G_OBJECT(handle), "_dw_height", GINT_TO_POINTER(height));
7745 }
7746 /* Resize minus the border size */
7747 if(width > cx && height > cy)
7748 {
7749 gtk_window_resize(GTK_WINDOW(handle), width - cx , height - cy );
7750 gtk_window_set_default_size(GTK_WINDOW(handle), width - cx, height - cy);
7751 }
7752 }
7753 else 7528 else
7754 gtk_widget_set_size_request(handle, width, height); 7529 gtk_widget_set_size_request(handle, width, height);
7755 } 7530 }
7756 7531
7757 /* 7532 /*
9317 { 9092 {
9318 filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( filew ) ); 9093 filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( filew ) );
9319 /*g_free (filename);*/ 9094 /*g_free (filename);*/
9320 } 9095 }
9321 9096
9322 gtk_widget_destroy( filew ); 9097 if(GTK_IS_WIDGET(filew))
9098 g_object_unref(G_OBJECT(filew));
9323 return filename; 9099 return filename;
9324 } 9100 }
9325 9101
9326 9102
9327 /* 9103 /*
9743 * The appname is only required on Windows. If NULL is passed the detected 9519 * The appname is only required on Windows. If NULL is passed the detected
9744 * application name will be used, but a prettier name may be desired. 9520 * application name will be used, but a prettier name may be desired.
9745 */ 9521 */
9746 int dw_app_id_set(const char *appid, const char *appname) 9522 int dw_app_id_set(const char *appid, const char *appname)
9747 { 9523 {
9748 #if GLIB_CHECK_VERSION(2,28,0)
9749 if(g_application_id_is_valid(appid)) 9524 if(g_application_id_is_valid(appid))
9750 { 9525 {
9751 strncpy(_dw_app_id, appid, _DW_APP_ID_SIZE); 9526 strncpy(_dw_app_id, appid, _DW_APP_ID_SIZE);
9752 return DW_ERROR_NONE; 9527 return DW_ERROR_NONE;
9753 } 9528 }
9754 return DW_ERROR_GENERAL; 9529 return DW_ERROR_GENERAL;
9755 #else
9756 return DW_ERROR_UNKNOWN;
9757 #endif
9758 } 9530 }
9759 9531
9760 /* 9532 /*
9761 * Call a function from the window (widget)'s context. 9533 * Call a function from the window (widget)'s context.
9762 * Parameters: 9534 * Parameters: