Skip to content
This repository has been archived by the owner on Jan 26, 2024. It is now read-only.

WIP: allow xwayland clients to change the override_redirect flag #445

Draft
wants to merge 1 commit into
base: wlroots-next
Choose a base branch
from

Conversation

sevz17
Copy link
Collaborator

@sevz17 sevz17 commented Jun 28, 2023

Closes: #432

@StratusFearMe21
Copy link

Is this PR ready yet? And if not, what work still needs to be done? I'm willing to finish this PR myself if you tell me what's left to be done here

@sevz17
Copy link
Collaborator Author

sevz17 commented Aug 15, 2023

Is this PR ready yet? And if not, what work still needs to be done? I'm willing to finish this PR myself if you tell me what's left to be done here

I managed to avoid the menus closing themselves but they do not receive pointer input when they are above their main window

@sevz17
Copy link
Collaborator Author

sevz17 commented Aug 15, 2023

I tried wlr_xwayland_surface_restack but it didn't help.

@StratusFearMe21
Copy link

StratusFearMe21 commented Aug 16, 2023

Interesting, I've just applied this PR to my dwl and it does work, as long as you keep your left click pressed down when you're in the menu

@Twinkie001
Copy link

Twinkie001 commented Aug 23, 2023

Would this bit of code from Sway be any help?

if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { 
 	// This simply returns focus to the parent surface if there's one available. 
 	// This seems to handle JetBrains issues. 
 	if (xsurface->parent && xsurface->parent->surface 
 			&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) { 
 		seat_set_focus_surface(seat, xsurface->parent->surface, false); 
 		return; 
 	} 
  
 	// Restore focus 
 	struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); 
 	if (previous) { 
 		// Hack to get seat to re-focus the return value of get_focus 
 		seat_set_focus(seat, NULL); 
 		seat_set_focus(seat, previous); 
 	} 

Looks like the end bit is the most important:

		// Hack to get seat to re-focus the return value of get_focus 
 		seat_set_focus(seat, NULL); 
 		seat_set_focus(seat, previous); 

@sevz17
Copy link
Collaborator Author

sevz17 commented Aug 23, 2023

Would this bit of code from Sway be any help?

if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { 
 	// This simply returns focus to the parent surface if there's one available. 
 	// This seems to handle JetBrains issues. 
 	if (xsurface->parent && xsurface->parent->surface 
 			&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) { 
 		seat_set_focus_surface(seat, xsurface->parent->surface, false); 
 		return; 
 	} 
  
 	// Restore focus 
 	struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); 
 	if (previous) { 
 		// Hack to get seat to re-focus the return value of get_focus 
 		seat_set_focus(seat, NULL); 
 		seat_set_focus(seat, previous); 
 	} 

Looks like the end bit is the most important:

		// Hack to get seat to re-focus the return value of get_focus 
 		seat_set_focus(seat, NULL); 
 		seat_set_focus(seat, previous); 

Seems promising, what function does it come from?

@Twinkie001
Copy link

I'll dig around some more, but i found it here: swaywm/sway#6324
It might be this one: swaywm/sway#6764
I'm not much of a C programmer though...

@Twinkie001
Copy link

Here's the actual commit that they did:
swaywm/sway@b2852c5

@Twinkie001
Copy link

Found some more stuff...
here's where they introduce the redirect flag:

static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
	struct sway_xwayland_unmanaged *surface =
		wl_container_of(listener, surface, destroy);
	wl_list_remove(&surface->request_configure.link);
	wl_list_remove(&surface->associate.link);
	wl_list_remove(&surface->dissociate.link);
	wl_list_remove(&surface->destroy.link);
	wl_list_remove(&surface->override_redirect.link);
	wl_list_remove(&surface->request_activate.link);
	free(surface);
}

static void handle_map(struct wl_listener *listener, void *data);

struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface);

static void unmanaged_handle_override_redirect(struct wl_listener *listener, void *data) {
	struct sway_xwayland_unmanaged *surface =
		wl_container_of(listener, surface, override_redirect);
	struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;

	bool mapped = xsurface->surface != NULL && xsurface->surface->mapped;
	if (mapped) {
		unmanaged_handle_unmap(&surface->unmap, NULL);
	}

	unmanaged_handle_destroy(&surface->destroy, NULL);
	xsurface->data = NULL;
	struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface);
	if (mapped) {
		handle_map(&xwayland_view->map, xsurface);
	}
}

static struct sway_xwayland_unmanaged *create_unmanaged(
		struct wlr_xwayland_surface *xsurface) {
	struct sway_xwayland_unmanaged *surface =
		calloc(1, sizeof(struct sway_xwayland_unmanaged));
	if (surface == NULL) {
		sway_log(SWAY_ERROR, "Allocation failed");
		return NULL;
	}

	surface->wlr_xwayland_surface = xsurface;

	wl_signal_add(&xsurface->events.request_configure,
		&surface->request_configure);
	surface->request_configure.notify = unmanaged_handle_request_configure;
	wl_signal_add(&xsurface->events.associate, &surface->associate);
	surface->associate.notify = unmanaged_handle_associate;
	wl_signal_add(&xsurface->events.dissociate, &surface->dissociate);
	surface->dissociate.notify = unmanaged_handle_dissociate;
	wl_signal_add(&xsurface->events.destroy, &surface->destroy);
	surface->destroy.notify = unmanaged_handle_destroy;
	wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
	surface->override_redirect.notify = unmanaged_handle_override_redirect;
	wl_signal_add(&xsurface->events.request_activate, &surface->request_activate);
	surface->request_activate.notify = unmanaged_handle_request_activate;

	return surface;
}


then they add a signal:

wl_signal_add(&xsurface->events.set_override_redirect,
			&xwayland_view->override_redirect);
	xwayland_view->override_redirect.notify = handle_override_redirect;

then this thing:

void handle_xwayland_surface(struct wl_listener *listener, void *data) {
	struct wlr_xwayland_surface *xsurface = data;

	if (xsurface->override_redirect) {
		sway_log(SWAY_DEBUG, "New xwayland unmanaged surface");
		create_unmanaged(xsurface);
		return;
	}

	create_xwayland_view(xsurface);
}

Hope this helps...
I found it in here:
https://github.com/swaywm/sway/blob/master/sway/desktop/xwayland.c

@sevz17
Copy link
Collaborator Author

sevz17 commented Sep 1, 2023

Hm, destroying and creating again the client does not seem to work: https://github.com/sevz17/dwl/tree/fix-unmanaged-v2

@Twinkie001
Copy link

Twinkie001 commented Sep 3, 2023

Well, i tried :)
Actually tried the commit and like StratusFearMe21 said it's pretty usable.
Sorry for being late on this one, I initially built my DWL with wlroots 0.16 and didn't notice this was for wlroots-next so i had to re-build it(i was gonna do that anyway :) ).
At this point it almost feels like it's a mouse issue. It basically doesn't re-focus on the menu when you let go of the mouse.
Maybe this has something to do with the mouse signal or whatever it's called. Basically need to tell it to re-focus the menu on left mouse button release.. I vaguely recall that some WM's(Hyprand?) have options for window rules that allow you to do that.
In this case i guess we'd have to create something like window rule that's baked into the dwl.c
Lmk what you guys think...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants