@@ -61,6 +61,8 @@ const char *const atom_map[ATOM_LAST] = {
61
61
[TIMESTAMP ] = "TIMESTAMP" ,
62
62
[DELETE ] = "DELETE" ,
63
63
[NET_STARTUP_ID ] = "_NET_STARTUP_ID" ,
64
+ [NET_STARTUP_INFO ] = "_NET_STARTUP_INFO" ,
65
+ [NET_STARTUP_INFO_BEGIN ] = "_NET_STARTUP_INFO_BEGIN" ,
64
66
[NET_WM_WINDOW_TYPE_NORMAL ] = "_NET_WM_WINDOW_TYPE_NORMAL" ,
65
67
[NET_WM_WINDOW_TYPE_UTILITY ] = "_NET_WM_WINDOW_TYPE_UTILITY" ,
66
68
[NET_WM_WINDOW_TYPE_TOOLTIP ] = "_NET_WM_WINDOW_TYPE_TOOLTIP" ,
@@ -89,6 +91,14 @@ const char *const atom_map[ATOM_LAST] = {
89
91
[NET_CLIENT_LIST_STACKING ] = "_NET_CLIENT_LIST_STACKING" ,
90
92
};
91
93
94
+ #define STARTUP_INFO_REMOVE_PREFIX "remove: ID="
95
+ struct pending_startup_id {
96
+ char * msg ;
97
+ size_t len ;
98
+ xcb_window_t window ;
99
+ struct wl_list link ;
100
+ };
101
+
92
102
static const struct wlr_surface_role xwayland_surface_role ;
93
103
94
104
bool wlr_surface_is_xwayland_surface (struct wlr_surface * surface ) {
@@ -1361,6 +1371,73 @@ static void xwm_handle_net_active_window_message(struct wlr_xwm *xwm,
1361
1371
wlr_signal_emit_safe (& surface -> events .request_activate , surface );
1362
1372
}
1363
1373
1374
+ static void pending_startup_id_destroy (struct pending_startup_id * pending ) {
1375
+ wl_list_remove (& pending -> link );
1376
+ free (pending -> msg );
1377
+ free (pending );
1378
+ }
1379
+
1380
+ static void xwm_handle_net_startup_info_message (struct wlr_xwm * xwm ,
1381
+ xcb_client_message_event_t * ev ) {
1382
+ struct pending_startup_id * pending , * curr = NULL ;
1383
+ wl_list_for_each (pending , & xwm -> pending_startup_ids , link ) {
1384
+ if (pending -> window == ev -> window ) {
1385
+ curr = pending ;
1386
+ break ;
1387
+ }
1388
+ }
1389
+
1390
+ char * start ;
1391
+ size_t buf_len = sizeof (ev -> data );
1392
+ if (curr ) {
1393
+ curr -> msg = realloc (curr -> msg , curr -> len + buf_len );
1394
+ if (!curr -> msg ) {
1395
+ pending_startup_id_destroy (curr );
1396
+ return ;
1397
+ }
1398
+ start = curr -> msg + curr -> len ;
1399
+ curr -> len += buf_len ;
1400
+ } else {
1401
+ curr = calloc (1 , sizeof (struct pending_startup_id ));
1402
+ if (!curr )
1403
+ return ;
1404
+ curr -> window = ev -> window ;
1405
+ curr -> msg = malloc (buf_len );
1406
+ if (!curr -> msg ) {
1407
+ free (curr );
1408
+ return ;
1409
+ }
1410
+ start = curr -> msg ;
1411
+ curr -> len = buf_len ;
1412
+ wl_list_insert (& xwm -> pending_startup_ids , & curr -> link );
1413
+ }
1414
+
1415
+ char * id = NULL ;
1416
+ const char * data = (const char * )ev -> data .data8 ;
1417
+ for (size_t i = 0 ; i < buf_len ; i ++ ) {
1418
+ start [i ] = data [i ];
1419
+ if (start [i ] == '\0' ) {
1420
+ if (strncmp (curr -> msg , STARTUP_INFO_REMOVE_PREFIX ,
1421
+ strlen (STARTUP_INFO_REMOVE_PREFIX )) == 0 &&
1422
+ strlen (curr -> msg ) > strlen (STARTUP_INFO_REMOVE_PREFIX )) {
1423
+ id = curr -> msg + strlen (STARTUP_INFO_REMOVE_PREFIX );
1424
+ break ;
1425
+ } else {
1426
+ wlr_log (WLR_ERROR , "Unhandled message '%s'\n" , curr -> msg );
1427
+ pending_startup_id_destroy (curr );
1428
+ return ;
1429
+ }
1430
+ }
1431
+ }
1432
+
1433
+ if (id ) {
1434
+ struct wlr_xwayland_remove_startup_info_event data = { id , ev -> window };
1435
+ wlr_log (WLR_DEBUG , "Got startup id: %s" , id );
1436
+ wlr_signal_emit_safe (& xwm -> xwayland -> events .remove_startup_info , & data );
1437
+ pending_startup_id_destroy (curr );
1438
+ }
1439
+ }
1440
+
1364
1441
static void xwm_handle_wm_change_state_message (struct wlr_xwm * xwm ,
1365
1442
xcb_client_message_event_t * ev ) {
1366
1443
struct wlr_xwayland_surface * xsurface = lookup_surface (xwm , ev -> window );
@@ -1399,6 +1476,9 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm,
1399
1476
xwm_handle_wm_protocols_message (xwm , ev );
1400
1477
} else if (ev -> type == xwm -> atoms [NET_ACTIVE_WINDOW ]) {
1401
1478
xwm_handle_net_active_window_message (xwm , ev );
1479
+ } else if (ev -> type == xwm -> atoms [NET_STARTUP_INFO ] ||
1480
+ ev -> type == xwm -> atoms [NET_STARTUP_INFO_BEGIN ]) {
1481
+ xwm_handle_net_startup_info_message (xwm , ev );
1402
1482
} else if (ev -> type == xwm -> atoms [WM_CHANGE_STATE ]) {
1403
1483
xwm_handle_wm_change_state_message (xwm , ev );
1404
1484
} else if (!xwm_handle_selection_client_message (xwm , ev )) {
@@ -1718,6 +1798,11 @@ void xwm_destroy(struct wlr_xwm *xwm) {
1718
1798
wl_list_remove (& xwm -> compositor_destroy .link );
1719
1799
xcb_disconnect (xwm -> xcb_conn );
1720
1800
1801
+ struct pending_startup_id * pending , * next ;
1802
+ wl_list_for_each_safe (pending , next , & xwm -> pending_startup_ids , link ) {
1803
+ pending_startup_id_destroy (pending );
1804
+ }
1805
+
1721
1806
xwm -> xwayland -> xwm = NULL ;
1722
1807
free (xwm );
1723
1808
}
@@ -1958,6 +2043,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
1958
2043
wl_list_init (& xwm -> surfaces );
1959
2044
wl_list_init (& xwm -> surfaces_in_stack_order );
1960
2045
wl_list_init (& xwm -> unpaired_surfaces );
2046
+ wl_list_init (& xwm -> pending_startup_ids );
1961
2047
xwm -> ping_timeout = 10000 ;
1962
2048
1963
2049
xwm -> xcb_conn = xcb_connect_to_fd (wm_fd , NULL );
0 commit comments