diff options
-rw-r--r-- | backend/backend.c | 9 | ||||
-rw-r--r-- | backend/meson.build | 5 | ||||
-rw-r--r-- | include/render/gles2.h | 1 | ||||
-rw-r--r-- | include/wlr/render/egl.h | 3 | ||||
-rw-r--r-- | include/wlr/types/wlr_cursor.h | 25 | ||||
-rw-r--r-- | include/wlr/types/wlr_xdg_shell.h | 26 | ||||
-rw-r--r-- | include/wlr/types/wlr_xdg_shell_v6.h | 26 | ||||
-rw-r--r-- | include/xwayland/xwm.h | 1 | ||||
-rw-r--r-- | meson.build | 64 | ||||
-rw-r--r-- | meson_options.txt | 1 | ||||
-rw-r--r-- | render/egl.c | 23 | ||||
-rw-r--r-- | render/gles2/renderer.c | 5 | ||||
-rw-r--r-- | rootston/input.c | 3 | ||||
-rw-r--r-- | rootston/output.c | 1 | ||||
-rw-r--r-- | rootston/seat.c | 27 | ||||
-rw-r--r-- | rootston/xdg_shell.c | 11 | ||||
-rw-r--r-- | rootston/xdg_shell_v6.c | 11 | ||||
-rw-r--r-- | types/wlr_xdg_shell.c | 111 | ||||
-rw-r--r-- | types/wlr_xdg_shell_v6.c | 112 | ||||
-rw-r--r-- | xwayland/selection.c | 97 |
20 files changed, 359 insertions, 203 deletions
diff --git a/backend/backend.c b/backend/backend.c index c67be617..52344dac 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -11,9 +11,14 @@ #include <wlr/backend/multi.h> #include <wlr/backend/session.h> #include <wlr/backend/wayland.h> -#include <wlr/backend/x11.h> +#include <wlr/config.h> #include <wlr/util/log.h> +/* WLR_HAS_X11_BACKEND needs to be after wlr/config.h */ +#ifdef WLR_HAS_X11_BACKEND +#include <wlr/backend/x11.h> +#endif + void wlr_backend_init(struct wlr_backend *backend, const struct wlr_backend_impl *impl) { assert(backend); @@ -94,6 +99,7 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { } } +#ifdef WLR_HAS_X11_BACKEND const char *x11_display = getenv("DISPLAY"); if (x11_display) { struct wlr_backend *x11_backend = @@ -101,6 +107,7 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { wlr_multi_backend_add(backend, x11_backend); return backend; } +#endif // Attempt DRM+libinput struct wlr_session *session = wlr_session_create(display); diff --git a/backend/meson.build b/backend/meson.build index c0ed76f1..a74ea024 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -24,7 +24,6 @@ backend_files = files( 'wayland/output.c', 'wayland/registry.c', 'wayland/wl_seat.c', - 'x11/backend.c', ) backend_deps = [ @@ -50,6 +49,10 @@ if conf_data.get('WLR_HAS_SYSTEMD', false) backend_deps += systemd endif +if conf_data.get('WLR_HAS_X11_BACKEND', false) + backend_files += files('x11/backend.c') +endif + if conf_data.get('WLR_HAS_ELOGIND', false) backend_files += files('session/logind.c') backend_deps += elogind diff --git a/include/render/gles2.h b/include/render/gles2.h index 43a8d648..33ad9a48 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -28,6 +28,7 @@ struct wlr_gles2_renderer { struct wlr_renderer wlr_renderer; struct wlr_egl *egl; + const char *exts_str; struct { GLuint quad; diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index aa429e8e..9f4c0334 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -13,8 +13,7 @@ struct wlr_egl { EGLConfig config; EGLContext context; - const char *egl_exts_str; - const char *gl_exts_str; + const char *exts_str; struct { bool buffer_age; diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index da010972..70dca9f7 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -7,12 +7,37 @@ #include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output.h> +/** + * wlr_cursor implements the behavior of the "cursor", that is, the image on the + * screen typically moved about with a mouse or so. It provides tracking for + * this in global coordinates, and integrates with wlr_output, + * wlr_output_layout, and wlr_input_device. You can use it to abstract multiple + * input devices over a single cursor, constrain cursor movement to the usable + * area of a wlr_output_layout and communicate position updates to the hardware + * cursor, constrain specific input devices to specific outputs or regions of + * the screen, and so on. + */ + struct wlr_cursor_state; struct wlr_cursor { struct wlr_cursor_state *state; double x, y; + /** + * The interpretation of these signals is the responsibility of the + * compositor, but some helpers are provided for your benefit. If you + * receive a relative motion event, for example, you may want to call + * wlr_cursor_move. If you receive an absolute event, call + * wlr_cursor_warp_absolute. If you pass an input device into these + * functions, it will apply the region/output constraints associated with + * that device to the resulting cursor motion. If an output layout is + * attached, these functions will constrain the resulting cursor motion to + * within the usable space of the output layout. + * + * Re-broadcasting these signals to, for example, a wlr_seat, is also your + * responsibility. + */ struct { struct wl_signal motion; struct wl_signal motion_absolute; diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 410663f7..a5cd3d54 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -40,6 +40,9 @@ struct wlr_xdg_popup { bool committed; struct wlr_xdg_surface *parent; struct wlr_seat *seat; + + // Position of the popup relative to the upper left corner of the window + // geometry of the parent surface struct wlr_box geometry; struct wl_list grab_link; // wlr_xdg_popup_grab::popups @@ -74,9 +77,22 @@ struct wlr_xdg_toplevel { struct wlr_xdg_surface *base; struct wlr_xdg_surface *parent; bool added; + struct wlr_xdg_toplevel_state next; // client protocol requests struct wlr_xdg_toplevel_state pending; // user configure requests struct wlr_xdg_toplevel_state current; + + char *title; + char *app_id; + + struct { + struct wl_signal request_maximize; + struct wl_signal request_fullscreen; + struct wl_signal request_minimize; + struct wl_signal request_move; + struct wl_signal request_resize; + struct wl_signal request_show_window_menu; + } events; }; struct wlr_xdg_surface_configure { @@ -106,9 +122,6 @@ struct wlr_xdg_surface { uint32_t configure_next_serial; struct wl_list configure_list; - char *title; - char *app_id; - bool has_next_geometry; struct wlr_box next_geometry; struct wlr_box geometry; @@ -121,13 +134,6 @@ struct wlr_xdg_surface { struct wl_signal new_popup; struct wl_signal map; struct wl_signal unmap; - - struct wl_signal request_maximize; - struct wl_signal request_fullscreen; - struct wl_signal request_minimize; - struct wl_signal request_move; - struct wl_signal request_resize; - struct wl_signal request_show_window_menu; } events; void *data; diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 3bfb97a4..c6820f01 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -40,6 +40,9 @@ struct wlr_xdg_popup_v6 { bool committed; struct wlr_xdg_surface_v6 *parent; struct wlr_seat *seat; + + // Position of the popup relative to the upper left corner of the window + // geometry of the parent surface struct wlr_box geometry; struct wl_list grab_link; // wlr_xdg_popup_grab_v6::popups @@ -74,9 +77,22 @@ struct wlr_xdg_toplevel_v6 { struct wlr_xdg_surface_v6 *base; struct wlr_xdg_surface_v6 *parent; bool added; + struct wlr_xdg_toplevel_v6_state next; // client protocol requests struct wlr_xdg_toplevel_v6_state pending; // user configure requests struct wlr_xdg_toplevel_v6_state current; + + char *title; + char *app_id; + + struct { + struct wl_signal request_maximize; + struct wl_signal request_fullscreen; + struct wl_signal request_minimize; + struct wl_signal request_move; + struct wl_signal request_resize; + struct wl_signal request_show_window_menu; + } events; }; struct wlr_xdg_surface_v6_configure { @@ -106,9 +122,6 @@ struct wlr_xdg_surface_v6 { uint32_t configure_next_serial; struct wl_list configure_list; - char *title; - char *app_id; - bool has_next_geometry; struct wlr_box next_geometry; struct wlr_box geometry; @@ -121,13 +134,6 @@ struct wlr_xdg_surface_v6 { struct wl_signal new_popup; struct wl_signal map; struct wl_signal unmap; - - struct wl_signal request_maximize; - struct wl_signal request_fullscreen; - struct wl_signal request_minimize; - struct wl_signal request_move; - struct wl_signal request_resize; - struct wl_signal request_show_window_menu; } events; void *data; diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 4b15cc84..9e21ea3a 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -2,6 +2,7 @@ #define XWAYLAND_XWM_H #include <wayland-server-core.h> +#include <wlr/config.h> #include <wlr/xwayland.h> #include <xcb/render.h> diff --git a/meson.build b/meson.build index c7ca038c..7740b416 100644 --- a/meson.build +++ b/meson.build @@ -58,14 +58,6 @@ libinput = dependency('libinput', version: '>=1.7.0') xkbcommon = dependency('xkbcommon') udev = dependency('libudev') pixman = dependency('pixman-1') -xcb = dependency('xcb') -xcb_composite = dependency('xcb-composite') -xcb_xfixes = dependency('xcb-xfixes') -xcb_image = dependency('xcb-image') -xcb_render = dependency('xcb-render') -xcb_icccm = dependency('xcb-icccm', required: false) -xcb_errors = dependency('xcb-errors', required: get_option('enable_xcb_errors') == 'true') -x11_xcb = dependency('x11-xcb') libcap = dependency('libcap', required: get_option('enable_libcap') == 'true') systemd = dependency('libsystemd', required: get_option('enable_systemd') == 'true') elogind = dependency('libelogind', required: get_option('enable_elogind') == 'true') @@ -75,14 +67,6 @@ exclude_headers = [] wlr_parts = [] wlr_deps = [] -if xcb_icccm.found() - conf_data.set('WLR_HAS_XCB_ICCCM', true) -endif - -if xcb_errors.found() and get_option('enable_xcb_errors') != 'false' - conf_data.set('WLR_HAS_XCB_ERRORS', true) -endif - if libcap.found() and get_option('enable_libcap') != 'false' conf_data.set('WLR_HAS_LIBCAP', true) wlr_deps += libcap @@ -97,6 +81,38 @@ if elogind.found() and get_option('enable_elogind') != 'false' conf_data.set('WLR_HAS_ELOGIND', true) endif +if get_option('enable_x11_backend') or get_option('enable_xwayland') + xcb = dependency('xcb') + xcb_composite = dependency('xcb-composite') + xcb_xfixes = dependency('xcb-xfixes') + xcb_image = dependency('xcb-image') + xcb_render = dependency('xcb-render') + x11_xcb = dependency('x11-xcb') + + xcb_icccm = dependency('xcb-icccm', required: false) + xcb_errors = dependency('xcb-errors', required: get_option('enable_xcb_errors') == 'true') + + if xcb_icccm.found() + conf_data.set('WLR_HAS_XCB_ICCCM', true) + endif + + if xcb_errors.found() and get_option('enable_xcb_errors') != 'false' + conf_data.set('WLR_HAS_XCB_ERRORS', true) + endif + + wlr_deps += [ + xcb, + xcb_composite, + x11_xcb, + ] +else + add_project_arguments('-DMESA_EGL_NO_X11_HEADERS', language: 'c') +endif + +if get_option('enable_x11_backend') + conf_data.set('WLR_HAS_X11_BACKEND', true) +endif + if get_option('enable_xwayland') subdir('xwayland') wlr_parts += [lib_wlr_xwayland] @@ -138,9 +154,6 @@ wlr_deps += [ xkbcommon, udev, pixman, - xcb, - xcb_composite, - x11_xcb, math, ] @@ -168,12 +181,13 @@ summary = [ '----------------', 'wlroots @0@'.format(meson.project_version()), '', - ' libcap: @0@'.format(conf_data.get('WLR_HAS_LIBCAP', false)), - ' systemd: @0@'.format(conf_data.get('WLR_HAS_SYSTEMD', false)), - ' elogind: @0@'.format(conf_data.get('WLR_HAS_ELOGIND', false)), - ' xwayland: @0@'.format(conf_data.get('WLR_HAS_XWAYLAND', false)), - ' xcb-icccm: @0@'.format(conf_data.get('WLR_HAS_XCB_ICCCM', false)), - ' xcb-errors: @0@'.format(conf_data.get('WLR_HAS_XCB_ERRORS', false)), + ' libcap: @0@'.format(conf_data.get('WLR_HAS_LIBCAP', false)), + ' systemd: @0@'.format(conf_data.get('WLR_HAS_SYSTEMD', false)), + ' elogind: @0@'.format(conf_data.get('WLR_HAS_ELOGIND', false)), + ' xwayland: @0@'.format(conf_data.get('WLR_HAS_XWAYLAND', false)), + ' x11_backend: @0@'.format(conf_data.get('WLR_HAS_X11_BACKEND', false)), + ' xcb-icccm: @0@'.format(conf_data.get('WLR_HAS_XCB_ICCCM', false)), + ' xcb-errors: @0@'.format(conf_data.get('WLR_HAS_XCB_ERRORS', false)), '----------------', '' ] diff --git a/meson_options.txt b/meson_options.txt index 4812b6f8..9e8567d0 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -3,3 +3,4 @@ option('enable_systemd', type: 'combo', choices: ['auto', 'true', 'false'], valu option('enable_elogind', type: 'combo', choices: ['auto', 'true', 'false'], value: 'auto', description: 'Enable support for logind') option('enable_xcb_errors', type: 'combo', choices: ['auto', 'true', 'false'], value: 'auto', description: 'Use xcb-errors util library') option('enable_xwayland', type: 'boolean', value: true, description: 'Enable support X11 applications') +option('enable_x11_backend', type: 'boolean', value: true, description: 'Enable X11 backend') diff --git a/render/egl.c b/render/egl.c index e582b6d3..f2966774 100644 --- a/render/egl.c +++ b/render/egl.c @@ -2,7 +2,6 @@ #include <stdio.h> #include <EGL/egl.h> #include <EGL/eglext.h> -#include <GLES2/gl2.h> #include <stdlib.h> #include <wlr/render/egl.h> #include <wlr/util/log.h> @@ -155,32 +154,28 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, } eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl->context); - egl->egl_exts_str = eglQueryString(egl->display, EGL_EXTENSIONS); - egl->gl_exts_str = (const char*) glGetString(GL_EXTENSIONS); + egl->exts_str = eglQueryString(egl->display, EGL_EXTENSIONS); wlr_log(L_INFO, "Using EGL %d.%d", (int)major, (int)minor); - wlr_log(L_INFO, "Supported EGL extensions: %s", egl->egl_exts_str); + wlr_log(L_INFO, "Supported EGL extensions: %s", egl->exts_str); wlr_log(L_INFO, "EGL vendor: %s", eglQueryString(egl->display, EGL_VENDOR)); - wlr_log(L_INFO, "Using %s", glGetString(GL_VERSION)); - wlr_log(L_INFO, "GL vendor: %s", glGetString(GL_VENDOR)); - wlr_log(L_INFO, "Supported OpenGL ES extensions: %s", egl->gl_exts_str); - if (!check_egl_ext(egl->egl_exts_str, "EGL_WL_bind_wayland_display") || - !check_egl_ext(egl->egl_exts_str, "EGL_KHR_image_base")) { + if (!check_egl_ext(egl->exts_str, "EGL_WL_bind_wayland_display") || + !check_egl_ext(egl->exts_str, "EGL_KHR_image_base")) { wlr_log(L_ERROR, "Required egl extensions not supported"); goto error; } egl->egl_exts.buffer_age = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_buffer_age"); + check_egl_ext(egl->exts_str, "EGL_EXT_buffer_age"); egl->egl_exts.swap_buffers_with_damage = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_swap_buffers_with_damage") || - check_egl_ext(egl->egl_exts_str, "EGL_KHR_swap_buffers_with_damage"); + check_egl_ext(egl->exts_str, "EGL_EXT_swap_buffers_with_damage") || + check_egl_ext(egl->exts_str, "EGL_KHR_swap_buffers_with_damage"); egl->egl_exts.dmabuf_import = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import"); + check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import"); egl->egl_exts.dmabuf_import_modifiers = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import_modifiers") + check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import_modifiers") && eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT; print_dmabuf_formats(egl); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 61665a07..36a62aa7 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -377,6 +377,11 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { renderer->egl = wlr_backend_get_egl(backend); wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); + renderer->exts_str = (const char*) glGetString(GL_EXTENSIONS); + wlr_log(L_INFO, "Using %s", glGetString(GL_VERSION)); + wlr_log(L_INFO, "GL vendor: %s", glGetString(GL_VENDOR)); + wlr_log(L_INFO, "Supported GLES2 extensions: %s", renderer->exts_str); + if (glDebugMessageCallbackKHR && glDebugMessageControlKHR) { glEnable(GL_DEBUG_OUTPUT_KHR); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); diff --git a/rootston/input.c b/rootston/input.c index 657b0946..3e1b06fb 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -2,10 +2,13 @@ #include <stdlib.h> #include <wayland-server.h> #include <wlr/backend/libinput.h> +#include <wlr/config.h> #include <wlr/types/wlr_cursor.h> #include <wlr/util/log.h> #include <wlr/xcursor.h> +#ifdef WLR_HAS_XWAYLAND #include <wlr/xwayland.h> +#endif #include "rootston/config.h" #include "rootston/input.h" #include "rootston/keyboard.h" diff --git a/rootston/output.c b/rootston/output.c index 8d6444d6..52ece54d 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -3,6 +3,7 @@ #include <stdbool.h> #include <stdlib.h> #include <time.h> +#include <wlr/config.h> #include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_output_layout.h> diff --git a/rootston/seat.c b/rootston/seat.c index d2d211ba..bdcad5c7 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -723,6 +723,33 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) { wl_list_insert(&seat->input->server->desktop->views, &view->link); } + + bool unfullscreen = true; + +#ifdef WLR_HAS_XWAYLAND + if (view && view->type == ROOTS_XWAYLAND_VIEW && + view->xwayland_surface->override_redirect) { + unfullscreen = false; + } +#endif + + if (view && unfullscreen) { + struct roots_desktop *desktop = view->desktop; + struct roots_output *output; + struct wlr_box box; + view_get_box(view, &box); + wl_list_for_each(output, &desktop->outputs, link) { + if (output->fullscreen_view && + output->fullscreen_view != view && + wlr_output_layout_intersects( + desktop->layout, + output->wlr_output, &box)) { + view_set_fullscreen(output->fullscreen_view, + false, NULL); + } + } + } + struct roots_view *prev_focus = roots_seat_get_focus(seat); if (view == prev_focus) { return; diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c index 923fbeb4..62b57641 100644 --- a/rootston/xdg_shell.c +++ b/rootston/xdg_shell.c @@ -353,7 +353,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { wl_container_of(listener, desktop, xdg_shell_surface); wlr_log(L_DEBUG, "new xdg toplevel: title=%s, app_id=%s", - surface->title, surface->app_id); + surface->toplevel->title, surface->toplevel->app_id); wlr_xdg_surface_ping(surface); struct roots_xdg_surface *roots_surface = @@ -371,15 +371,16 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { roots_surface->unmap.notify = handle_unmap; wl_signal_add(&surface->events.unmap, &roots_surface->unmap); roots_surface->request_move.notify = handle_request_move; - wl_signal_add(&surface->events.request_move, &roots_surface->request_move); + wl_signal_add(&surface->toplevel->events.request_move, + &roots_surface->request_move); roots_surface->request_resize.notify = handle_request_resize; - wl_signal_add(&surface->events.request_resize, + wl_signal_add(&surface->toplevel->events.request_resize, &roots_surface->request_resize); roots_surface->request_maximize.notify = handle_request_maximize; - wl_signal_add(&surface->events.request_maximize, + wl_signal_add(&surface->toplevel->events.request_maximize, &roots_surface->request_maximize); roots_surface->request_fullscreen.notify = handle_request_fullscreen; - wl_signal_add(&surface->events.request_fullscreen, + wl_signal_add(&surface->toplevel->events.request_fullscreen, &roots_surface->request_fullscreen); roots_surface->new_popup.notify = handle_new_popup; wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 8d1a340e..11bc0180 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -355,7 +355,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_container_of(listener, desktop, xdg_shell_v6_surface); wlr_log(L_DEBUG, "new xdg toplevel: title=%s, app_id=%s", - surface->title, surface->app_id); + surface->toplevel->title, surface->toplevel->app_id); wlr_xdg_surface_v6_ping(surface); struct roots_xdg_surface_v6 *roots_surface = @@ -373,15 +373,16 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { roots_surface->unmap.notify = handle_unmap; wl_signal_add(&surface->events.unmap, &roots_surface->unmap); roots_surface->request_move.notify = handle_request_move; - wl_signal_add(&surface->events.request_move, &roots_surface->request_move); + wl_signal_add(&surface->toplevel->events.request_move, + &roots_surface->request_move); roots_surface->request_resize.notify = handle_request_resize; - wl_signal_add(&surface->events.request_resize, + wl_signal_add(&surface->toplevel->events.request_resize, &roots_surface->request_resize); roots_surface->request_maximize.notify = handle_request_maximize; - wl_signal_add(&surface->events.request_maximize, + wl_signal_add(&surface->toplevel->events.request_maximize, &roots_surface->request_maximize); roots_surface->request_fullscreen.notify = handle_request_fullscreen; - wl_signal_add(&surface->events.request_fullscreen, + wl_signal_add(&surface->toplevel->events.request_fullscreen, &roots_surface->request_fullscreen); roots_surface->new_popup.notify = handle_new_popup; wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); diff --git a/types/wlr_xdg_shell.c b/types/wlr_xdg_shell.c index cf713eb9..382cf839 100644 --- a/types/wlr_xdg_shell.c +++ b/types/wlr_xdg_shell.c @@ -198,16 +198,15 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) { wlr_signal_emit_safe(&surface->events.unmap, surface); } - if (surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { - wl_resource_set_user_data(surface->toplevel->resource, NULL); - free(surface->toplevel); - surface->toplevel = NULL; - } - - if (surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - wl_resource_set_user_data(surface->popup->resource, NULL); - - if (surface->popup->seat) { + switch (surface->role) { + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + free(surface->toplevel->title); + surface->toplevel->title = NULL; + free(surface->toplevel->app_id); + surface->toplevel->app_id = NULL; + break; + case WLR_XDG_SURFACE_ROLE_POPUP: + if (surface->popup->seat != NULL) { struct wlr_xdg_popup_grab *grab = xdg_shell_popup_grab_from_seat(surface->client->shell, surface->popup->seat); @@ -222,11 +221,12 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) { wlr_seat_keyboard_end_grab(grab->seat); } } - } - wl_list_remove(&surface->popup->link); - free(surface->popup); - surface->popup = NULL; + surface->popup->seat = NULL; + } + break; + case WLR_XDG_SURFACE_ROLE_NONE: + assert(false && "not reached"); } struct wlr_xdg_surface_configure *configure, *tmp; @@ -234,13 +234,7 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) { xdg_surface_configure_destroy(configure); } - surface->role = WLR_XDG_SURFACE_ROLE_NONE; - free(surface->title); - surface->title = NULL; - free(surface->app_id); - surface->app_id = NULL; - - surface->added = surface->configured = surface->mapped = false; + surface->configured = surface->mapped = false; surface->configure_serial = 0; if (surface->configure_idle) { wl_event_source_remove(surface->configure_idle); @@ -253,6 +247,29 @@ static void xdg_surface_unmap(struct wlr_xdg_surface *surface) { memset(&surface->next_geometry, 0, sizeof(struct wlr_box)); } +static void xdg_toplevel_destroy(struct wlr_xdg_surface *surface) { + assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); + xdg_surface_unmap(surface); + + wl_resource_set_user_data(surface->toplevel->resource, NULL); + free(surface->toplevel); + surface->toplevel = NULL; + + surface->role = WLR_XDG_SURFACE_ROLE_NONE; +} + +static void xdg_popup_destroy(struct wlr_xdg_surface *surface) { + assert(surface->role == WLR_XDG_SURFACE_ROLE_POPUP); + xdg_surface_unmap(surface); + + wl_resource_set_user_data(surface->popup->resource, NULL); + wl_list_remove(&surface->popup->link); + free(surface->popup); + surface->popup = NULL; + + surface->role = WLR_XDG_SURFACE_ROLE_NONE; +} + static void xdg_surface_destroy(struct wlr_xdg_surface *surface) { if (surface->role != WLR_XDG_SURFACE_ROLE_NONE) { xdg_surface_unmap(surface); @@ -260,6 +277,18 @@ static void xdg_surface_destroy(struct wlr_xdg_surface *surface) { wlr_signal_emit_safe(&surface->events.destroy, surface); + switch (surface->role) { + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + xdg_toplevel_destroy(surface); + break; + case WLR_XDG_SURFACE_ROLE_POPUP: + xdg_popup_destroy(surface); + break; + case WLR_XDG_SURFACE_ROLE_NONE: + // This space is intentionally left blank + break; + } + wl_resource_set_user_data(surface->resource, NULL); wl_list_remove(&surface->link); wl_list_remove(&surface->surface_destroy_listener.link); @@ -574,7 +603,7 @@ static void xdg_popup_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface *surface = xdg_surface_from_xdg_popup_resource(resource); if (surface != NULL) { - xdg_surface_unmap(surface); + xdg_popup_destroy(surface); } } @@ -673,8 +702,8 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client, return; } - free(surface->title); - surface->title = tmp; + free(surface->toplevel->title); + surface->toplevel->title = tmp; } static void xdg_toplevel_handle_set_app_id(struct wl_client *client, @@ -688,8 +717,8 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client, return; } - free(surface->app_id); - surface->app_id = tmp; + free(surface->toplevel->app_id); + surface->toplevel->app_id = tmp; } static void xdg_toplevel_handle_show_window_menu(struct wl_client *client, @@ -720,7 +749,7 @@ static void xdg_toplevel_handle_show_window_menu(struct wl_client *client, .y = y, }; - wlr_signal_emit_safe(&surface->events.request_show_window_menu, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_show_window_menu, &event); } static void xdg_toplevel_handle_move(struct wl_client *client, @@ -749,7 +778,7 @@ static void xdg_toplevel_handle_move(struct wl_client *client, .serial = serial, }; - wlr_signal_emit_safe(&surface->events.request_move, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_move, &event); } static void xdg_toplevel_handle_resize(struct wl_client *client, @@ -779,7 +808,7 @@ static void xdg_toplevel_handle_resize(struct wl_client *client, .edges = edges, }; - wlr_signal_emit_safe(&surface->events.request_resize, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_resize, &event); } static void xdg_toplevel_handle_set_max_size(struct wl_client *client, @@ -803,7 +832,7 @@ static void xdg_toplevel_handle_set_maximized(struct wl_client *client, struct wlr_xdg_surface *surface = xdg_surface_from_xdg_toplevel_resource(resource); surface->toplevel->next.maximized = true; - wlr_signal_emit_safe(&surface->events.request_maximize, surface); + wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface); } static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, @@ -811,7 +840,7 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, struct wlr_xdg_surface *surface = xdg_surface_from_xdg_toplevel_resource(resource); surface->toplevel->next.maximized = false; - wlr_signal_emit_safe(&surface->events.request_maximize, surface); + wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface); } static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, @@ -832,7 +861,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, .output = output, }; - wlr_signal_emit_safe(&surface->events.request_fullscreen, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event); } static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, @@ -848,14 +877,14 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, .output = NULL, }; - wlr_signal_emit_safe(&surface->events.request_fullscreen, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event); } static void xdg_toplevel_handle_set_minimized(struct wl_client *client, struct wl_resource *resource) { struct wlr_xdg_surface *surface = xdg_surface_from_xdg_toplevel_resource(resource); - wlr_signal_emit_safe(&surface->events.request_minimize, surface); + wlr_signal_emit_safe(&surface->toplevel->events.request_minimize, surface); } static const struct xdg_toplevel_interface xdg_toplevel_implementation = { @@ -887,7 +916,7 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface *surface = xdg_surface_from_xdg_toplevel_resource(resource); if (surface != NULL) { - xdg_surface_unmap(surface); + xdg_toplevel_destroy(surface); } } @@ -905,6 +934,12 @@ static void xdg_surface_handle_get_toplevel(struct wl_client *client, wl_resource_post_no_memory(resource); return; } + wl_signal_init(&surface->toplevel->events.request_maximize); + wl_signal_init(&surface->toplevel->events.request_fullscreen); + wl_signal_init(&surface->toplevel->events.request_minimize); + wl_signal_init(&surface->toplevel->events.request_move); + wl_signal_init(&surface->toplevel->events.request_resize); + wl_signal_init(&surface->toplevel->events.request_show_window_menu); surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL; surface->toplevel->base = surface; @@ -1349,12 +1384,6 @@ static void xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client, wl_list_init(&surface->configure_list); wl_list_init(&surface->popups); - wl_signal_init(&surface->events.request_maximize); - wl_signal_init(&surface->events.request_fullscreen); - wl_signal_init(&surface->events.request_minimize); - wl_signal_init(&surface->events.request_move); - wl_signal_init(&surface->events.request_resize); - wl_signal_init(&surface->events.request_show_window_menu); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.ping_timeout); wl_signal_init(&surface->events.new_popup); diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 464e0157..4c40e129 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -198,16 +198,15 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) { wlr_signal_emit_safe(&surface->events.unmap, surface); } - if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { - wl_resource_set_user_data(surface->toplevel->resource, NULL); - free(surface->toplevel); - surface->toplevel = NULL; - } - - if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { - wl_resource_set_user_data(surface->popup->resource, NULL); - - if (surface->popup->seat) { + switch (surface->role) { + case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: + free(surface->toplevel->title); + surface->toplevel->title = NULL; + free(surface->toplevel->app_id); + surface->toplevel->app_id = NULL; + break; + case WLR_XDG_SURFACE_V6_ROLE_POPUP: + if (surface->popup->seat != NULL) { struct wlr_xdg_popup_grab_v6 *grab = xdg_shell_popup_grab_from_seat(surface->client->shell, surface->popup->seat); @@ -222,11 +221,12 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) { wlr_seat_keyboard_end_grab(grab->seat); } } - } - wl_list_remove(&surface->popup->link); - free(surface->popup); - surface->popup = NULL; + surface->popup->seat = NULL; + } + break; + case WLR_XDG_SURFACE_V6_ROLE_NONE: + assert(false && "not reached"); } struct wlr_xdg_surface_v6_configure *configure, *tmp; @@ -234,13 +234,7 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) { xdg_surface_configure_destroy(configure); } - surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE; - free(surface->title); - surface->title = NULL; - free(surface->app_id); - surface->app_id = NULL; - - surface->added = surface->configured = surface->mapped = false; + surface->configured = surface->mapped = false; surface->configure_serial = 0; if (surface->configure_idle) { wl_event_source_remove(surface->configure_idle); @@ -253,6 +247,29 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) { memset(&surface->next_geometry, 0, sizeof(struct wlr_box)); } +static void xdg_toplevel_destroy(struct wlr_xdg_surface_v6 *surface) { + assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); + xdg_surface_unmap(surface); + + wl_resource_set_user_data(surface->toplevel->resource, NULL); + free(surface->toplevel); + surface->toplevel = NULL; + + surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE; +} + +static void xdg_popup_destroy(struct wlr_xdg_surface_v6 *surface) { + assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP); + xdg_surface_unmap(surface); + + wl_resource_set_user_data(surface->popup->resource, NULL); + wl_list_remove(&surface->popup->link); + free(surface->popup); + surface->popup = NULL; + + surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE; +} + static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) { if (surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE) { xdg_surface_unmap(surface); @@ -260,6 +277,18 @@ static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) { wlr_signal_emit_safe(&surface->events.destroy, surface); + switch (surface->role) { + case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: + xdg_toplevel_destroy(surface); + break; + case WLR_XDG_SURFACE_V6_ROLE_POPUP: + xdg_popup_destroy(surface); + break; + case WLR_XDG_SURFACE_V6_ROLE_NONE: + // This space is intentionally left blank + break; + } + wl_resource_set_user_data(surface->resource, NULL); wl_list_remove(&surface->link); wl_list_remove(&surface->surface_destroy_listener.link); @@ -545,7 +574,7 @@ static void xdg_popup_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_popup_resource(resource); if (surface != NULL) { - xdg_surface_unmap(surface); + xdg_popup_destroy(surface); } } @@ -643,8 +672,8 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client, return; } - free(surface->title); - surface->title = tmp; + free(surface->toplevel->title); + surface->toplevel->title = tmp; } static void xdg_toplevel_handle_set_app_id(struct wl_client *client, @@ -657,8 +686,8 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client, return; } - free(surface->app_id); - surface->app_id = tmp; + free(surface->toplevel->app_id); + surface->toplevel->app_id = tmp; } static void xdg_toplevel_handle_show_window_menu(struct wl_client *client, @@ -689,7 +718,8 @@ static void xdg_toplevel_handle_show_window_menu(struct wl_client *client, .y = y, }; - wlr_signal_emit_safe(&surface->events.request_show_window_menu, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_show_window_menu, + &event); } static void xdg_toplevel_handle_move(struct wl_client *client, @@ -718,7 +748,7 @@ static void xdg_toplevel_handle_move(struct wl_client *client, .serial = serial, }; - wlr_signal_emit_safe(&surface->events.request_move, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_move, &event); } static void xdg_toplevel_handle_resize(struct wl_client *client, @@ -748,7 +778,7 @@ static void xdg_toplevel_handle_resize(struct wl_client *client, .edges = edges, }; - wlr_signal_emit_safe(&surface->events.request_resize, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_resize, &event); } static void xdg_toplevel_handle_set_max_size(struct wl_client *client, @@ -772,7 +802,7 @@ static void xdg_toplevel_handle_set_maximized(struct wl_client *client, struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_toplevel_resource(resource); surface->toplevel->next.maximized = true; - wlr_signal_emit_safe(&surface->events.request_maximize, surface); + wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface); } static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, @@ -780,7 +810,7 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_toplevel_resource(resource); surface->toplevel->next.maximized = false; - wlr_signal_emit_safe(&surface->events.request_maximize, surface); + wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface); } static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, @@ -801,7 +831,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, .output = output, }; - wlr_signal_emit_safe(&surface->events.request_fullscreen, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event); } static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, @@ -817,14 +847,14 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, .output = NULL, }; - wlr_signal_emit_safe(&surface->events.request_fullscreen, &event); + wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event); } static void xdg_toplevel_handle_set_minimized(struct wl_client *client, struct wl_resource *resource) { struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_toplevel_resource(resource); - wlr_signal_emit_safe(&surface->events.request_minimize, surface); + wlr_signal_emit_safe(&surface->toplevel->events.request_minimize, surface); } static const struct zxdg_toplevel_v6_interface @@ -856,7 +886,7 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_toplevel_resource(resource); if (surface != NULL) { - xdg_surface_unmap(surface); + xdg_toplevel_destroy(surface); } } @@ -874,6 +904,12 @@ static void xdg_surface_handle_get_toplevel(struct wl_client *client, wl_resource_post_no_memory(resource); return; } + wl_signal_init(&surface->toplevel->events.request_maximize); + wl_signal_init(&surface->toplevel->events.request_fullscreen); + wl_signal_init(&surface->toplevel->events.request_minimize); + wl_signal_init(&surface->toplevel->events.request_move); + wl_signal_init(&surface->toplevel->events.request_resize); + wl_signal_init(&surface->toplevel->events.request_show_window_menu); surface->role = WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL; surface->toplevel->base = surface; @@ -1318,12 +1354,6 @@ static void xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client, wl_list_init(&surface->configure_list); wl_list_init(&surface->popups); - wl_signal_init(&surface->events.request_maximize); - wl_signal_init(&surface->events.request_fullscreen); - wl_signal_init(&surface->events.request_minimize); - wl_signal_init(&surface->events.request_move); - wl_signal_init(&surface->events.request_resize); - wl_signal_init(&surface->events.request_show_window_menu); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.ping_timeout); wl_signal_init(&surface->events.new_popup); diff --git a/xwayland/selection.c b/xwayland/selection.c index 1d390026..72f3de3e 100644 --- a/xwayland/selection.c +++ b/xwayland/selection.c @@ -47,7 +47,21 @@ static int xwm_selection_flush_source_data(struct wlr_xwm_selection *selection) return length; } -static int xwm_read_data_source(int fd, uint32_t mask, void *data) { +static void xwm_data_source_remove_property_source( + struct wlr_xwm_selection *selection) { + if (selection->property_source) { + wl_event_source_remove(selection->property_source); + } + selection->property_source = NULL; +} + +static void xwm_data_source_close_source_fd( + struct wlr_xwm_selection *selection) { + close(selection->source_fd); + selection->source_fd = -1; +} + +static int xwm_data_source_read(int fd, uint32_t mask, void *data) { struct wlr_xwm_selection *selection = data; struct wlr_xwm *xwm = selection->xwm; @@ -72,13 +86,13 @@ static int xwm_read_data_source(int fd, uint32_t mask, void *data) { } wlr_log(L_DEBUG, "read %d (available %d, mask 0x%x) bytes: \"%.*s\"", - len, available, mask, len, (char *) p); + len, available, mask, len, (char *) p); selection->source_data.size = current + len; if (selection->source_data.size >= incr_chunk_size) { if (!selection->incr) { wlr_log(L_DEBUG, "got %zu bytes, starting incr", - selection->source_data.size); + selection->source_data.size); selection->incr = 1; xcb_change_property(xwm->xcb_conn, XCB_PROP_MODE_REPLACE, @@ -89,20 +103,17 @@ static int xwm_read_data_source(int fd, uint32_t mask, void *data) { 1, &incr_chunk_size); selection->property_set = true; selection->flush_property_on_delete = 1; - wl_event_source_remove(selection->property_source); - selection->property_source = NULL; + xwm_data_source_remove_property_source(selection); xwm_selection_send_notify(selection, selection->request.property); } else if (selection->property_set) { - wlr_log(L_DEBUG, "got %zu bytes, waiting for " - "property delete", selection->source_data.size); + wlr_log(L_DEBUG, "got %zu bytes, waiting for property delete", + selection->source_data.size); selection->flush_property_on_delete = 1; - wl_event_source_remove(selection->property_source); - selection->property_source = NULL; + xwm_data_source_remove_property_source(selection); } else { - wlr_log(L_DEBUG, "got %zu bytes, " - "property deleted, setting new property", - selection->source_data.size); + wlr_log(L_DEBUG, "got %zu bytes, property deleted, setting new " + "property", selection->source_data.size); xwm_selection_flush_source_data(selection); } } else if (len == 0 && !selection->incr) { @@ -111,9 +122,8 @@ static int xwm_read_data_source(int fd, uint32_t mask, void *data) { xwm_selection_flush_source_data(selection); xwm_selection_send_notify(selection, selection->request.property); xcb_flush(xwm->xcb_conn); - wl_event_source_remove(selection->property_source); - selection->property_source = NULL; - close(fd); + xwm_data_source_remove_property_source(selection); + xwm_data_source_close_source_fd(selection); wl_array_release(&selection->source_data); selection->request.requestor = XCB_NONE; } else if (len == 0 && selection->incr) { @@ -121,20 +131,16 @@ static int xwm_read_data_source(int fd, uint32_t mask, void *data) { selection->flush_property_on_delete = 1; if (selection->property_set) { - wlr_log(L_DEBUG, "got %zu bytes, waiting for " - "property delete", selection->source_data.size); + wlr_log(L_DEBUG, "got %zu bytes, waiting for property delete", + selection->source_data.size); } else { - wlr_log(L_DEBUG, "got %zu bytes, " - "property deleted, setting new property", - selection->source_data.size); + wlr_log(L_DEBUG, "got %zu bytes, property deleted, setting new " + "property", selection->source_data.size); xwm_selection_flush_source_data(selection); } xcb_flush(xwm->xcb_conn); - wl_event_source_remove(selection->property_source); - selection->property_source = NULL; - close(selection->source_fd); - selection->source_fd = -1; - close(fd); + xwm_data_source_remove_property_source(selection); + xwm_data_source_close_source_fd(selection); } else { wlr_log(L_DEBUG, "nothing happened, buffered the bytes"); } @@ -143,9 +149,8 @@ static int xwm_read_data_source(int fd, uint32_t mask, void *data) { error_out: xwm_selection_send_notify(selection, XCB_ATOM_NONE); - wl_event_source_remove(selection->property_source); - selection->property_source = NULL; - close(fd); + xwm_data_source_remove_property_source(selection); + xwm_data_source_close_source_fd(selection); wl_array_release(&selection->source_data); return 0; } @@ -191,9 +196,7 @@ static void xwm_selection_send_data(struct wlr_xwm_selection *selection, struct wl_event_loop *loop = wl_display_get_event_loop(selection->xwm->xwayland->wl_display); selection->property_source = wl_event_loop_add_fd(loop, - selection->source_fd, - WL_EVENT_READABLE, - xwm_read_data_source, + selection->source_fd, WL_EVENT_READABLE, xwm_data_source_read, selection); xwm_selection_source_send(selection, mime_type, p[1]); @@ -371,7 +374,13 @@ static void xwm_handle_selection_request(struct wlr_xwm *xwm, } } -static int writable_callback(int fd, uint32_t mask, void *data) { +static void xwm_data_source_destroy_property_reply( + struct wlr_xwm_selection *selection) { + free(selection->property_reply); + selection->property_reply = NULL; +} + +static int xwm_data_source_write(int fd, uint32_t mask, void *data) { struct wlr_xwm_selection *selection = data; struct wlr_xwm *xwm = selection->xwm; @@ -381,13 +390,9 @@ static int writable_callback(int fd, uint32_t mask, void *data) { int len = write(fd, property + selection->property_start, remainder); if (len == -1) { - free(selection->property_reply); - selection->property_reply = NULL; - if (selection->property_source) { - wl_event_source_remove(selection->property_source); - } - selection->property_source = NULL; - close(fd); + xwm_data_source_destroy_property_reply(selection); + xwm_data_source_remove_property_source(selection); + xwm_data_source_close_source_fd(selection); wlr_log(L_ERROR, "write error to target fd: %m"); return 1; } @@ -398,12 +403,8 @@ static int writable_callback(int fd, uint32_t mask, void *data) { selection->property_start += len; if (len == remainder) { - free(selection->property_reply); - selection->property_reply = NULL; - if (selection->property_source) { - wl_event_source_remove(selection->property_source); - } - selection->property_source = NULL; + xwm_data_source_destroy_property_reply(selection); + xwm_data_source_remove_property_source(selection); if (selection->incr) { xcb_delete_property(xwm->xcb_conn, @@ -411,7 +412,7 @@ static int writable_callback(int fd, uint32_t mask, void *data) { xwm->atoms[WL_SELECTION]); } else { wlr_log(L_DEBUG, "transfer complete"); - close(fd); + xwm_data_source_close_source_fd(selection); } } @@ -422,13 +423,13 @@ static void xwm_write_property(struct wlr_xwm_selection *selection, xcb_get_property_reply_t *reply) { selection->property_start = 0; selection->property_reply = reply; - writable_callback(selection->source_fd, WL_EVENT_WRITABLE, selection); + xwm_data_source_write(selection->source_fd, WL_EVENT_WRITABLE, selection); if (selection->property_reply) { struct wl_event_loop *loop = wl_display_get_event_loop(selection->xwm->xwayland->wl_display); selection->property_source = wl_event_loop_add_fd(loop, - selection->source_fd, WL_EVENT_WRITABLE, writable_callback, + selection->source_fd, WL_EVENT_WRITABLE, xwm_data_source_write, selection); } } |