Mercurial > dwindows
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: |