mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-18 14:31:43 +01:00
JBR-6212 Wayland: app does not terminate upon Wayland protocol error
(cherry picked from commit 5ad4f8a06d)
This commit is contained in:
@@ -83,10 +83,10 @@ import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@@ -227,7 +227,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
int result = readEvents();
|
||||
if (result == READ_RESULT_ERROR) {
|
||||
log.severe("Wayland protocol I/O error");
|
||||
// TODO: display disconnect handling here?
|
||||
shutDownAfterServerError();
|
||||
break;
|
||||
} else if (result == READ_RESULT_FINISHED_WITH_EVENTS) {
|
||||
AWTAutoShutdown.notifyToolkitThreadBusy(); // busy processing events
|
||||
@@ -249,6 +249,19 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void shutDownAfterServerError() {
|
||||
EventQueue.invokeLater(() -> {
|
||||
var frames = Arrays.asList(Frame.getFrames());
|
||||
Collections.reverse(frames);
|
||||
frames.forEach(frame -> frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)));
|
||||
|
||||
// They've had their chance to exit from the "window closing" handler code. If we have gotten here,
|
||||
// that chance wasn't taken. But we cannot continue because the connection with the server is
|
||||
// no longer available, so let's exit forcibly.
|
||||
System.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If more than this amount milliseconds has passed since the same mouse button click,
|
||||
|
||||
@@ -461,15 +461,30 @@ Java_sun_awt_wl_WLClipboard_initNative(
|
||||
if (payload == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
|
||||
}
|
||||
CHECK_NULL_THROW_OOME_RETURN(env, payload, "failed to allocate memory for DataOfferPayload", 0);
|
||||
CHECK_NULL_THROW_OOME_RETURN(env, payload, "Failed to allocate memory for DataOfferPayload", 0);
|
||||
|
||||
if (!isPrimary) {
|
||||
// TODO: may be needed by DnD also, initialize in a common place
|
||||
wl_data_device = wl_data_device_manager_get_data_device(wl_ddm, wl_seat);
|
||||
if (wl_data_device == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
|
||||
JNU_ThrowByName(env,
|
||||
"java/awt/AWTError",
|
||||
"wl_data_device_manager_get_data_device() failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wl_data_device_add_listener(wl_data_device, &wl_data_device_listener, payload);
|
||||
} else {
|
||||
if (zwp_selection_dm != NULL) {
|
||||
zwp_selection_device = zwp_primary_selection_device_manager_v1_get_device(zwp_selection_dm, wl_seat);
|
||||
if (zwp_selection_device == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
|
||||
JNU_ThrowByName(env,
|
||||
"java/awt/AWTError",
|
||||
"zwp_primary_selection_device_manager_v1_get_device() failed");
|
||||
return 0;
|
||||
}
|
||||
zwp_primary_selection_device_v1_add_listener(zwp_selection_device, &zwp_selection_device_listener, payload);
|
||||
} else {
|
||||
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
|
||||
|
||||
@@ -50,10 +50,12 @@ struct activation_token_list_item {
|
||||
struct activation_token_list_item *next_item;
|
||||
};
|
||||
|
||||
static struct activation_token_list_item *add_token(struct activation_token_list_item *list,
|
||||
struct xdg_activation_token_v1 *token_to_add) {
|
||||
static struct activation_token_list_item *add_token(JNIEnv* env,
|
||||
struct activation_token_list_item *list,
|
||||
struct xdg_activation_token_v1* token_to_add) {
|
||||
struct activation_token_list_item *new_item =
|
||||
(struct activation_token_list_item *) calloc(1, sizeof(struct activation_token_list_item));
|
||||
CHECK_NULL_THROW_OOME_RETURN(env, new_item, "Failed to allocate a Wayland activation token", NULL);
|
||||
new_item->token = token_to_add;
|
||||
new_item->next_item = list;
|
||||
return new_item;
|
||||
@@ -119,7 +121,7 @@ xdg_surface_configure(void *data,
|
||||
|
||||
if (wlFrame->configuredPending) {
|
||||
wlFrame->configuredPending = JNI_FALSE;
|
||||
|
||||
|
||||
JNIEnv *env = getEnv();
|
||||
const jobject nativeFramePeer = (*env)->NewLocalRef(env, wlFrame->nativeFramePeer);
|
||||
if (nativeFramePeer) {
|
||||
@@ -430,15 +432,19 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLSurface
|
||||
struct WLFrame *parentFrame = jlong_to_ptr(parentPtr);
|
||||
if (frame->wl_surface) return;
|
||||
frame->wl_surface = wl_compositor_create_surface(wl_compositor);
|
||||
CHECK_NULL(frame->wl_surface);
|
||||
frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface);
|
||||
CHECK_NULL(frame->xdg_surface);
|
||||
if (gtk_shell1 != NULL) {
|
||||
frame->gtk_surface = gtk_shell1_get_gtk_surface(gtk_shell1, frame->wl_surface);
|
||||
CHECK_NULL(frame->gtk_surface);
|
||||
}
|
||||
|
||||
wl_surface_add_listener(frame->wl_surface, &wl_surface_listener, frame);
|
||||
xdg_surface_add_listener(frame->xdg_surface, &xdg_surface_listener, frame);
|
||||
frame->toplevel = JNI_TRUE;
|
||||
frame->xdg_toplevel = xdg_surface_get_toplevel(frame->xdg_surface);
|
||||
CHECK_NULL(frame->xdg_toplevel);
|
||||
xdg_toplevel_add_listener(frame->xdg_toplevel, &xdg_toplevel_listener, frame);
|
||||
if (title) {
|
||||
FrameSetTitle(env, frame, title);
|
||||
@@ -472,6 +478,7 @@ newPositioner
|
||||
jint width, jint height, jint offsetX, jint offsetY)
|
||||
{
|
||||
struct xdg_positioner *xdg_positioner = xdg_wm_base_create_positioner(xdg_wm_base);
|
||||
CHECK_NULL_RETURN(xdg_positioner, NULL);
|
||||
|
||||
// "For an xdg_positioner object to be considered complete, it must have
|
||||
// a non-zero size set by set_size, and a non-zero anchor rectangle
|
||||
@@ -498,7 +505,9 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
|
||||
struct WLFrame *parentFrame = (struct WLFrame*) parentPtr;
|
||||
if (frame->wl_surface) return;
|
||||
frame->wl_surface = wl_compositor_create_surface(wl_compositor);
|
||||
CHECK_NULL(frame->wl_surface);
|
||||
frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface);
|
||||
CHECK_NULL(frame->xdg_surface);
|
||||
|
||||
wl_surface_add_listener(frame->wl_surface, &wl_surface_listener, frame);
|
||||
xdg_surface_add_listener(frame->xdg_surface, &xdg_surface_listener, frame);
|
||||
@@ -507,7 +516,9 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
|
||||
assert(parentFrame);
|
||||
struct xdg_positioner *xdg_positioner = newPositioner(parentX, parentY, parentWidth, parentHeight,
|
||||
width, height, offsetX, offsetY);
|
||||
CHECK_NULL(xdg_positioner);
|
||||
frame->xdg_popup = xdg_surface_get_popup(frame->xdg_surface, parentFrame->xdg_surface, xdg_positioner);
|
||||
CHECK_NULL(frame->xdg_popup);
|
||||
xdg_popup_add_listener(frame->xdg_popup, &xdg_popup_listener, frame);
|
||||
xdg_positioner_destroy(xdg_positioner);
|
||||
|
||||
@@ -530,6 +541,7 @@ Java_sun_awt_wl_WLComponentPeer_nativeRepositionWLPopup
|
||||
|
||||
struct xdg_positioner *xdg_positioner = newPositioner(parentX, parentY, parentWidth, parentHeight,
|
||||
width, height, offsetX, offsetY);
|
||||
CHECK_NULL(xdg_positioner);
|
||||
static int token = 42; // This will be received by xdg_popup_repositioned(); unused for now.
|
||||
xdg_popup_reposition(frame->xdg_popup, xdg_positioner, token++);
|
||||
xdg_positioner_destroy(xdg_positioner);
|
||||
@@ -599,7 +611,7 @@ JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeStartResize
|
||||
(JNIEnv *env, jobject obj, jlong ptr, jint edges)
|
||||
{
|
||||
struct WLFrame *frame = jlong_to_ptr(ptr);
|
||||
if (frame->toplevel && wl_seat) {
|
||||
if (frame->toplevel && wl_seat && frame->xdg_toplevel != NULL) {
|
||||
xdg_toplevel_resize(frame->xdg_toplevel, wl_seat, last_mouse_pressed_serial, edges);
|
||||
}
|
||||
}
|
||||
@@ -647,12 +659,13 @@ Java_sun_awt_wl_WLComponentPeer_nativeActivate
|
||||
struct WLFrame *frame = jlong_to_ptr(ptr);
|
||||
if (frame->wl_surface && xdg_activation_v1 && wl_seat) {
|
||||
struct xdg_activation_token_v1 *token = xdg_activation_v1_get_activation_token(xdg_activation_v1);
|
||||
CHECK_NULL(token);
|
||||
xdg_activation_token_v1_add_listener(token, &xdg_activation_token_v1_listener, frame);
|
||||
xdg_activation_token_v1_set_serial(token, last_input_or_focus_serial, wl_seat);
|
||||
if (wl_surface_in_focus) {
|
||||
xdg_activation_token_v1_set_surface(token, wl_surface_in_focus);
|
||||
}
|
||||
xdg_activation_token_v1_commit(token);
|
||||
frame->activation_token_list = add_token(frame->activation_token_list, token);
|
||||
frame->activation_token_list = add_token(env, frame->activation_token_list, token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_wl_WLCustomCursor_nativeCreateCustomCursor
|
||||
|
||||
struct WLCursor *cursor = (struct WLCursor*) malloc(sizeof(struct WLCursor));
|
||||
if (!cursor) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Failed to allocate WLCursor");
|
||||
wl_buffer_destroy(buffer);
|
||||
return 0;
|
||||
}
|
||||
@@ -156,6 +157,7 @@ JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeSetCursor
|
||||
if (!wl_cursor_surface)
|
||||
wl_cursor_surface = wl_compositor_create_surface(wl_compositor);
|
||||
|
||||
CHECK_NULL(wl_cursor_surface);
|
||||
if (buffer != last_buffer) {
|
||||
last_buffer = buffer;
|
||||
wl_surface_attach(wl_cursor_surface, buffer, 0, 0);
|
||||
|
||||
@@ -211,11 +211,15 @@ void
|
||||
WLOutputRegister(struct wl_registry *wl_registry, uint32_t id)
|
||||
{
|
||||
WLOutput * output = calloc(1, sizeof(WLOutput));
|
||||
JNIEnv * env = getEnv();
|
||||
CHECK_NULL_THROW_OOME(env, output, "Failed to allocate WLOutput");
|
||||
|
||||
output->id = id;
|
||||
output->wl_output = wl_registry_bind(wl_registry, id, &wl_output_interface, 2);
|
||||
if (output->wl_output == NULL) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "wl_registry_bind() failed");
|
||||
}
|
||||
wl_output_add_listener(output->wl_output, &wl_output_listener, output);
|
||||
|
||||
output->next = outputList;
|
||||
outputList = output;
|
||||
}
|
||||
|
||||
@@ -658,6 +658,8 @@ process_new_listener_before_end_of_init() {
|
||||
// are delivered in-order, this can be used as a barrier to ensure all previous
|
||||
// requests and the resulting events have been handled."
|
||||
struct wl_callback *callback = wl_display_sync(wl_display);
|
||||
if (callback == NULL) return;
|
||||
|
||||
wl_callback_add_listener(callback,
|
||||
&display_sync_listener,
|
||||
callback);
|
||||
@@ -679,12 +681,16 @@ registry_global(void *data, struct wl_registry *wl_registry,
|
||||
wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4);
|
||||
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
||||
xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 3);
|
||||
xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
|
||||
process_new_listener_before_end_of_init();
|
||||
if (xdg_wm_base != NULL) {
|
||||
xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
|
||||
process_new_listener_before_end_of_init();
|
||||
}
|
||||
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||
wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 5);
|
||||
wl_seat_add_listener(wl_seat, &wl_seat_listener, NULL);
|
||||
process_new_listener_before_end_of_init();
|
||||
if (wl_seat != NULL) {
|
||||
wl_seat_add_listener(wl_seat, &wl_seat_listener, NULL);
|
||||
process_new_listener_before_end_of_init();
|
||||
}
|
||||
} else if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||
WLOutputRegister(wl_registry, name);
|
||||
process_new_listener_before_end_of_init();
|
||||
@@ -695,23 +701,25 @@ registry_global(void *data, struct wl_registry *wl_registry,
|
||||
} else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
|
||||
wl_ddm = wl_registry_bind(wl_registry, name,&wl_data_device_manager_interface, 3);
|
||||
} else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
|
||||
zwp_selection_dm = wl_registry_bind(wl_registry, name,&zwp_primary_selection_device_manager_v1_interface, 1);
|
||||
zwp_selection_dm = wl_registry_bind(wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
|
||||
}
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
else if (strcmp(interface, wakefield_interface.name) == 0) {
|
||||
wakefield = wl_registry_bind(wl_registry, name, &wakefield_interface, 1);
|
||||
wakefield_add_listener(wakefield, &wakefield_listener, NULL);
|
||||
robot_queue = wl_display_create_queue(wl_display);
|
||||
if (robot_queue == NULL) {
|
||||
J2dTrace(J2D_TRACE_ERROR, "WLToolkit: Failed to create wakefield robot queue\n");
|
||||
wakefield_destroy(wakefield);
|
||||
wakefield = NULL;
|
||||
} else {
|
||||
wl_proxy_set_queue((struct wl_proxy*)wakefield, robot_queue);
|
||||
if (wakefield != NULL) {
|
||||
wakefield_add_listener(wakefield, &wakefield_listener, NULL);
|
||||
robot_queue = wl_display_create_queue(wl_display);
|
||||
if (robot_queue == NULL) {
|
||||
J2dTrace(J2D_TRACE_ERROR, "WLToolkit: Failed to create wakefield robot queue\n");
|
||||
wakefield_destroy(wakefield);
|
||||
wakefield = NULL;
|
||||
} else {
|
||||
wl_proxy_set_queue((struct wl_proxy*)wakefield, robot_queue);
|
||||
}
|
||||
// TODO: call before destroying the display:
|
||||
// wl_event_queue_destroy(robot_queue);
|
||||
}
|
||||
// TODO: call before destroying the display:
|
||||
// wl_event_queue_destroy(robot_queue);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -931,6 +939,11 @@ Java_sun_awt_wl_WLToolkit_initIDs
|
||||
}
|
||||
|
||||
struct wl_registry *wl_registry = wl_display_get_registry(wl_display);
|
||||
if (wl_registry == NULL) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Failed to obtain Wayland registry");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_registry_add_listener(wl_registry, &wl_registry_listener, NULL);
|
||||
// Process info about Wayland globals here; maybe register more handlers that
|
||||
// will have to be processed later in finalize_init().
|
||||
|
||||
Reference in New Issue
Block a user