mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 02:00:41 +00:00
(Wayland) wp_viewporter + scaling fix (#15176)
* Use wp_viewporter * Set buffer scale to highest of displays the window is touching * Fixes fullscreen issue mentioned in #15168 * Simplify process of adding new wayland protocols
This commit is contained in:
parent
7874a64529
commit
e8ec3031a8
@ -1231,11 +1231,12 @@ ifeq ($(HAVE_WAYLAND), 1)
|
||||
input/common/wayland_common.o \
|
||||
input/drivers/wayland_input.o \
|
||||
gfx/common/wayland_common.o \
|
||||
gfx/common/wayland/viewporter.o \
|
||||
gfx/common/wayland/xdg-shell.o \
|
||||
gfx/common/wayland/idle-inhibit-unstable-v1.o \
|
||||
gfx/common/wayland/xdg-decoration-unstable-v1.o \
|
||||
gfx/common/wayland/pointer-constraints-unstable-v1.o \
|
||||
gfx/common/wayland/relative-pointer-unstable-v1.o
|
||||
gfx/common/wayland/pointer-constraints-unstable-v1.o \
|
||||
gfx/common/wayland/relative-pointer-unstable-v1.o
|
||||
|
||||
ifeq ($(HAVE_VULKAN), 1)
|
||||
OBJ += gfx/drivers_context/wayland_vk_ctx.o
|
||||
|
7
deps/wayland-protocols/stable/viewporter/README
vendored
Normal file
7
deps/wayland-protocols/stable/viewporter/README
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
Viewporter: cropping and scaling extension for surface contents
|
||||
|
||||
Previously known as wl_scaler.
|
||||
|
||||
Maintainers:
|
||||
Pekka Paalanen <pekka.paalanen@collabora.co.uk>
|
||||
|
180
deps/wayland-protocols/stable/viewporter/viewporter.xml
vendored
Normal file
180
deps/wayland-protocols/stable/viewporter/viewporter.xml
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="viewporter">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2013-2016 Collabora, Ltd.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="wp_viewporter" version="1">
|
||||
<description summary="surface cropping and scaling">
|
||||
The global interface exposing surface cropping and scaling
|
||||
capabilities is used to instantiate an interface extension for a
|
||||
wl_surface object. This extended interface will then allow
|
||||
cropping and scaling the surface contents, effectively
|
||||
disconnecting the direct relationship between the buffer and the
|
||||
surface size.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="unbind from the cropping and scaling interface">
|
||||
Informs the server that the client will not be using this
|
||||
protocol object anymore. This does not affect any other objects,
|
||||
wp_viewport objects included.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="viewport_exists" value="0"
|
||||
summary="the surface already has a viewport object associated"/>
|
||||
</enum>
|
||||
|
||||
<request name="get_viewport">
|
||||
<description summary="extend surface interface for crop and scale">
|
||||
Instantiate an interface extension for the given wl_surface to
|
||||
crop and scale its content. If the given wl_surface already has
|
||||
a wp_viewport object associated, the viewport_exists
|
||||
protocol error is raised.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="wp_viewport"
|
||||
summary="the new viewport interface id"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="the surface"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="wp_viewport" version="1">
|
||||
<description summary="crop and scale interface to a wl_surface">
|
||||
An additional interface to a wl_surface object, which allows the
|
||||
client to specify the cropping and scaling of the surface
|
||||
contents.
|
||||
|
||||
This interface works with two concepts: the source rectangle (src_x,
|
||||
src_y, src_width, src_height), and the destination size (dst_width,
|
||||
dst_height). The contents of the source rectangle are scaled to the
|
||||
destination size, and content outside the source rectangle is ignored.
|
||||
This state is double-buffered, and is applied on the next
|
||||
wl_surface.commit.
|
||||
|
||||
The two parts of crop and scale state are independent: the source
|
||||
rectangle, and the destination size. Initially both are unset, that
|
||||
is, no scaling is applied. The whole of the current wl_buffer is
|
||||
used as the source, and the surface size is as defined in
|
||||
wl_surface.attach.
|
||||
|
||||
If the destination size is set, it causes the surface size to become
|
||||
dst_width, dst_height. The source (rectangle) is scaled to exactly
|
||||
this size. This overrides whatever the attached wl_buffer size is,
|
||||
unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
|
||||
has no content and therefore no size. Otherwise, the size is always
|
||||
at least 1x1 in surface local coordinates.
|
||||
|
||||
If the source rectangle is set, it defines what area of the wl_buffer is
|
||||
taken as the source. If the source rectangle is set and the destination
|
||||
size is not set, then src_width and src_height must be integers, and the
|
||||
surface size becomes the source rectangle size. This results in cropping
|
||||
without scaling. If src_width or src_height are not integers and
|
||||
destination size is not set, the bad_size protocol error is raised when
|
||||
the surface state is applied.
|
||||
|
||||
The coordinate transformations from buffer pixel coordinates up to
|
||||
the surface-local coordinates happen in the following order:
|
||||
1. buffer_transform (wl_surface.set_buffer_transform)
|
||||
2. buffer_scale (wl_surface.set_buffer_scale)
|
||||
3. crop and scale (wp_viewport.set*)
|
||||
This means, that the source rectangle coordinates of crop and scale
|
||||
are given in the coordinates after the buffer transform and scale,
|
||||
i.e. in the coordinates that would be the surface-local coordinates
|
||||
if the crop and scale was not applied.
|
||||
|
||||
If src_x or src_y are negative, the bad_value protocol error is raised.
|
||||
Otherwise, if the source rectangle is partially or completely outside of
|
||||
the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
|
||||
when the surface state is applied. A NULL wl_buffer does not raise the
|
||||
out_of_buffer error.
|
||||
|
||||
If the wl_surface associated with the wp_viewport is destroyed,
|
||||
all wp_viewport requests except 'destroy' raise the protocol error
|
||||
no_surface.
|
||||
|
||||
If the wp_viewport object is destroyed, the crop and scale
|
||||
state is removed from the wl_surface. The change will be applied
|
||||
on the next wl_surface.commit.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="remove scaling and cropping from the surface">
|
||||
The associated wl_surface's crop and scale state is removed.
|
||||
The change is applied on the next wl_surface.commit.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="bad_value" value="0"
|
||||
summary="negative or zero values in width or height"/>
|
||||
<entry name="bad_size" value="1"
|
||||
summary="destination size is not integer"/>
|
||||
<entry name="out_of_buffer" value="2"
|
||||
summary="source rectangle extends outside of the content area"/>
|
||||
<entry name="no_surface" value="3"
|
||||
summary="the wl_surface was destroyed"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_source">
|
||||
<description summary="set the source rectangle for cropping">
|
||||
Set the source rectangle of the associated wl_surface. See
|
||||
wp_viewport for the description, and relation to the wl_buffer
|
||||
size.
|
||||
|
||||
If all of x, y, width and height are -1.0, the source rectangle is
|
||||
unset instead. Any other set of values where width or height are zero
|
||||
or negative, or x or y are negative, raise the bad_value protocol
|
||||
error.
|
||||
|
||||
The crop and scale state is double-buffered state, and will be
|
||||
applied on the next wl_surface.commit.
|
||||
</description>
|
||||
<arg name="x" type="fixed" summary="source rectangle x"/>
|
||||
<arg name="y" type="fixed" summary="source rectangle y"/>
|
||||
<arg name="width" type="fixed" summary="source rectangle width"/>
|
||||
<arg name="height" type="fixed" summary="source rectangle height"/>
|
||||
</request>
|
||||
|
||||
<request name="set_destination">
|
||||
<description summary="set the surface size for scaling">
|
||||
Set the destination size of the associated wl_surface. See
|
||||
wp_viewport for the description, and relation to the wl_buffer
|
||||
size.
|
||||
|
||||
If width is -1 and height is -1, the destination size is unset
|
||||
instead. Any other pair of values for width and height that
|
||||
contains zero or negative values raises the bad_value protocol
|
||||
error.
|
||||
|
||||
The crop and scale state is double-buffered state, and will be
|
||||
applied on the next wl_surface.commit.
|
||||
</description>
|
||||
<arg name="width" type="int" summary="surface width"/>
|
||||
<arg name="height" type="int" summary="surface height"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
@ -55,28 +55,19 @@ else
|
||||
CODEGEN=private-code
|
||||
fi
|
||||
|
||||
XDG_SHELL='stable/xdg-shell/xdg-shell.xml'
|
||||
XDG_DECORATION_UNSTABLE='unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'
|
||||
IDLE_INHIBIT_UNSTABLE='unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'
|
||||
POINTER_CONSTRAINTS_UNSTABLE='unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'
|
||||
RELATIVE_POINTER_UNSTABLE='unstable/relative-pointer/relative-pointer-unstable-v1.xml'
|
||||
generate_source () {
|
||||
PROTO_DIR="$1"
|
||||
PROTO_NAME="$2"
|
||||
PROTO_FILE="$WAYLAND_PROTOS/$PROTO_DIR/$PROTO_NAME.xml"
|
||||
|
||||
#Generate xdg-shell header and .c files
|
||||
"$WAYSCAN" client-header "$WAYLAND_PROTOS/$XDG_SHELL" ./xdg-shell.h
|
||||
"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/$XDG_SHELL" ./xdg-shell.c
|
||||
"$WAYSCAN" client-header "$PROTO_FILE" "./$PROTO_NAME.h"
|
||||
"$WAYSCAN" $CODEGEN "$PROTO_FILE" "./$PROTO_NAME.c"
|
||||
}
|
||||
|
||||
#Generate idle-inhibit header and .c files
|
||||
"$WAYSCAN" client-header "$WAYLAND_PROTOS/$IDLE_INHIBIT_UNSTABLE" ./idle-inhibit-unstable-v1.h
|
||||
"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/$IDLE_INHIBIT_UNSTABLE" ./idle-inhibit-unstable-v1.c
|
||||
generate_source 'stable/viewporter' 'viewporter'
|
||||
generate_source 'stable/xdg-shell' 'xdg-shell'
|
||||
generate_source 'unstable/xdg-decoration' 'xdg-decoration-unstable-v1'
|
||||
generate_source 'unstable/idle-inhibit' 'idle-inhibit-unstable-v1'
|
||||
generate_source 'unstable/pointer-constraints' 'pointer-constraints-unstable-v1'
|
||||
generate_source 'unstable/relative-pointer' 'relative-pointer-unstable-v1'
|
||||
|
||||
#Generate xdg-decoration header and .c files
|
||||
"$WAYSCAN" client-header "$WAYLAND_PROTOS/$XDG_DECORATION_UNSTABLE" ./xdg-decoration-unstable-v1.h
|
||||
"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/$XDG_DECORATION_UNSTABLE" ./xdg-decoration-unstable-v1.c
|
||||
|
||||
#Generate pointer-constraints header and .c files
|
||||
"$WAYSCAN" client-header "$WAYLAND_PROTOS/$POINTER_CONSTRAINTS_UNSTABLE" ./pointer-constraints-unstable-v1.h
|
||||
"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/$POINTER_CONSTRAINTS_UNSTABLE" ./pointer-constraints-unstable-v1.c
|
||||
|
||||
#Generate relative-pointer header and .c files
|
||||
"$WAYSCAN" client-header "$WAYLAND_PROTOS/$RELATIVE_POINTER_UNSTABLE" ./relative-pointer-unstable-v1.h
|
||||
"$WAYSCAN" $CODEGEN "$WAYLAND_PROTOS/$RELATIVE_POINTER_UNSTABLE" ./relative-pointer-unstable-v1.c
|
||||
|
@ -79,6 +79,11 @@ static const unsigned long retroarch_icon_data[] = {
|
||||
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
|
||||
};
|
||||
|
||||
static void update_viewport(gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
wp_viewport_set_destination(wl->viewport, wl->width, wl->height);
|
||||
}
|
||||
|
||||
void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
|
||||
void *toplevel,
|
||||
int32_t width, int32_t height, struct wl_array *states)
|
||||
@ -130,6 +135,8 @@ void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl,
|
||||
wl->buffer_width = wl->width * wl->buffer_scale;
|
||||
wl->buffer_height = wl->height * wl->buffer_scale;
|
||||
wl->resize = true;
|
||||
if (wl->viewport)
|
||||
update_viewport(wl);
|
||||
}
|
||||
|
||||
if (floating)
|
||||
@ -195,6 +202,8 @@ void libdecor_frame_handle_configure_common(struct libdecor_frame *frame,
|
||||
wl->buffer_width = width * wl->buffer_scale;
|
||||
wl->buffer_height = height * wl->buffer_scale;
|
||||
wl->resize = true;
|
||||
if (wl->viewport)
|
||||
update_viewport(wl);
|
||||
}
|
||||
|
||||
state = wl->libdecor_state_new(wl->width, wl->height);
|
||||
@ -228,23 +237,26 @@ void gfx_ctx_wl_get_video_size_common(gfx_ctx_wayland_data_t *wl,
|
||||
{
|
||||
if (!wl->reported_display_size)
|
||||
{
|
||||
output_info_t *tmp = NULL;
|
||||
display_output_t *od;
|
||||
output_info_t *oi = wl->current_output;
|
||||
|
||||
wl->reported_display_size = true;
|
||||
|
||||
/* If window is not ready get any monitor */
|
||||
if (!oi)
|
||||
wl_list_for_each_safe(oi, tmp, &wl->all_outputs, link)
|
||||
break;
|
||||
wl_list_for_each(od, &wl->all_outputs, link)
|
||||
{
|
||||
oi = od->output;
|
||||
break;
|
||||
};
|
||||
|
||||
*width = oi->width;
|
||||
*height = oi->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = wl->buffer_width;
|
||||
*height = wl->buffer_height;
|
||||
*width = wl->width * wl->pending_buffer_scale;
|
||||
*height = wl->height * wl->pending_buffer_scale;
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,6 +281,8 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl)
|
||||
if (wl->cursor.surface)
|
||||
wl_surface_destroy(wl->cursor.surface);
|
||||
|
||||
if (wl->viewport)
|
||||
wp_viewport_destroy(wl->viewport);
|
||||
if (wl->idle_inhibitor)
|
||||
zwp_idle_inhibitor_v1_destroy(wl->idle_inhibitor);
|
||||
if (wl->deco)
|
||||
@ -294,15 +308,28 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl)
|
||||
xdg_wm_base_destroy(wl->xdg_shell);
|
||||
if (wl->data_device_manager)
|
||||
wl_data_device_manager_destroy (wl->data_device_manager);
|
||||
while (!wl_list_empty(&wl->all_outputs)) {
|
||||
output_info_t *oi;
|
||||
oi = wl_container_of(wl->all_outputs.next, oi, link);
|
||||
wl_output_destroy(oi->output);
|
||||
wl_list_remove(&oi->link);
|
||||
free(oi);
|
||||
while (!wl_list_empty(&wl->current_outputs))
|
||||
{
|
||||
surface_output_t *os;
|
||||
os = wl_container_of(wl->current_outputs.next, os, link);
|
||||
wl_list_remove(&os->link);
|
||||
free(os);
|
||||
}
|
||||
while (!wl_list_empty(&wl->all_outputs))
|
||||
{
|
||||
display_output_t *od;
|
||||
output_info_t *oi;
|
||||
od = wl_container_of(wl->all_outputs.next, od, link);
|
||||
oi = od->output;
|
||||
wl_output_destroy(oi->output);
|
||||
wl_list_remove(&od->link);
|
||||
free(oi);
|
||||
free(od);
|
||||
}
|
||||
if (wl->shm)
|
||||
wl_shm_destroy (wl->shm);
|
||||
if (wl->viewporter)
|
||||
wp_viewporter_destroy(wl->viewporter);
|
||||
if (wl->compositor)
|
||||
wl_compositor_destroy(wl->compositor);
|
||||
if (wl->registry)
|
||||
@ -371,12 +398,15 @@ bool gfx_ctx_wl_get_metrics_common(void *data,
|
||||
enum display_metric_types type, float *value)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
output_info_t *tmp = NULL;
|
||||
display_output_t *od;
|
||||
output_info_t *oi = wl ? wl->current_output : NULL;
|
||||
|
||||
if (!oi)
|
||||
wl_list_for_each_safe(oi, tmp, &wl->all_outputs, link)
|
||||
wl_list_for_each(od, &wl->all_outputs, link)
|
||||
{
|
||||
oi = od->output;
|
||||
break;
|
||||
};
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@ -568,7 +598,6 @@ static bool wl_draw_splash_screen(gfx_ctx_wayland_data_t *wl)
|
||||
16);
|
||||
|
||||
wl_surface_attach(wl->surface, buffer->wl_buffer, 0, 0);
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
if (wl_surface_get_version(wl->surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
|
||||
wl_surface_damage_buffer(wl->surface, 0, 0,
|
||||
wl->buffer_width,
|
||||
@ -600,14 +629,16 @@ bool gfx_ctx_wl_init_common(
|
||||
#endif
|
||||
|
||||
wl_list_init(&wl->all_outputs);
|
||||
wl_list_init(&wl->current_outputs);
|
||||
|
||||
frontend_driver_destroy_signal_handler_state();
|
||||
|
||||
wl->input.dpy = wl_display_connect(NULL);
|
||||
wl->last_buffer_scale = 1;
|
||||
wl->buffer_scale = 1;
|
||||
wl->floating_width = SPLASH_WINDOW_WIDTH;
|
||||
wl->floating_height = SPLASH_WINDOW_HEIGHT;
|
||||
wl->input.dpy = wl_display_connect(NULL);
|
||||
wl->last_buffer_scale = 1;
|
||||
wl->buffer_scale = 1;
|
||||
wl->pending_buffer_scale = 1;
|
||||
wl->floating_width = SPLASH_WINDOW_WIDTH;
|
||||
wl->floating_height = SPLASH_WINDOW_HEIGHT;
|
||||
|
||||
if (!wl->input.dpy)
|
||||
{
|
||||
@ -650,8 +681,9 @@ bool gfx_ctx_wl_init_common(
|
||||
}
|
||||
|
||||
wl->surface = wl_compositor_create_surface(wl->compositor);
|
||||
if (wl->viewporter)
|
||||
wl->viewport = wp_viewporter_get_viewport(wl->viewporter, wl->surface);
|
||||
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
wl_surface_add_listener(wl->surface, &wl_surface_listener, wl);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
@ -776,16 +808,17 @@ bool gfx_ctx_wl_set_video_mode_common_size(gfx_ctx_wayland_data_t *wl,
|
||||
|
||||
if (!fullscreen)
|
||||
{
|
||||
wl->buffer_scale = wl->pending_buffer_scale;
|
||||
wl->buffer_width *= wl->buffer_scale;
|
||||
wl->buffer_height *= wl->buffer_scale;
|
||||
}
|
||||
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
if (wl->viewport)
|
||||
update_viewport(wl);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (wl->libdecor)
|
||||
{
|
||||
struct libdecor_state *state = wl->libdecor_state_new(width, height);
|
||||
struct libdecor_state *state = wl->libdecor_state_new(wl->width, wl->height);
|
||||
wl->libdecor_frame_commit(wl->libdecor_frame, state, NULL);
|
||||
wl->libdecor_state_free(state);
|
||||
}
|
||||
@ -802,7 +835,8 @@ bool gfx_ctx_wl_set_video_mode_common_fullscreen(gfx_ctx_wayland_data_t *wl,
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
output_info_t *oi, *tmp;
|
||||
display_output_t *od;
|
||||
output_info_t *oi;
|
||||
struct wl_output *output = NULL;
|
||||
int output_i = 0;
|
||||
|
||||
@ -812,14 +846,18 @@ bool gfx_ctx_wl_set_video_mode_common_fullscreen(gfx_ctx_wayland_data_t *wl,
|
||||
output = oi->output;
|
||||
RARCH_LOG("[Wayland]: Auto fullscreen on display \"%s\" \"%s\"\n", oi->make, oi->model);
|
||||
}
|
||||
else wl_list_for_each_safe(oi, tmp, &wl->all_outputs, link)
|
||||
else
|
||||
{
|
||||
if (++output_i == video_monitor_index)
|
||||
wl_list_for_each(od, &wl->all_outputs, link)
|
||||
{
|
||||
output = oi->output;
|
||||
RARCH_LOG("[Wayland]: Fullscreen on display %i \"%s\" \"%s\"\n", output_i, oi->make, oi->model);
|
||||
break;
|
||||
}
|
||||
if (++output_i == video_monitor_index)
|
||||
{
|
||||
oi = od->output;
|
||||
output = oi->output;
|
||||
RARCH_LOG("[Wayland]: Fullscreen on display %i \"%s\" \"%s\"\n", output_i, oi->make, oi->model);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!output)
|
||||
@ -899,14 +937,14 @@ void gfx_ctx_wl_check_window_common(gfx_ctx_wayland_data_t *wl,
|
||||
|
||||
get_video_size(wl, &new_width, &new_height);
|
||||
|
||||
if ( new_width != *width
|
||||
if ( wl->pending_buffer_scale != wl->buffer_scale
|
||||
|| new_width != *width
|
||||
|| new_height != *height)
|
||||
{
|
||||
wl->buffer_scale = wl->pending_buffer_scale;
|
||||
*width = new_width;
|
||||
*height = new_height;
|
||||
*resize = true;
|
||||
|
||||
wl->last_buffer_scale = wl->buffer_scale;
|
||||
}
|
||||
|
||||
*quit = (bool)frontend_driver_get_signal_handler_state();
|
||||
|
@ -116,11 +116,13 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
|
||||
wl->last_buffer_scale = wl->buffer_scale;
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
wl_egl_window_resize(wl->win, width, height, 0, 0);
|
||||
#endif
|
||||
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,9 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
|
||||
wl->last_buffer_scale = wl->buffer_scale;
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
|
||||
if (vulkan_create_swapchain(&wl->vk, width, height, wl->swap_interval))
|
||||
{
|
||||
wl->vk.context.flags |= VK_CTX_FLAG_INVALID_SWAPCHAIN;
|
||||
@ -101,8 +104,6 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height)
|
||||
|
||||
wl->vk.flags &= ~VK_DATA_FLAG_NEED_NEW_SWAPCHAIN;
|
||||
|
||||
wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -516,29 +516,100 @@ static void wl_seat_handle_name(void *data,
|
||||
|
||||
/* Surface callbacks. */
|
||||
|
||||
static bool wl_update_scale(gfx_ctx_wayland_data_t *wl)
|
||||
{
|
||||
surface_output_t *os;
|
||||
output_info_t *new_output = NULL;
|
||||
unsigned largest_scale = 0;
|
||||
|
||||
wl_list_for_each(os, &wl->current_outputs, link)
|
||||
{
|
||||
if (os->output->scale > largest_scale) {
|
||||
largest_scale = os->output->scale;
|
||||
new_output = os->output;
|
||||
}
|
||||
};
|
||||
|
||||
if (new_output && wl->current_output != new_output) {
|
||||
wl->current_output = new_output;
|
||||
wl->pending_buffer_scale = new_output->scale;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wl_current_outputs_add(gfx_ctx_wayland_data_t *wl,
|
||||
struct wl_output *output)
|
||||
{
|
||||
display_output_t *od;
|
||||
surface_output_t *os;
|
||||
output_info_t *oi_found = NULL;
|
||||
|
||||
wl_list_for_each(od, &wl->all_outputs, link)
|
||||
{
|
||||
if (od->output->output == output)
|
||||
{
|
||||
oi_found = od->output;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (oi_found)
|
||||
{
|
||||
surface_output_t *os = (surface_output_t*)
|
||||
calloc(1, sizeof(surface_output_t));
|
||||
os->output = oi_found;
|
||||
wl_list_insert(&wl->current_outputs, &os->link);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool wl_current_outputs_remove(gfx_ctx_wayland_data_t *wl,
|
||||
struct wl_output *output)
|
||||
{
|
||||
surface_output_t *os;
|
||||
surface_output_t *os_found = NULL;
|
||||
|
||||
wl_list_for_each(os, &wl->current_outputs, link)
|
||||
{
|
||||
if (os->output->output == output)
|
||||
{
|
||||
os_found = os;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (os_found)
|
||||
{
|
||||
wl_list_remove(&os_found->link);
|
||||
free(os_found);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void wl_surface_enter(void *data, struct wl_surface *wl_surface,
|
||||
struct wl_output *output)
|
||||
{
|
||||
output_info_t *oi;
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
output_info_t *oi;
|
||||
|
||||
wl->input.mouse.surface = wl_surface;
|
||||
wl->input.mouse.surface = wl_surface;
|
||||
|
||||
/* TODO: track all outputs the surface is on, pick highest scale */
|
||||
|
||||
wl_list_for_each(oi, &wl->all_outputs, link)
|
||||
{
|
||||
if (oi->output == output)
|
||||
{
|
||||
wl->current_output = oi;
|
||||
wl->last_buffer_scale = wl->buffer_scale;
|
||||
wl->buffer_scale = oi->scale;
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (wl_current_outputs_add(wl, output))
|
||||
wl_update_scale(wl);
|
||||
}
|
||||
|
||||
static void wl_nop(void *a, struct wl_surface *b, struct wl_output *c) { }
|
||||
static void wl_surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output)
|
||||
{
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
output_info_t *oi;
|
||||
|
||||
if (wl_current_outputs_remove(wl, output))
|
||||
wl_update_scale(wl);
|
||||
}
|
||||
|
||||
/* Shell surface callbacks. */
|
||||
static void xdg_shell_ping(
|
||||
@ -554,7 +625,7 @@ static void xdg_surface_handle_configure(
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
}
|
||||
|
||||
static void wl_display_handle_geometry(void *data,
|
||||
static void wl_output_handle_geometry(void *data,
|
||||
struct wl_output *output,
|
||||
int x, int y,
|
||||
int physical_width, int physical_height,
|
||||
@ -563,29 +634,29 @@ static void wl_display_handle_geometry(void *data,
|
||||
const char *model,
|
||||
int transform)
|
||||
{
|
||||
output_info_t *oi = (output_info_t*)data;
|
||||
oi->physical_width = physical_width;
|
||||
oi->physical_height = physical_height;
|
||||
oi->make = strdup(make);
|
||||
oi->model = strdup(model);
|
||||
output_info_t *oi = (output_info_t*)data;
|
||||
oi->physical_width = physical_width;
|
||||
oi->physical_height = physical_height;
|
||||
oi->make = strdup(make);
|
||||
oi->model = strdup(model);
|
||||
}
|
||||
|
||||
static void wl_display_handle_mode(void *data,
|
||||
static void wl_output_handle_mode(void *data,
|
||||
struct wl_output *output,
|
||||
uint32_t flags,
|
||||
int width,
|
||||
int height,
|
||||
int refresh)
|
||||
{
|
||||
output_info_t *oi = (output_info_t*)data;
|
||||
oi->width = width;
|
||||
oi->height = height;
|
||||
oi->refresh_rate = refresh;
|
||||
output_info_t *oi = (output_info_t*)data;
|
||||
oi->width = width;
|
||||
oi->height = height;
|
||||
oi->refresh_rate = refresh;
|
||||
}
|
||||
|
||||
static void wl_display_handle_done(void *data, struct wl_output *output) { }
|
||||
static void wl_output_handle_done(void *data, struct wl_output *output) { }
|
||||
|
||||
static void wl_display_handle_scale(void *data,
|
||||
static void wl_output_handle_scale(void *data,
|
||||
struct wl_output *output,
|
||||
int32_t factor)
|
||||
{
|
||||
@ -621,16 +692,22 @@ static void wl_registry_handle_global(void *data, struct wl_registry *reg,
|
||||
if (string_is_equal(interface, wl_compositor_interface.name))
|
||||
wl->compositor = (struct wl_compositor*)wl_registry_bind(reg,
|
||||
id, &wl_compositor_interface, MIN(version, 4));
|
||||
else if (string_is_equal(interface, wp_viewporter_interface.name))
|
||||
wl->viewporter = (struct wp_viewporter*)wl_registry_bind(reg,
|
||||
id, &wp_viewporter_interface, MIN(version, 1));
|
||||
else if (string_is_equal(interface, wl_output_interface.name))
|
||||
{
|
||||
display_output_t *od = (display_output_t*)
|
||||
calloc(1, sizeof(display_output_t));
|
||||
output_info_t *oi = (output_info_t*)
|
||||
calloc(1, sizeof(output_info_t));
|
||||
|
||||
oi->global_id = id;
|
||||
oi->output = (struct wl_output*)wl_registry_bind(reg,
|
||||
od->output = oi;
|
||||
oi->global_id = id;
|
||||
oi->output = (struct wl_output*)wl_registry_bind(reg,
|
||||
id, &wl_output_interface, MIN(version, 2));
|
||||
wl_output_add_listener(oi->output, &output_listener, oi);
|
||||
wl_list_insert(&wl->all_outputs, &oi->link);
|
||||
wl_list_insert(&wl->all_outputs, &od->link);
|
||||
wl_display_roundtrip(wl->input.dpy);
|
||||
}
|
||||
else if (string_is_equal(interface, xdg_wm_base_interface.name))
|
||||
@ -675,18 +752,25 @@ static void wl_registry_handle_global(void *data, struct wl_registry *reg,
|
||||
static void wl_registry_handle_global_remove(void *data,
|
||||
struct wl_registry *registry, uint32_t id)
|
||||
{
|
||||
output_info_t *oi, *tmp;
|
||||
display_output_t *od, *tmp;
|
||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||
bool surface_output_removed = false;
|
||||
|
||||
wl_list_for_each_safe(oi, tmp, &wl->all_outputs, link)
|
||||
wl_list_for_each_safe(od, tmp, &wl->all_outputs, link)
|
||||
{
|
||||
if (oi->global_id == id)
|
||||
if (od->output->global_id == id)
|
||||
{
|
||||
wl_list_remove(&oi->link);
|
||||
free(oi);
|
||||
if (wl_current_outputs_remove(wl, od->output->output))
|
||||
surface_output_removed = true;
|
||||
wl_list_remove(&od->link);
|
||||
free(od->output);
|
||||
free(od);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (surface_output_removed)
|
||||
wl_update_scale(wl);
|
||||
}
|
||||
|
||||
static int wl_ioready(int fd, int flags, int timeoutMS)
|
||||
@ -931,10 +1015,10 @@ const struct wl_registry_listener registry_listener = {
|
||||
};
|
||||
|
||||
const struct wl_output_listener output_listener = {
|
||||
wl_display_handle_geometry,
|
||||
wl_display_handle_mode,
|
||||
wl_display_handle_done,
|
||||
wl_display_handle_scale,
|
||||
wl_output_handle_geometry,
|
||||
wl_output_handle_mode,
|
||||
wl_output_handle_done,
|
||||
wl_output_handle_scale,
|
||||
};
|
||||
|
||||
const struct xdg_wm_base_listener xdg_shell_listener = {
|
||||
@ -947,7 +1031,7 @@ const struct xdg_surface_listener xdg_surface_listener = {
|
||||
|
||||
const struct wl_surface_listener wl_surface_listener = {
|
||||
wl_surface_enter,
|
||||
wl_nop,
|
||||
wl_surface_leave,
|
||||
};
|
||||
|
||||
const struct wl_seat_listener seat_listener = {
|
||||
|
@ -32,19 +32,12 @@
|
||||
#include "../../gfx/common/vulkan_common.h"
|
||||
#endif
|
||||
|
||||
/* Generated from idle-inhibit-unstable-v1.xml */
|
||||
/* Generated from wayland protocol files by generate_wayland_protos.sh */
|
||||
#include "../../gfx/common/wayland/viewporter.h"
|
||||
#include "../../gfx/common/wayland/idle-inhibit-unstable-v1.h"
|
||||
|
||||
/* Generated from xdg-shell.xml */
|
||||
#include "../../gfx/common/wayland/xdg-shell.h"
|
||||
|
||||
/* Generated from xdg-decoration-unstable-v1.h */
|
||||
#include "../../gfx/common/wayland/xdg-decoration-unstable-v1.h"
|
||||
|
||||
/* Generated from pointer-constraints-unstable-v1.h */
|
||||
#include "../../gfx/common/wayland/pointer-constraints-unstable-v1.h"
|
||||
|
||||
/* Generated from relative-pointer-unstable-v1.h */
|
||||
#include "../../gfx/common/wayland/relative-pointer-unstable-v1.h"
|
||||
|
||||
#define UDEV_KEY_MAX 0x2ff
|
||||
@ -88,9 +81,20 @@ typedef struct output_info
|
||||
unsigned scale;
|
||||
char *make;
|
||||
char *model;
|
||||
struct wl_list link; /* wl->all_outputs */
|
||||
} output_info_t;
|
||||
|
||||
typedef struct display_output
|
||||
{
|
||||
output_info_t *output;
|
||||
struct wl_list link;
|
||||
} display_output_t;
|
||||
|
||||
typedef struct surface_output
|
||||
{
|
||||
output_info_t *output;
|
||||
struct wl_list link;
|
||||
} surface_output_t;
|
||||
|
||||
typedef struct gfx_ctx_wayland_data gfx_ctx_wayland_data_t;
|
||||
|
||||
typedef struct input_ctx_wayland_data
|
||||
@ -138,8 +142,10 @@ typedef struct gfx_ctx_wayland_data
|
||||
#endif
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct wp_viewporter *viewporter;
|
||||
struct wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct wp_viewport *viewport;
|
||||
struct xdg_wm_base *xdg_shell;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct wl_keyboard *wl_keyboard;
|
||||
@ -173,6 +179,7 @@ typedef struct gfx_ctx_wayland_data
|
||||
#endif
|
||||
input_ctx_wayland_data_t input; /* ptr alignment */
|
||||
struct wl_list all_outputs;
|
||||
struct wl_list current_outputs;
|
||||
|
||||
struct
|
||||
{
|
||||
@ -193,6 +200,7 @@ typedef struct gfx_ctx_wayland_data
|
||||
unsigned floating_width;
|
||||
unsigned floating_height;
|
||||
unsigned last_buffer_scale;
|
||||
unsigned pending_buffer_scale;
|
||||
unsigned buffer_scale;
|
||||
|
||||
bool core_hw_context_enable;
|
||||
|
@ -44,10 +44,6 @@
|
||||
#include "../../retroarch.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
/* TODO/FIXME -
|
||||
* fix game focus toggle
|
||||
*/
|
||||
|
||||
/* Forward declaration */
|
||||
|
||||
void flush_wayland_fd(void *data);
|
||||
|
Loading…
Reference in New Issue
Block a user