Repository: godotengine/godot
File: platform/linuxbsd/x11/display_server_x11.cpp (C++)

Code before:
	if (ret.is_empty()) {
		ret = _clipboard_get(XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window);
	}

	return ret;
}

Bool DisplayServerX11::_predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg) {
	if (event->xany.window == *(Window *)arg) {
		return (event->type == SelectionRequest) ||
				(event->type == SelectionNotify);
	} else {
		return False;
	}
}

void DisplayServerX11::_clipboard_transfer_ownership(Atom p_source, Window x11_window) const {
	_THREAD_SAFE_METHOD_

	Window selection_owner = XGetSelectionOwner(x11_display, p_source);

	if (selection_owner != x11_window) {
		return;
	}

	// Block events polling while processing selection events.
	MutexLock mutex_lock(events_mutex);

	Atom clipboard_manager = XInternAtom(x11_display, "CLIPBOARD_MANAGER", False);
	Atom save_targets = XInternAtom(x11_display, "SAVE_TARGETS", False);
	XConvertSelection(x11_display, clipboard_manager, save_targets, None,
			x11_window, CurrentTime);

	// Process events from the queue.
	while (true) {
		if (!_wait_for_events()) {
			// Error or timeout, abort.
			break;
		}

		// Non-blocking wait for next event and remove it from the queue.
		XEvent ev;
		while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_save_targets, (XPointer)&x11_window)) {
			switch (ev.type) {
				case SelectionRequest:
					_handle_selection_request_event(&(ev.xselectionrequest));
					break;

				case SelectionNotify: {
					if (ev.xselection.target == save_targets) {
						// Once SelectionNotify is received, we're done whether it succeeded or not.

Review comment (suggestion):
We'd usually prefer early returns to avoid adding a lot of indentation and make the exit conditions clearer.

So this could be:
```cpp
if (selection_owner == None) {
	return None;
}

// Block events polling while processing selection events.
MutexLock mutex_lock(events_mutex);

...
```

Code after:
				&len, &bytes_left, // data length
				(unsigned char **)&valid_targets);

		if (valid_targets) {
			XFree(valid_targets);
			valid_targets = nullptr;
		}

		if (type == XA_ATOM && bytes_left > 0) {
			// Data is ready and can be processed all at once.
			result = XGetWindowProperty(x11_display, x11_window,
					selection, 0, bytes_left / 4, 0,
					XA_ATOM, &type, &format,
					&len, &dummy, (unsigned char **)&valid_targets);
			if (result == Success) {
				atom_count = len;
			} else {
				print_verbose("Failed to get selection data.");
				return None;
			}
		} else {
			return None;
		}
	} else {
		return None;
	}
	for (unsigned long i = 0; i < atom_count; i++) {
		Atom atom = valid_targets[i];
		if (atom == png) {
			XFree(valid_targets);
			return png;
		}
	}

	XFree(valid_targets);
	return None;
}

String DisplayServerX11::_clipboard_get(Atom p_source, Window x11_window) const {
	String ret;
	Atom utf8_atom = XInternAtom(x11_display, "UTF8_STRING", True);
	if (utf8_atom != None) {
		ret = _clipboard_get_impl(p_source, x11_window, utf8_atom);
	}
	if (ret.is_empty()) {
		ret = _clipboard_get_impl(p_source, x11_window, XA_STRING);
	}
	return ret;
}

String DisplayServerX11::clipboard_get() const {