mirror of
https://github.com/labwc/labwc.git
synced 2026-03-29 07:58:10 -04:00
tearing: add fullscreen options (#1941)
Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com>
This commit is contained in:
parent
19f0b769de
commit
433a4509af
9 changed files with 105 additions and 20 deletions
|
|
@ -187,7 +187,12 @@ Actions are used in menus and keyboard/mouse bindings.
|
||||||
original window. There can be multiple windows with this mode set.
|
original window. There can be multiple windows with this mode set.
|
||||||
|
|
||||||
*<action name="ToggleTearing" />*
|
*<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" />*
|
*<action name="FocusOutput" output="HDMI-A-1" />*
|
||||||
Give focus to topmost window on given output and warp the cursor
|
Give focus to topmost window on given output and warp the cursor
|
||||||
|
|
|
||||||
|
|
@ -185,9 +185,18 @@ this is for compatibility with Openbox.
|
||||||
*fullscreen* enables adaptive sync whenever a window is in fullscreen
|
*fullscreen* enables adaptive sync whenever a window is in fullscreen
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
*<core><allowTearing>* [yes|no]
|
*<core><allowTearing>* [yes|no|fullscreen|fullscreenForced]
|
||||||
Allow tearing, if requested by the active window, to reduce input lag.
|
Allow tearing to reduce input lag. Default is no.
|
||||||
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
|
Note: Enabling this option with atomic mode setting is experimental. If
|
||||||
you experience undesirable side effects when tearing is allowed,
|
you experience undesirable side effects when tearing is allowed,
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,13 @@ enum adaptive_sync_mode {
|
||||||
LAB_ADAPTIVE_SYNC_FULLSCREEN,
|
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 {
|
enum tiling_events_mode {
|
||||||
LAB_TILING_EVENTS_NEVER = 0,
|
LAB_TILING_EVENTS_NEVER = 0,
|
||||||
LAB_TILING_EVENTS_REGION = 1 << 0,
|
LAB_TILING_EVENTS_REGION = 1 << 0,
|
||||||
|
|
@ -54,7 +61,7 @@ struct rcxml {
|
||||||
bool xdg_shell_server_side_deco;
|
bool xdg_shell_server_side_deco;
|
||||||
int gap;
|
int gap;
|
||||||
enum adaptive_sync_mode adaptive_sync;
|
enum adaptive_sync_mode adaptive_sync;
|
||||||
bool allow_tearing;
|
enum tearing_mode allow_tearing;
|
||||||
bool reuse_output_mode;
|
bool reuse_output_mode;
|
||||||
enum view_placement_policy placement_policy;
|
enum view_placement_policy placement_policy;
|
||||||
bool xwayland_persistence;
|
bool xwayland_persistence;
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,7 @@ struct output *output_nearest_to_cursor(struct server *server);
|
||||||
bool output_is_usable(struct output *output);
|
bool output_is_usable(struct output *output);
|
||||||
void output_update_usable_area(struct output *output);
|
void output_update_usable_area(struct output *output);
|
||||||
void output_update_all_usable_areas(struct server *server, bool layout_changed);
|
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_in_layout_coords(struct output *output);
|
||||||
struct wlr_box output_usable_area_scaled(struct output *output);
|
struct wlr_box output_usable_area_scaled(struct output *output);
|
||||||
void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@ enum ssd_preference {
|
||||||
LAB_SSD_PREF_SERVER,
|
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
|
* Directions in which a view can be maximized. "None" is used
|
||||||
* internally to mean "not maximized" but is not valid in rc.xml.
|
* internally to mean "not maximized" but is not valid in rc.xml.
|
||||||
|
|
@ -187,6 +193,7 @@ struct view {
|
||||||
enum view_axis maximized;
|
enum view_axis maximized;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool tearing_hint;
|
bool tearing_hint;
|
||||||
|
enum three_state force_tearing;
|
||||||
bool visible_on_all_workspaces;
|
bool visible_on_all_workspaces;
|
||||||
enum view_edge tiled;
|
enum view_edge tiled;
|
||||||
uint32_t edges_visible; /* enum wlr_edges bitset */
|
uint32_t edges_visible; /* enum wlr_edges bitset */
|
||||||
|
|
|
||||||
19
src/action.c
19
src/action.c
|
|
@ -1109,9 +1109,22 @@ actions_run(struct view *activator, struct server *server,
|
||||||
break;
|
break;
|
||||||
case ACTION_TYPE_TOGGLE_TEARING:
|
case ACTION_TYPE_TOGGLE_TEARING:
|
||||||
if (view) {
|
if (view) {
|
||||||
view->tearing_hint = !view->tearing_hint;
|
switch (view->force_tearing) {
|
||||||
wlr_log(WLR_DEBUG, "tearing %sabled",
|
case LAB_STATE_UNSPECIFIED:
|
||||||
view->tearing_hint ? "en" : "dis");
|
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;
|
break;
|
||||||
case ACTION_TYPE_TOGGLE_SHADE:
|
case ACTION_TYPE_TOGGLE_SHADE:
|
||||||
|
|
|
||||||
|
|
@ -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
|
static void
|
||||||
entry(xmlNode *node, char *nodename, char *content)
|
entry(xmlNode *node, char *nodename, char *content)
|
||||||
{
|
{
|
||||||
|
|
@ -886,7 +900,7 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
} else if (!strcasecmp(nodename, "adaptiveSync.core")) {
|
} else if (!strcasecmp(nodename, "adaptiveSync.core")) {
|
||||||
set_adaptive_sync_mode(content, &rc.adaptive_sync);
|
set_adaptive_sync_mode(content, &rc.adaptive_sync);
|
||||||
} else if (!strcasecmp(nodename, "allowTearing.core")) {
|
} 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")) {
|
} else if (!strcasecmp(nodename, "reuseOutputMode.core")) {
|
||||||
set_bool(content, &rc.reuse_output_mode);
|
set_bool(content, &rc.reuse_output_mode);
|
||||||
} else if (!strcmp(nodename, "policy.placement")) {
|
} else if (!strcmp(nodename, "policy.placement")) {
|
||||||
|
|
|
||||||
40
src/output.c
40
src/output.c
|
|
@ -38,28 +38,50 @@ get_tearing_retry_count(struct output *output)
|
||||||
return refresh > 0 ? refresh / 500 : 120;
|
return refresh > 0 ? refresh / 500 : 120;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
get_tearing_preference(struct output *output)
|
output_get_tearing_allowance(struct output *output)
|
||||||
{
|
{
|
||||||
struct server *server = output->server;
|
struct server *server = output->server;
|
||||||
|
|
||||||
/* Never allow tearing when disabled */
|
/* never allow tearing when disabled */
|
||||||
if (!rc.allow_tearing) {
|
if (!rc.allow_tearing) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tearing is only allowed for the output with the active view */
|
struct view *view = server->active_view;
|
||||||
if (!server->active_view || server->active_view->output != output) {
|
|
||||||
|
/* tearing is only allowed for the output with the active view */
|
||||||
|
if (!view || view->output != output) {
|
||||||
return false;
|
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)) {
|
if (output->nr_tearing_failures >= get_tearing_retry_count(output)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the active view requests tearing, or it is toggled on with action, allow it */
|
/* allow tearing for any window when requested or forced */
|
||||||
return server->active_view->tearing_hint;
|
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
|
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_scene_output *scene_output = output->scene_output;
|
||||||
struct wlr_output_state *pending = &output->pending;
|
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 =
|
bool committed =
|
||||||
lab_wlr_scene_output_commit(scene_output, pending);
|
lab_wlr_scene_output_commit(scene_output, pending);
|
||||||
|
|
|
||||||
|
|
@ -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 tearing_controller *controller = wl_container_of(listener, controller, set_hint);
|
||||||
struct view *view = view_from_wlr_surface(controller->tearing_control->surface);
|
struct view *view = view_from_wlr_surface(controller->tearing_control->surface);
|
||||||
if (view && controller->tearing_control->current) {
|
if (view) {
|
||||||
view->tearing_hint = true;
|
/*
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue