]> git.mdlowis.com Git - proto/labwc.git/commitdiff
tearing: add fullscreen options (#1941)
authorJens Peters <jp7677@gmail.com>
Tue, 6 Aug 2024 20:23:10 +0000 (22:23 +0200)
committerGitHub <noreply@github.com>
Tue, 6 Aug 2024 20:23:10 +0000 (21:23 +0100)
Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com>
docs/labwc-actions.5.scd
docs/labwc-config.5.scd
include/config/rcxml.h
include/labwc.h
include/view.h
src/action.c
src/config/rcxml.c
src/output.c
src/tearing.c

index 9ccfb7988c887eec19d7c292942073c89fe59e19..cb6fac6332e4b9776a13d1d8668a16b97f7393de 100644 (file)
@@ -187,7 +187,12 @@ Actions are used in menus and keyboard/mouse bindings.
        original window. There can be multiple windows with this mode set.
 
 *<action name="ToggleTearing" />*
-       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.
 
 *<action name="FocusOutput" output="HDMI-A-1" />*
        Give focus to topmost window on given output and warp the cursor
index 986194d3228c91c75292d95d90fb0a070219b099..55956db42cc023fa504de7412fc1c6643bf181b0 100644 (file)
@@ -185,9 +185,18 @@ this is for compatibility with Openbox.
        *fullscreen* enables adaptive sync whenever a window is in fullscreen
        mode.
 
-*<core><allowTearing>* [yes|no]
-       Allow tearing, if requested by the active window, to reduce input lag.
-       Default is no.
+*<core><allowTearing>* [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,
index 62fb5e572608983bfabeaab064ee0aabbac2ca87..c49bafd2a8e0b54ffd1af5c97ebd10262e3de8bd 100644 (file)
@@ -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;
index 28aeebca2b4e2eba69d8b101d56e952b789e535e..466a90d39d5ba2248ffc9fcfb381e869f64579db 100644 (file)
@@ -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,
index 9dc70aa8967643c7b33bb3dcd0b3fac0c37181f4..0fde958e76335f1183ececdbc29770c80b37413d 100644 (file)
@@ -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 */
index 0aa45d7a863b5e51feeacfeece7e95bbf648e0a5..69a317bb988ab80a0b2ce61b00d955f45c6d16d2 100644 (file)
@@ -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:
index aa0bface58b45f25316c07695a1a8a3c2aee0615..0227911bba2bba3f860506022173acef5daf4baa 100644 (file)
@@ -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")) {
index 8ba8225a27207316c2d588db331eab57b95fb23e..b9ac9855c80079468ea2b9e69909a39c9443a0b3 100644 (file)
@@ -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);
index 583fe1e2469e2f70b0b3d9d5670c701c54fcca45..b4e86d608b36798fd4900d3c70aa06171614a00b 100644 (file)
@@ -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;
        }
 }