diff --git a/.build.yml b/.build.yml index 8b2f9c1f..4b3e197d 100644 --- a/.build.yml +++ b/.build.yml @@ -25,4 +25,4 @@ tasks: ninja - clang: | cd wlroots/build-clang - ninja + ninja scan-build diff --git a/backend/drm/drm.c b/backend/drm/drm.c index a666ce71..5396dcd4 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -344,7 +344,8 @@ static void drm_connector_start_renderer(struct wlr_drm_connector *conn) { void enable_drm_connector(struct wlr_output *output, bool enable) { struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output; - if (conn->state != WLR_DRM_CONN_CONNECTED) { + if (conn->state != WLR_DRM_CONN_CONNECTED + && conn->state != WLR_DRM_CONN_NEEDS_MODESET) { return; } @@ -563,7 +564,7 @@ static bool drm_connector_set_mode(struct wlr_output *output, struct wlr_drm_crtc *crtc = conn->crtc; if (!crtc) { wlr_log(WLR_ERROR, "Unable to match %s with a CRTC", conn->output.name); - goto error_conn; + return false; } wlr_log(WLR_DEBUG, "%s: crtc=%td ovr=%td pri=%td cur=%td", conn->output.name, crtc - drm->crtcs, @@ -867,7 +868,9 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { // +1 so length can never be 0, which is undefined behaviour. // Last element isn't used. bool seen[seen_len + 1]; - memset(seen, 0, sizeof(seen)); + memset(seen, false, sizeof(seen)); + size_t new_outputs_len = 0; + struct wlr_drm_connector *new_outputs[res->count_connectors + 1]; for (int i = 0; i < res->count_connectors; ++i) { drmModeConnector *drm_conn = drmModeGetConnector(drm->fd, @@ -973,13 +976,10 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { wl_list_insert(&wlr_conn->output.modes, &mode->wlr_mode.link); } - wlr_output_update_enabled(&wlr_conn->output, true); + wlr_output_update_enabled(&wlr_conn->output, wlr_conn->crtc != NULL); wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET; - wlr_log(WLR_INFO, "Sending modesetting signal for '%s'", - wlr_conn->output.name); - wlr_signal_emit_safe(&drm->backend.events.new_output, - &wlr_conn->output); + new_outputs[new_outputs_len++] = wlr_conn; } else if (wlr_conn->state == WLR_DRM_CONN_CONNECTED && drm_conn->connection != DRM_MODE_CONNECTED) { wlr_log(WLR_INFO, "'%s' disconnected", wlr_conn->output.name); @@ -1010,6 +1010,15 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { wl_list_remove(&conn->link); free(conn); } + + for (size_t i = 0; i < new_outputs_len; ++i) { + struct wlr_drm_connector *conn = new_outputs[i]; + + wlr_log(WLR_INFO, "Requesting modeset for '%s'", + conn->output.name); + wlr_signal_emit_safe(&drm->backend.events.new_output, + &conn->output); + } } static void page_flip_handler(int fd, unsigned seq, diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 579a11cf..0642f925 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -28,7 +28,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, ++group->ring_count; } } - group->rings = calloc(sizeof(int), group->ring_count); + group->rings = calloc(sizeof(unsigned int), group->ring_count); size_t ring = 0; for (size_t i = 0; i < pad->ring_count; ++i) { if (libinput_tablet_pad_mode_group_has_ring(li_group, i)) { @@ -41,7 +41,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, ++group->strip_count; } } - group->strips = calloc(sizeof(int), group->strip_count); + group->strips = calloc(sizeof(unsigned int), group->strip_count); size_t strip = 0; for (size_t i = 0; i < pad->strip_count; ++i) { if (libinput_tablet_pad_mode_group_has_strip(li_group, i)) { @@ -54,7 +54,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, ++group->button_count; } } - group->buttons = calloc(sizeof(int), group->button_count); + group->buttons = calloc(sizeof(unsigned int), group->button_count); size_t button = 0; for (size_t i = 0; i < pad->button_count; ++i) { if (libinput_tablet_pad_mode_group_has_button(li_group, i)) { diff --git a/examples/idle.c b/examples/idle.c index 30e106db..87a03924 100644 --- a/examples/idle.c +++ b/examples/idle.c @@ -152,14 +152,20 @@ int main(int argc, char *argv[]) { .display = display, }; - if (simulate_activity_timeout != 0 && simulate_activity_timeout < close_timeout) { + bool create_t1 = (simulate_activity_timeout != 0) && + (simulate_activity_timeout < close_timeout); + + if (create_t1) { if (pthread_create(&t1, NULL, &simulate_activity, (void *)&arg) != 0) { return -1; } } - if (close_timeout != 0) { + + bool create_t2 = (close_timeout != 0); + + if (create_t2) { if (pthread_create(&t2, NULL, &close_program, (void *)&arg) != 0) { - if (simulate_activity_timeout != 0) { + if (create_t1) { pthread_cancel(t1); } return -1; @@ -170,18 +176,19 @@ int main(int argc, char *argv[]) { fprintf(stdout, "waiting\n"); if (pthread_create(&t3, NULL, &main_loop, (void *)display) != 0) { - if (simulate_activity_timeout != 0) { + if (create_t1) { pthread_cancel(t1); } - if (close_timeout != 0 ) { + if (create_t2) { pthread_cancel(t2); } + return -1; } - if (simulate_activity_timeout != 0) { + if (create_t1) { pthread_join(t1, NULL); } - if (close_timeout != 0) { + if (create_t2) { pthread_join(t2, NULL); } pthread_cancel(t3); diff --git a/examples/meson.build b/examples/meson.build index 0fb37a9e..b5ad6c98 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -20,31 +20,31 @@ endif examples = { 'simple': { 'src': 'simple.c', - 'dep': wlroots, + 'dep': [wlroots], }, 'pointer': { 'src': 'pointer.c', - 'dep': wlroots, + 'dep': [wlroots], }, 'touch': { 'src': ['touch.c', 'cat.c'], - 'dep': wlroots, + 'dep': [wlroots], }, 'tablet': { 'src': 'tablet.c', - 'dep': wlroots, + 'dep': [wlroots], }, 'rotation': { 'src': ['rotation.c', 'cat.c'], - 'dep': wlroots, + 'dep': [wlroots], }, 'multi-pointer': { 'src': 'multi-pointer.c', - 'dep': wlroots, + 'dep': [wlroots], }, 'output-layout': { 'src': ['output-layout.c', 'cat.c'], - 'dep': wlroots, + 'dep': [wlroots], }, 'screenshot': { 'src': 'screenshot.c', @@ -93,10 +93,18 @@ examples = { } foreach name, info : examples - executable( - name, - info.get('src'), - dependencies: info.get('dep'), - build_by_default: get_option('examples'), - ) + all_dep_found = true + foreach d : info.get('dep') + all_dep_found = all_dep_found and d.found() + endforeach + if all_dep_found + executable( + name, + info.get('src'), + dependencies: info.get('dep'), + build_by_default: get_option('examples'), + ) + else + warning('Dependencies not satisfied for ' + name) + endif endforeach diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 363a16f0..3496fb43 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -53,7 +52,6 @@ struct roots_desktop { struct wlr_idle *idle; struct wlr_idle_inhibit_manager_v1 *idle_inhibit; struct wlr_input_inhibit_manager *input_inhibit; - struct wlr_linux_dmabuf_v1 *linux_dmabuf; struct wlr_layer_shell *layer_shell; struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; struct wlr_screencopy_manager_v1 *screencopy; diff --git a/include/wlr/types/wlr_screencopy_v1.h b/include/wlr/types/wlr_screencopy_v1.h index 822fb3d0..aba32a45 100644 --- a/include/wlr/types/wlr_screencopy_v1.h +++ b/include/wlr/types/wlr_screencopy_v1.h @@ -10,6 +10,7 @@ #define WLR_TYPES_WLR_SCREENCOPY_V1_H #include +#include struct wlr_screencopy_manager_v1 { struct wl_global *global; diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 2eda768a..cf1c2cd1 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -138,6 +138,7 @@ struct wlr_xwayland_surface { struct wl_event_source *ping_timer; // _NET_WM_STATE + bool modal; bool fullscreen; bool maximized_vert, maximized_horz; @@ -150,6 +151,7 @@ struct wlr_xwayland_surface { struct wl_signal request_resize; struct wl_signal request_maximize; struct wl_signal request_fullscreen; + struct wl_signal request_activate; struct wl_signal map; struct wl_signal unmap; diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 08d37736..607cc797 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -40,6 +40,7 @@ enum atom_name { _NET_WM_MOVERESIZE, _NET_WM_NAME, _NET_SUPPORTING_WM_CHECK, + _NET_WM_STATE_MODAL, _NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 6c2b9fbb..31bf2b18 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -1,10 +1,11 @@ #include #include #include +#include #include #include +#include #include -#include #include #include "util/signal.h" @@ -176,6 +177,10 @@ void wlr_renderer_init_wl_display(struct wlr_renderer *r, } } + if (r->impl->texture_from_dmabuf) { + wlr_linux_dmabuf_v1_create(wl_display, r); + } + if (r->impl->init_wl_display) { r->impl->init_wl_display(r, wl_display); } diff --git a/rootston/desktop.c b/rootston/desktop.c index 658611e3..efb7581a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -893,9 +892,6 @@ struct roots_desktop *desktop_create(struct roots_server *server, wl_signal_add(&desktop->input_inhibit->events.deactivate, &desktop->input_inhibit_deactivate); - desktop->linux_dmabuf = wlr_linux_dmabuf_v1_create(server->wl_display, - server->renderer); - desktop->virtual_keyboard = wlr_virtual_keyboard_manager_v1_create( server->wl_display); wl_signal_add(&desktop->virtual_keyboard->events.new_virtual_keyboard, diff --git a/rootston/output.c b/rootston/output.c index d8edf1c2..8677f491 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -822,12 +822,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { wlr_output->model, wlr_output->serial, wlr_output->phys_width, wlr_output->phys_height); - if (!wl_list_empty(&wlr_output->modes)) { - struct wlr_output_mode *mode = - wl_container_of((&wlr_output->modes)->prev, mode, link); - wlr_output_set_mode(wlr_output, mode); - } - struct roots_output *output = calloc(1, sizeof(struct roots_output)); clock_gettime(CLOCK_MONOTONIC, &output->last_frame); output->desktop = desktop; @@ -856,22 +850,28 @@ void handle_new_output(struct wl_listener *listener, void *data) { struct roots_output_config *output_config = roots_config_get_output(config, wlr_output); + + if ((!output_config || output_config->enable) && !wl_list_empty(&wlr_output->modes)) { + struct wlr_output_mode *mode = + wl_container_of(wlr_output->modes.prev, mode, link); + wlr_output_set_mode(wlr_output, mode); + } + if (output_config) { if (output_config->enable) { - struct roots_output_mode_config *mode_config; - if (wlr_output_is_drm(wlr_output)) { + struct roots_output_mode_config *mode_config; wl_list_for_each(mode_config, &output_config->modes, link) { wlr_drm_connector_add_mode(wlr_output, &mode_config->info); } - } else { - if (!wl_list_empty(&output_config->modes)) { - wlr_log(WLR_ERROR, "Can only add modes for DRM backend"); - } + } else if (!wl_list_empty(&output_config->modes)) { + wlr_log(WLR_ERROR, "Can only add modes for DRM backend"); } + if (output_config->mode.width) { set_mode(wlr_output, output_config); } + wlr_output_set_scale(wlr_output, output_config->scale); wlr_output_set_transform(wlr_output, output_config->transform); wlr_output_layout_add(desktop->layout, wlr_output, output_config->x, diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c index fed9afcd..2cf2081e 100644 --- a/rootston/xdg_shell.c +++ b/rootston/xdg_shell.c @@ -507,8 +507,6 @@ static void decoration_handle_surface_commit(struct wl_listener *listener, } void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) { - struct roots_desktop *desktop = - wl_container_of(listener, desktop, xdg_toplevel_decoration); struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration = data; wlr_log(WLR_DEBUG, "new xdg toplevel decoration"); diff --git a/types/tablet_v2/wlr_tablet_v2_pad.c b/types/tablet_v2/wlr_tablet_v2_pad.c index 1fcfa38e..a1672d28 100644 --- a/types/tablet_v2/wlr_tablet_v2_pad.c +++ b/types/tablet_v2/wlr_tablet_v2_pad.c @@ -368,7 +368,7 @@ struct wlr_tablet_v2_tablet_pad *wlr_tablet_pad_create( } pad->group_count = wl_list_length(&wlr_pad->groups); - pad->groups = calloc(pad->group_count, sizeof(int)); + pad->groups = calloc(pad->group_count, sizeof(uint32_t)); if (!pad->groups) { free(pad); return NULL; @@ -471,9 +471,9 @@ void wlr_send_tablet_v2_tablet_pad_button( void wlr_send_tablet_v2_tablet_pad_strip(struct wlr_tablet_v2_tablet_pad *pad, uint32_t strip, double position, bool finger, uint32_t time) { - if (!pad->current_client && - pad->current_client->strips && - pad->current_client->strips[strip]) { + if (!pad->current_client || + !pad->current_client->strips || + !pad->current_client->strips[strip]) { return; } struct wl_resource *resource = pad->current_client->strips[strip]; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 82ad1a4a..49f11b20 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -332,7 +332,7 @@ static void handle_pointer_motion(struct wl_listener *listener, void *data) { static void apply_output_transform(double *x, double *y, enum wl_output_transform transform) { - double dx = *x, dy = *y; + double dx = 0.0, dy = 0.0; double width = 1.0, height = 1.0; switch (transform) { diff --git a/xwayland/xwm.c b/xwayland/xwm.c index c939d8ea..cebd9bbc 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -39,6 +39,7 @@ const char *atom_map[ATOM_LAST] = { "_NET_WM_MOVERESIZE", "_NET_WM_NAME", "_NET_SUPPORTING_WM_CHECK", + "_NET_WM_STATE_MODAL", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", @@ -147,6 +148,7 @@ static struct wlr_xwayland_surface *xwayland_surface_create( wl_signal_init(&surface->events.request_resize); wl_signal_init(&surface->events.request_maximize); wl_signal_init(&surface->events.request_fullscreen); + wl_signal_init(&surface->events.request_activate); wl_signal_init(&surface->events.map); wl_signal_init(&surface->events.unmap); wl_signal_init(&surface->events.set_class); @@ -268,6 +270,9 @@ static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) { int i; i = 0; + if (xsurface->modal) { + property[i++] = xwm->atoms[_NET_WM_STATE_MODAL]; + } if (xsurface->fullscreen) { property[i++] = xwm->atoms[_NET_WM_STATE_FULLSCREEN]; } @@ -575,7 +580,9 @@ static void read_surface_net_wm_state(struct wlr_xwm *xwm, xsurface->fullscreen = 0; xcb_atom_t *atom = xcb_get_property_value(reply); for (uint32_t i = 0; i < reply->value_len; i++) { - if (atom[i] == xwm->atoms[_NET_WM_STATE_FULLSCREEN]) { + if (atom[i] == xwm->atoms[_NET_WM_STATE_MODAL]) { + xsurface->modal = true; + } else if (atom[i] == xwm->atoms[_NET_WM_STATE_FULLSCREEN]) { xsurface->fullscreen = true; } else if (atom[i] == xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT]) { xsurface->maximized_vert = true; @@ -1028,7 +1035,10 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, for (size_t i = 0; i < 2; ++i) { uint32_t property = client_message->data.data32[1 + i]; - if (property == xwm->atoms[_NET_WM_STATE_FULLSCREEN] && + if (property == xwm->atoms[_NET_WM_STATE_MODAL] && + update_state(action, &xsurface->modal)) { + xsurface_set_net_wm_state(xsurface); + } else if (property == xwm->atoms[_NET_WM_STATE_FULLSCREEN] && update_state(action, &xsurface->fullscreen)) { xsurface_set_net_wm_state(xsurface); } else if (property == xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT] && @@ -1087,6 +1097,15 @@ static void xwm_handle_wm_protocols_message(struct wlr_xwm *xwm, } } +static void xwm_handle_net_active_window_message(struct wlr_xwm *xwm, + xcb_client_message_event_t *ev) { + struct wlr_xwayland_surface *surface = lookup_surface(xwm, ev->window); + if (surface == NULL) { + return; + } + wlr_signal_emit_safe(&surface->events.request_activate, surface); +} + static void xwm_handle_client_message(struct wlr_xwm *xwm, xcb_client_message_event_t *ev) { wlr_log(WLR_DEBUG, "XCB_CLIENT_MESSAGE (%u)", ev->window); @@ -1099,6 +1118,8 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm, xwm_handle_net_wm_moveresize_message(xwm, ev); } else if (ev->type == xwm->atoms[WM_PROTOCOLS]) { xwm_handle_wm_protocols_message(xwm, ev); + } else if (ev->type == xwm->atoms[_NET_ACTIVE_WINDOW]) { + xwm_handle_net_active_window_message(xwm, ev); } else if (!xwm_handle_selection_client_message(xwm, ev)) { char *type_name = xwm_get_atom_name(xwm, ev->type); wlr_log(WLR_DEBUG, "unhandled x11 client message %u (%s)", ev->type, @@ -1630,6 +1651,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { xwm->atoms[NET_WM_STATE], xwm->atoms[_NET_ACTIVE_WINDOW], xwm->atoms[_NET_WM_MOVERESIZE], + xwm->atoms[_NET_WM_STATE_MODAL], xwm->atoms[_NET_WM_STATE_FULLSCREEN], xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT], xwm->atoms[_NET_WM_STATE_MAXIMIZED_HORZ],