diff options
-rwxr-xr-x | glgen.sh | 35 | ||||
-rw-r--r-- | include/rootston/config.h | 1 | ||||
-rw-r--r-- | include/rootston/desktop.h | 7 | ||||
-rw-r--r-- | include/rootston/server.h | 2 | ||||
-rw-r--r-- | include/rootston/view.h | 4 | ||||
-rw-r--r-- | include/wlr/types/wlr_keyboard.h | 1 | ||||
-rw-r--r-- | include/wlr/types/wlr_surface.h | 7 | ||||
-rw-r--r-- | include/wlr/types/wlr_xdg_shell_v6.h | 8 | ||||
-rw-r--r-- | meson.build | 36 | ||||
-rw-r--r-- | meson_options.txt | 1 | ||||
-rw-r--r-- | rootston/config.c | 16 | ||||
-rw-r--r-- | rootston/desktop.c | 90 | ||||
-rw-r--r-- | rootston/meson.build | 33 | ||||
-rw-r--r-- | rootston/rootston.ini.example | 4 | ||||
-rw-r--r-- | types/wlr_surface.c | 49 | ||||
-rw-r--r-- | types/wlr_xdg_shell_v6.c | 41 |
16 files changed, 214 insertions, 121 deletions
@@ -30,28 +30,36 @@ CHECK_FMT='if (!%s) { }' while read -r COMMAND; do - [ ${COMMAND::1} = "-" ] - OPTIONAL=$? + OPTIONAL=0 + FUNC_PTR_FMT='PFN%sPROC' - COMMAND=${COMMAND#-} - if [ ${COMMAND: -2} = "WL" ]; then + case $COMMAND in + -*) + OPTIONAL=1 + ;; + esac + + case $COMMAND in + *WL) FUNC_PTR_FMT='PFN%s' - else - FUNC_PTR_FMT='PFN%sPROC' - fi + ;; + esac + COMMAND=${COMMAND#-} FUNC_PTR=$(printf "$FUNC_PTR_FMT" "$COMMAND" | tr [:lower:] [:upper:]) DECL="$DECL$(printf "\n$DECL_FMT" "$FUNC_PTR" "$COMMAND")" DEFN="$DEFN$(printf "\n$DEFN_FMT" "$FUNC_PTR" "$COMMAND")" LOADER="$LOADER$(printf "\n$LOADER_FMT" "$COMMAND" "$FUNC_PTR" "$COMMAND")" - if [ $OPTIONAL -ne 0 ]; then + if [ $OPTIONAL -eq 0 ]; then LOADER="$LOADER$(printf "\n$CHECK_FMT" "$COMMAND" "$COMMAND")" fi done < $SPEC -if [ ${OUT: -2} = '.h' ]; then + +case $OUT in +*.h) cat > $OUT << EOF #ifndef $INCLUDE_GUARD #define $INCLUDE_GUARD @@ -69,7 +77,8 @@ if [ ${OUT: -2} = '.h' ]; then #endif EOF -elif [ ${OUT: -2} = '.c' ]; then + ;; +*.c) cat > $OUT << EOF #include <wlr/util/log.h> #include "$BASE.h" @@ -86,6 +95,8 @@ elif [ ${OUT: -2} = '.c' ]; then return true; } EOF -else + ;; +*) exit 1 -fi + ;; +esac diff --git a/include/rootston/config.h b/include/rootston/config.h index 545b6742..66347c3c 100644 --- a/include/rootston/config.h +++ b/include/rootston/config.h @@ -27,6 +27,7 @@ struct binding_config { }; struct roots_config { + bool xwayland; // TODO: Multiple cursors, multiseat struct { char *mapped_output; diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 68fc5b94..1225bdcd 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -35,15 +35,18 @@ struct roots_desktop { struct wlr_compositor *compositor; struct wlr_wl_shell *wl_shell; struct wlr_xdg_shell_v6 *xdg_shell_v6; - struct wlr_xwayland *xwayland; struct wlr_gamma_control_manager *gamma_control_manager; struct wlr_screenshooter *screenshooter; struct wl_listener output_add; struct wl_listener output_remove; struct wl_listener xdg_shell_v6_surface; - struct wl_listener xwayland_surface; struct wl_listener wl_shell_surface; + +#ifdef HAS_XWAYLAND + struct wlr_xwayland *xwayland; + struct wl_listener xwayland_surface; +#endif }; struct roots_server; diff --git a/include/rootston/server.h b/include/rootston/server.h index 15e3a4ee..a4eacb7f 100644 --- a/include/rootston/server.h +++ b/include/rootston/server.h @@ -5,7 +5,9 @@ #include <wlr/backend/session.h> #include <wlr/types/wlr_data_device_manager.h> #include <wlr/render.h> +#ifdef HAS_XWAYLAND #include <wlr/xwayland.h> +#endif #include "rootston/config.h" #include "rootston/desktop.h" #include "rootston/input.h" diff --git a/include/rootston/view.h b/include/rootston/view.h index 0b68f93f..af087182 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -58,12 +58,16 @@ struct roots_view { union { struct wlr_wl_shell_surface *wl_shell_surface; struct wlr_xdg_surface_v6 *xdg_surface_v6; +#ifdef HAS_XWAYLAND struct wlr_xwayland_surface *xwayland_surface; +#endif }; union { struct roots_wl_shell_surface *roots_wl_shell_surface; struct roots_xdg_surface_v6 *roots_xdg_surface_v6; +#ifdef HAS_XWAYLAND struct roots_xwayland_surface *roots_xwayland_surface; +#endif }; struct wlr_surface *wlr_surface; // TODO: This would probably be better as a field that's updated on a diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index 99a624c2..a6726a7c 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -3,6 +3,7 @@ #include <wayland-server.h> #include <stdint.h> +#include <stdbool.h> #include <wayland-server.h> #include <xkbcommon/xkbcommon.h> diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 9f898b38..03376788 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -122,4 +122,11 @@ void wlr_surface_make_subsurface(struct wlr_surface *surface, */ struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface); +/** + * Find a subsurface within this surface at the surface-local coordinates. + * Returns the surface and coordinates in the topmost surface coordinate system + * or NULL if no subsurface is found at that location. + */ +struct wlr_subsurface *wlr_surface_subsurface_at(struct wlr_surface *surface, + double sx, double sy, double *sub_x, double *sub_y); #endif diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 00295ec1..48da6604 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -206,4 +206,12 @@ void wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface, */ void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface); +/** + * Find a popup within this surface at the surface-local coordinates. Returns + * the popup and coordinates in the topmost surface coordinate system or NULL if + * no popup is found at that location. + */ +struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at( + struct wlr_xdg_surface_v6 *surface, double sx, double sy, + double *popup_sx, double *popup_sy); #endif diff --git a/meson.build b/meson.build index 179550d6..d885484b 100644 --- a/meson.build +++ b/meson.build @@ -24,7 +24,6 @@ add_project_link_arguments( ) wlr_inc = include_directories('include') -install_subdir('include/wlr', install_dir: 'include') cc = meson.get_compiler('c') @@ -72,13 +71,36 @@ if elogind.found() and get_option('enable_elogind') add_project_arguments('-DHAS_ELOGIND', language: 'c') endif +exclude_files = [] +wlr_parts = [] +conf_data = configuration_data() +if get_option('enable_xwayland') + add_project_arguments('-DHAS_XWAYLAND', language: 'c') + subdir('xwayland') + wlr_parts += [lib_wlr_xwayland] + conf_data.set('WLR_HAS_XWAYLAND', true) +else + exclude_files += ['xwayland.h'] +endif +configure_file(output: 'config.h', install_dir: 'include/wlr', configuration: conf_data) +install_subdir('include/wlr', install_dir: 'include', exclude_files: exclude_files) + + subdir('protocol') subdir('render') subdir('backend') subdir('types') subdir('util') subdir('xcursor') -subdir('xwayland') + +wlr_parts += [ + lib_wl_protos, + lib_wlr_backend, + lib_wlr_render, + lib_wlr_types, + lib_wlr_util, + lib_wlr_xcursor, +] wlr_deps = [ wayland_server, @@ -104,15 +126,7 @@ wlr_deps = [ lib_wlr = library( 'wlroots', files('dummy.c'), - link_whole: [ - lib_wl_protos, - lib_wlr_backend, - lib_wlr_render, - lib_wlr_types, - lib_wlr_util, - lib_wlr_xcursor, - lib_wlr_xwayland, - ], + link_whole: wlr_parts, dependencies: wlr_deps, include_directories: wlr_inc, install: true, diff --git a/meson_options.txt b/meson_options.txt index a3f9ca45..b1e64bd9 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,3 +1,4 @@ option('enable_libcap', type: 'boolean', value: true, description: 'Enable support for capabilities') option('enable_systemd', type: 'boolean', value: true, description: 'Enable support for logind') option('enable_elogind', type: 'boolean', value: true, description: 'Enable support for logind') +option('enable_xwayland', type: 'boolean', value: true, description: 'Enable support X11 applications') diff --git a/rootston/config.c b/rootston/config.c index d454c2d9..4918c8dd 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -5,6 +5,7 @@ #include <limits.h> #include <getopt.h> #include <string.h> +#include <strings.h> #include <unistd.h> #include <sys/param.h> #include <wlr/util/log.h> @@ -114,7 +115,19 @@ static const char *device_prefix = "device:"; static int config_ini_handler(void *user, const char *section, const char *name, const char *value) { struct roots_config *config = user; - if (strncmp(output_prefix, section, strlen(output_prefix)) == 0) { + if (strcmp(section, "core") == 0) { + if (strcmp(name, "xwayland") == 0) { + if (strcasecmp(value, "true") == 0) { + config->xwayland = true; + } else if (strcasecmp(value, "false") == 0) { + config->xwayland = false; + } else { + wlr_log(L_ERROR, "got unknown xwayland value: %s", value); + } + } else { + wlr_log(L_ERROR, "got unknown core config: %s", name); + } + } else if (strncmp(output_prefix, section, strlen(output_prefix)) == 0) { const char *output_name = section + strlen(output_prefix); struct output_config *oc; bool found = false; @@ -251,6 +264,7 @@ static int config_ini_handler(void *user, const char *section, const char *name, struct roots_config *parse_args(int argc, char *argv[]) { struct roots_config *config = calloc(1, sizeof(struct roots_config)); + config->xwayland = true; wl_list_init(&config->outputs); wl_list_init(&config->devices); wl_list_init(&config->bindings); diff --git a/rootston/desktop.c b/rootston/desktop.c index b34fb19e..bef0fad4 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -98,75 +98,6 @@ bool view_initialize(struct roots_view *view) { return centered; } -static struct wlr_subsurface *subsurface_at(struct wlr_surface *surface, - double sx, double sy, double *sub_x, double *sub_y) { - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { - double _sub_x = subsurface->surface->current->subsurface_position.x; - double _sub_y = subsurface->surface->current->subsurface_position.y; - struct wlr_subsurface *sub = - subsurface_at(subsurface->surface, _sub_x + sx, _sub_y + sy, - sub_x, sub_y); - if (sub) { - // TODO: This won't work for nested subsurfaces. Convert sub_x and - // sub_y to the parent coordinate system - return sub; - } - - int sub_width = subsurface->surface->current->buffer_width; - int sub_height = subsurface->surface->current->buffer_height; - if ((sx > _sub_x && sx < _sub_x + sub_width) && - (sy > _sub_y && sy < _sub_y + sub_height)) { - if (pixman_region32_contains_point( - &subsurface->surface->current->input, - sx - _sub_x, sy - _sub_y, NULL)) { - *sub_x = _sub_x; - *sub_y = _sub_y; - return subsurface; - } - } - } - - return NULL; -} - -static struct wlr_xdg_surface_v6 *xdg_v6_popup_at( - struct wlr_xdg_surface_v6 *surface, double sx, double sy, - double *popup_sx, double *popup_sy) { - // XXX: I think this is so complicated because we're mixing geometry - // coordinates with surface coordinates. Input handling should only deal - // with surface coordinates. - struct wlr_xdg_surface_v6 *popup; - wl_list_for_each(popup, &surface->popups, popup_link) { - double _popup_sx = surface->geometry->x + popup->popup_state->geometry.x; - double _popup_sy = surface->geometry->y + popup->popup_state->geometry.y; - int popup_width = popup->popup_state->geometry.width; - int popup_height = popup->popup_state->geometry.height; - - struct wlr_xdg_surface_v6 *_popup = - xdg_v6_popup_at(popup, sx - _popup_sx + popup->geometry->x, - sy - _popup_sy + popup->geometry->y, popup_sx, popup_sy); - if (_popup) { - *popup_sx = *popup_sx + _popup_sx - popup->geometry->x; - *popup_sy = *popup_sy + _popup_sy - popup->geometry->y; - return _popup; - } - - if ((sx > _popup_sx && sx < _popup_sx + popup_width) && - (sy > _popup_sy && sy < _popup_sy + popup_height)) { - if (pixman_region32_contains_point(&popup->surface->current->input, - sx - _popup_sx + popup->geometry->x, - sy - _popup_sy + popup->geometry->y, NULL)) { - *popup_sx = _popup_sx - popup->geometry->x; - *popup_sy = _popup_sy - popup->geometry->y; - return popup; - } - } - } - - return NULL; -} - struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { for (int i = desktop->views->length - 1; i >= 0; --i) { @@ -196,8 +127,8 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, // TODO: test if this works with rotated views double popup_sx, popup_sy; struct wlr_xdg_surface_v6 *popup = - xdg_v6_popup_at(view->xdg_surface_v6, view_sx, view_sy, - &popup_sx, &popup_sy); + wlr_xdg_surface_v6_popup_at(view->xdg_surface_v6, + view_sx, view_sy, &popup_sx, &popup_sy); if (popup) { *sx = view_sx - popup_sx; @@ -209,7 +140,8 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, double sub_x, sub_y; struct wlr_subsurface *subsurface = - subsurface_at(view->wlr_surface, view_sx, view_sy, &sub_x, &sub_y); + wlr_surface_subsurface_at(view->wlr_surface, + view_sx, view_sy, &sub_x, &sub_y); if (subsurface) { *sx = view_sx - sub_x; *sy = view_sy - sub_y; @@ -262,11 +194,15 @@ struct roots_desktop *desktop_create(struct roots_server *server, &desktop->wl_shell_surface); desktop->wl_shell_surface.notify = handle_wl_shell_surface; - desktop->xwayland = wlr_xwayland_create(server->wl_display, - desktop->compositor); - wl_signal_add(&desktop->xwayland->events.new_surface, - &desktop->xwayland_surface); - desktop->xwayland_surface.notify = handle_xwayland_surface; +#ifdef HAS_XWAYLAND + if (config->xwayland) { + desktop->xwayland = wlr_xwayland_create(server->wl_display, + desktop->compositor); + wl_signal_add(&desktop->xwayland->events.new_surface, + &desktop->xwayland_surface); + desktop->xwayland_surface.notify = handle_xwayland_surface; + } +#endif desktop->gamma_control_manager = wlr_gamma_control_manager_create( server->wl_display); diff --git a/rootston/meson.build b/rootston/meson.build index 1eb0704d..7ff79f8e 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -1,17 +1,20 @@ +sources = [ + 'config.c', + 'cursor.c', + 'desktop.c', + 'ini.c', + 'input.c', + 'keyboard.c', + 'main.c', + 'output.c', + 'pointer.c', + 'tablet_tool.c', + 'xdg_shell_v6.c', + 'wl_shell.c', +] +if get_option('enable_xwayland') + sources += ['xwayland.c'] +endif executable( - 'rootston', [ - 'config.c', - 'cursor.c', - 'desktop.c', - 'ini.c', - 'input.c', - 'keyboard.c', - 'main.c', - 'output.c', - 'pointer.c', - 'tablet_tool.c', - 'xdg_shell_v6.c', - 'xwayland.c', - 'wl_shell.c', - ], dependencies: wlroots + 'rootston', sources, dependencies: wlroots ) diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example index 8ac474d4..460efa13 100644 --- a/rootston/rootston.ini.example +++ b/rootston/rootston.ini.example @@ -1,3 +1,7 @@ +[core] +# Disable X11 support. Enabled by default. +xwayland=false + # Single output configuration. String after semicolon must match output's name. [output:VGA-1] # Set logical (layout) coordinates for this screen diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 7b620c6b..ca7a9af5 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -134,6 +134,12 @@ static void surface_set_input_region(struct wl_client *client, } static void wlr_surface_update_size(struct wlr_surface *surface, struct wlr_surface_state *state) { + if (!state->buffer) { + state->height = 0; + state->width = 0; + return; + } + int scale = state->scale; enum wl_output_transform transform = state->transform; @@ -343,8 +349,16 @@ static void wlr_surface_commit_pending(struct wlr_surface *surface) { int32_t oldw = surface->current->buffer_width; int32_t oldh = surface->current->buffer_height; + bool null_buffer_commit = + (surface->pending->invalid & WLR_SURFACE_INVALID_BUFFER && + surface->pending->buffer == NULL); + wlr_surface_move_state(surface, surface->pending, surface->current); + if (null_buffer_commit) { + surface->texture->valid = false; + } + // commit subsurface order struct wlr_subsurface *subsurface; wl_list_for_each_reverse(subsurface, &surface->subsurface_pending_list, @@ -447,9 +461,6 @@ static void surface_commit(struct wl_client *client, void wlr_surface_flush_damage(struct wlr_surface *surface) { if (!surface->current->buffer) { - if (surface->texture->valid) { - // TODO: Detach buffers - } return; } struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer); @@ -835,3 +846,35 @@ struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface) { return surface; } + +struct wlr_subsurface *wlr_surface_subsurface_at(struct wlr_surface *surface, + double sx, double sy, double *sub_x, double *sub_y) { + struct wlr_subsurface *subsurface; + wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { + double _sub_x = subsurface->surface->current->subsurface_position.x; + double _sub_y = subsurface->surface->current->subsurface_position.y; + struct wlr_subsurface *sub = + wlr_surface_subsurface_at(subsurface->surface, _sub_x + sx, + _sub_y + sy, sub_x, sub_y); + if (sub) { + // TODO: This won't work for nested subsurfaces. Convert sub_x and + // sub_y to the parent coordinate system + return sub; + } + + int sub_width = subsurface->surface->current->buffer_width; + int sub_height = subsurface->surface->current->buffer_height; + if ((sx > _sub_x && sx < _sub_x + sub_width) && + (sy > _sub_y && sy < _sub_y + sub_height)) { + if (pixman_region32_contains_point( + &subsurface->surface->current->input, + sx - _sub_x, sy - _sub_y, NULL)) { + *sub_x = _sub_x; + *sub_y = _sub_y; + return subsurface; + } + } + } + + return NULL; +} diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 5f2554f8..a16d3319 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -1301,3 +1301,44 @@ void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface) { assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); zxdg_toplevel_v6_send_close(surface->toplevel_state->resource); } + +struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at( + struct wlr_xdg_surface_v6 *surface, double sx, double sy, + double *popup_sx, double *popup_sy) { + // XXX: I think this is so complicated because we're mixing geometry + // coordinates with surface coordinates. Input handling should only deal + // with surface coordinates. + struct wlr_xdg_surface_v6 *popup; + wl_list_for_each(popup, &surface->popups, popup_link) { + double _popup_sx = + surface->geometry->x + popup->popup_state->geometry.x; + double _popup_sy = + surface->geometry->y + popup->popup_state->geometry.y; + int popup_width = popup->popup_state->geometry.width; + int popup_height = popup->popup_state->geometry.height; + + struct wlr_xdg_surface_v6 *_popup = + wlr_xdg_surface_v6_popup_at(popup, + sx - _popup_sx + popup->geometry->x, + sy - _popup_sy + popup->geometry->y, + popup_sx, popup_sy); + if (_popup) { + *popup_sx = *popup_sx + _popup_sx - popup->geometry->x; + *popup_sy = *popup_sy + _popup_sy - popup->geometry->y; + return _popup; + } + + if ((sx > _popup_sx && sx < _popup_sx + popup_width) && + (sy > _popup_sy && sy < _popup_sy + popup_height)) { + if (pixman_region32_contains_point(&popup->surface->current->input, + sx - _popup_sx + popup->geometry->x, + sy - _popup_sy + popup->geometry->y, NULL)) { + *popup_sx = _popup_sx - popup->geometry->x; + *popup_sy = _popup_sy - popup->geometry->y; + return popup; + } + } + } + + return NULL; +} |