From: Jens Peters Date: Tue, 6 Aug 2024 20:23:10 +0000 (+0200) Subject: tearing: add fullscreen options (#1941) X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=433a4509af814c9ae92c71596545efbe12acc29c;p=proto%2Flabwc.git tearing: add fullscreen options (#1941) Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com> --- diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 9ccfb798..cb6fac63 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -187,7 +187,12 @@ Actions are used in menus and keyboard/mouse bindings. original window. There can be multiple windows with this mode set. ** - Toggles tearing for the focused window. + Toggles tearing for the focused window between enabled and disabled. + This overrides the preference (tearing hint) from the focused window. + + Requires the config option 'allowTearing'. When 'allowTearing' is set + to 'fullscreen' or 'fullscreenForced', tearing will still only be + enabled if the active window is in fullscreen mode. ** Give focus to topmost window on given output and warp the cursor diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 986194d3..55956db4 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -185,9 +185,18 @@ this is for compatibility with Openbox. *fullscreen* enables adaptive sync whenever a window is in fullscreen mode. -** [yes|no] - Allow tearing, if requested by the active window, to reduce input lag. - Default is no. +** [yes|no|fullscreen|fullscreenForced] + Allow tearing to reduce input lag. Default is no. + + *yes* allows tearing if requested by the active window. + + *fullscreen* allows tearing if requested by the active window, but + only when the window is in fullscreen mode. + + *fullscreenForced* enables tearing whenever the active window is in + fullscreen mode, whether or not the application has requested tearing. + + Use the *ToggleTearing* action for forcefully enable tearing. Note: Enabling this option with atomic mode setting is experimental. If you experience undesirable side effects when tearing is allowed, diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 62fb5e57..c49bafd2 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -30,6 +30,13 @@ enum adaptive_sync_mode { LAB_ADAPTIVE_SYNC_FULLSCREEN, }; +enum tearing_mode { + LAB_TEARING_DISABLED = 0, + LAB_TEARING_ENABLED, + LAB_TEARING_FULLSCREEN, + LAB_TEARING_FULLSCREEN_FORCED, +}; + enum tiling_events_mode { LAB_TILING_EVENTS_NEVER = 0, LAB_TILING_EVENTS_REGION = 1 << 0, @@ -54,7 +61,7 @@ struct rcxml { bool xdg_shell_server_side_deco; int gap; enum adaptive_sync_mode adaptive_sync; - bool allow_tearing; + enum tearing_mode allow_tearing; bool reuse_output_mode; enum view_placement_policy placement_policy; bool xwayland_persistence; diff --git a/include/labwc.h b/include/labwc.h index 28aeebca..466a90d3 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -535,6 +535,7 @@ struct output *output_nearest_to_cursor(struct server *server); bool output_is_usable(struct output *output); void output_update_usable_area(struct output *output); void output_update_all_usable_areas(struct server *server, bool layout_changed); +bool output_get_tearing_allowance(struct output *output); struct wlr_box output_usable_area_in_layout_coords(struct output *output); struct wlr_box output_usable_area_scaled(struct output *output); void handle_output_power_manager_set_mode(struct wl_listener *listener, diff --git a/include/view.h b/include/view.h index 9dc70aa8..0fde958e 100644 --- a/include/view.h +++ b/include/view.h @@ -30,6 +30,12 @@ enum ssd_preference { LAB_SSD_PREF_SERVER, }; +enum three_state { + LAB_STATE_UNSPECIFIED = 0, + LAB_STATE_ENABLED, + LAB_STATE_DISABLED +}; + /** * Directions in which a view can be maximized. "None" is used * internally to mean "not maximized" but is not valid in rc.xml. @@ -187,6 +193,7 @@ struct view { enum view_axis maximized; bool fullscreen; bool tearing_hint; + enum three_state force_tearing; bool visible_on_all_workspaces; enum view_edge tiled; uint32_t edges_visible; /* enum wlr_edges bitset */ diff --git a/src/action.c b/src/action.c index 0aa45d7a..69a317bb 100644 --- a/src/action.c +++ b/src/action.c @@ -1109,9 +1109,22 @@ actions_run(struct view *activator, struct server *server, break; case ACTION_TYPE_TOGGLE_TEARING: if (view) { - view->tearing_hint = !view->tearing_hint; - wlr_log(WLR_DEBUG, "tearing %sabled", - view->tearing_hint ? "en" : "dis"); + switch (view->force_tearing) { + case LAB_STATE_UNSPECIFIED: + view->force_tearing = + output_get_tearing_allowance(view->output) + ? LAB_STATE_DISABLED : LAB_STATE_ENABLED; + break; + case LAB_STATE_DISABLED: + view->force_tearing = LAB_STATE_ENABLED; + break; + case LAB_STATE_ENABLED: + view->force_tearing = LAB_STATE_DISABLED; + break; + } + wlr_log(WLR_ERROR, "force tearing %sabled", + view->force_tearing == LAB_STATE_ENABLED + ? "en" : "dis"); } break; case ACTION_TYPE_TOGGLE_SHADE: diff --git a/src/config/rcxml.c b/src/config/rcxml.c index aa0bface..0227911b 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -772,6 +772,20 @@ set_adaptive_sync_mode(const char *str, enum adaptive_sync_mode *variable) } } +static void +set_tearing_mode(const char *str, enum tearing_mode *variable) +{ + if (!strcasecmp(str, "fullscreen")) { + *variable = LAB_TEARING_FULLSCREEN; + } else if (!strcasecmp(str, "fullscreenForced")) { + *variable = LAB_TEARING_FULLSCREEN_FORCED; + } else if (parse_bool(str, -1) == 1) { + *variable = LAB_TEARING_ENABLED; + } else { + *variable = LAB_TEARING_DISABLED; + } +} + static void entry(xmlNode *node, char *nodename, char *content) { @@ -886,7 +900,7 @@ entry(xmlNode *node, char *nodename, char *content) } else if (!strcasecmp(nodename, "adaptiveSync.core")) { set_adaptive_sync_mode(content, &rc.adaptive_sync); } else if (!strcasecmp(nodename, "allowTearing.core")) { - set_bool(content, &rc.allow_tearing); + set_tearing_mode(content, &rc.allow_tearing); } else if (!strcasecmp(nodename, "reuseOutputMode.core")) { set_bool(content, &rc.reuse_output_mode); } else if (!strcmp(nodename, "policy.placement")) { diff --git a/src/output.c b/src/output.c index 8ba8225a..b9ac9855 100644 --- a/src/output.c +++ b/src/output.c @@ -38,28 +38,50 @@ get_tearing_retry_count(struct output *output) return refresh > 0 ? refresh / 500 : 120; } -static bool -get_tearing_preference(struct output *output) +bool +output_get_tearing_allowance(struct output *output) { struct server *server = output->server; - /* Never allow tearing when disabled */ + /* never allow tearing when disabled */ if (!rc.allow_tearing) { return false; } - /* Tearing is only allowed for the output with the active view */ - if (!server->active_view || server->active_view->output != output) { + struct view *view = server->active_view; + + /* tearing is only allowed for the output with the active view */ + if (!view || view->output != output) { return false; } - /* Tearing should not have failed too many times */ + /* tearing should not have failed too many times */ if (output->nr_tearing_failures >= get_tearing_retry_count(output)) { return false; } - /* If the active view requests tearing, or it is toggled on with action, allow it */ - return server->active_view->tearing_hint; + /* allow tearing for any window when requested or forced */ + if (rc.allow_tearing == LAB_TEARING_ENABLED) { + if (view->force_tearing == LAB_STATE_UNSPECIFIED) { + return view->tearing_hint; + } else { + return view->force_tearing == LAB_STATE_ENABLED; + } + } + + /* remaining tearing options apply only to full-screen windows */ + if (!view->fullscreen) { + return false; + } + + if (view->force_tearing == LAB_STATE_UNSPECIFIED) { + /* honor the tearing hint or the fullscreen-force preference */ + return view->tearing_hint || + rc.allow_tearing == LAB_TEARING_FULLSCREEN_FORCED; + } + + /* honor tearing as requested by action */ + return view->force_tearing == LAB_STATE_ENABLED; } static void @@ -128,7 +150,7 @@ output_frame_notify(struct wl_listener *listener, void *data) struct wlr_scene_output *scene_output = output->scene_output; struct wlr_output_state *pending = &output->pending; - pending->tearing_page_flip = get_tearing_preference(output); + pending->tearing_page_flip = output_get_tearing_allowance(output); bool committed = lab_wlr_scene_output_commit(scene_output, pending); diff --git a/src/tearing.c b/src/tearing.c index 583fe1e2..b4e86d60 100644 --- a/src/tearing.c +++ b/src/tearing.c @@ -15,8 +15,15 @@ set_tearing_hint(struct wl_listener *listener, void *data) { struct tearing_controller *controller = wl_container_of(listener, controller, set_hint); struct view *view = view_from_wlr_surface(controller->tearing_control->surface); - if (view && controller->tearing_control->current) { - view->tearing_hint = true; + if (view) { + /* + * tearing_control->current is actually an enum: + * WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC = 0 + * WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC = 1 + * + * Using it as a bool here allows us to not ship the XML. + */ + view->tearing_hint = controller->tearing_control->current; } }