@@ -237,22 +237,33 @@ static void xwm_handle_dnd_finished(struct wlr_xwm *xwm,
237
237
}
238
238
239
239
static bool xwm_add_atom_to_mime_types (struct wlr_xwm * xwm ,
240
- struct wl_array * mime_types , xcb_atom_t atom ) {
240
+ struct wl_array * mime_types , struct wl_array * mime_types_atoms ,
241
+ xcb_atom_t atom ) {
241
242
char * mime_type = xwm_mime_type_from_atom (xwm , atom );
242
243
if (mime_type == NULL ) {
243
244
return false;
244
245
}
246
+
245
247
char * * mime_type_ptr =
246
248
wl_array_add (mime_types , sizeof (* mime_type_ptr ));
247
249
if (mime_type_ptr == NULL ) {
248
250
return false;
249
251
}
250
252
* mime_type_ptr = mime_type ;
253
+
254
+ xcb_atom_t * mime_type_atom_ptr =
255
+ wl_array_add (mime_types_atoms , sizeof (* mime_type_atom_ptr ));
256
+ if (mime_type_atom_ptr == NULL ) {
257
+ return false;
258
+ }
259
+ * mime_type_atom_ptr = atom ;
260
+
251
261
return true;
252
262
}
253
263
254
264
static bool xwm_dnd_get_mime_types (struct wlr_xwm * xwm ,
255
- struct wl_array * mime_types , xcb_window_t source ) {
265
+ struct wl_array * mime_types , struct wl_array * mime_types_atoms ,
266
+ xcb_window_t source ) {
256
267
xcb_get_property_cookie_t cookie = xcb_get_property (xwm -> xcb_conn ,
257
268
1 , // delete
258
269
source ,
@@ -274,7 +285,8 @@ static bool xwm_dnd_get_mime_types(struct wlr_xwm *xwm,
274
285
275
286
xcb_atom_t * atoms = xcb_get_property_value (reply );
276
287
for (uint32_t i = 0 ; i < reply -> value_len ; ++ i ) {
277
- if (!xwm_add_atom_to_mime_types (xwm , mime_types , atoms [i ])) {
288
+ if (!xwm_add_atom_to_mime_types (xwm , mime_types , mime_types_atoms ,
289
+ atoms [i ])) {
278
290
wlr_log (L_ERROR , "failed to add MIME type atom to list" );
279
291
goto error ;
280
292
}
@@ -307,22 +319,31 @@ static void xwm_handle_dnd_enter(struct wlr_xwm *xwm,
307
319
return ;
308
320
}
309
321
310
- struct wl_array mime_types ;
311
- wl_array_init (& mime_types );
322
+ if (xwm -> incoming_drag == NULL ) {
323
+ wlr_log (L_DEBUG , "ignoring XdndEnter client message because "
324
+ "no xwayland drag is being performed" );
325
+ return ;
326
+ }
327
+
328
+ struct wlr_xwayland_data_source * source =
329
+ xwayland_data_source_from_wlr_data_source (xwm -> incoming_drag -> source );
330
+
312
331
if ((data -> data32 [1 ] & 1 ) == 0 ) {
313
332
// Less than 3 MIME types, those are in the message data
314
333
for (size_t i = 0 ; i < 3 ; ++ i ) {
315
334
xcb_atom_t atom = data -> data32 [2 + i ];
316
335
if (atom == XCB_ATOM_NONE ) {
317
336
break ;
318
337
}
319
- if (!xwm_add_atom_to_mime_types (xwm , & mime_types , atom )) {
338
+ if (!xwm_add_atom_to_mime_types (xwm , & source -> base .mime_types ,
339
+ & source -> mime_types_atoms , atom )) {
320
340
wlr_log (L_ERROR , "failed to add MIME type atom to list" );
321
341
break ;
322
342
}
323
343
}
324
344
} else {
325
- if (!xwm_dnd_get_mime_types (xwm , & mime_types , source_window )) {
345
+ if (!xwm_dnd_get_mime_types (xwm , & source -> base .mime_types ,
346
+ & source -> mime_types_atoms , source_window )) {
326
347
wlr_log (L_ERROR , "failed to add MIME type atom to list" );
327
348
}
328
349
}
@@ -358,9 +379,38 @@ int xwm_dnd_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
358
379
selection -> owner = event -> owner ;
359
380
360
381
if (event -> owner != XCB_ATOM_NONE ) {
361
- // TODO: start grab
382
+ wlr_log (L_INFO , "start grab" );
383
+
384
+ xcb_map_window (xwm -> xcb_conn , xwm -> dnd_window );
385
+ const static uint32_t values [] = { XCB_STACK_MODE_ABOVE };
386
+ xcb_configure_window (xwm -> xcb_conn , xwm -> dnd_window ,
387
+ XCB_CONFIG_WINDOW_STACK_MODE , values );
388
+
389
+ struct wlr_seat * seat = selection -> xwm -> seat ;
390
+ struct wlr_seat_client * seat_client = wlr_seat_client_for_wl_client (
391
+ seat , selection -> xwm -> xwayland -> client );
392
+
393
+ struct wlr_xwayland_data_source * source =
394
+ xwayland_data_source_create (selection );
395
+ if (source == NULL ) {
396
+ return 0 ;
397
+ }
398
+
399
+ selection -> xwm -> incoming_drag =
400
+ wlr_seat_client_start_grab (seat_client , & source -> base , NULL , NULL );
401
+ if (selection -> xwm -> incoming_drag == NULL ) {
402
+ wlr_log (L_ERROR , "could not start grab" );
403
+ }
362
404
} else {
363
- // TODO: end grab
405
+ wlr_log (L_INFO , "end grab" );
406
+
407
+ const static uint32_t values [] = { XCB_STACK_MODE_BELOW };
408
+ xcb_configure_window (xwm -> xcb_conn , xwm -> dnd_window ,
409
+ XCB_CONFIG_WINDOW_STACK_MODE , values );
410
+ xcb_unmap_window (xwm -> xcb_conn , xwm -> dnd_window );
411
+
412
+ // TODO: drag_end(selection->xwm->incoming_drag)
413
+ selection -> xwm -> incoming_drag = NULL ;
364
414
}
365
415
366
416
return 1 ;
0 commit comments