Commit ce6a7ae8 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard

winewayland.drv: Basic support for Windows monitor positioning.

Use the xdg-output-unstable-v1 protocol to get the positions of the Wayland outputs in the compositor logical space, and use this information to arrange the monitors in the Windows virtual screen space. For now we assume that the logical positions match the physical pixel positions (i.e., the outputs are not scaled), a deficiency which will be addressed in an upcoming commit. Signed-off-by: 's avatarAlexandros Frantzis <alexandros.frantzis@collabora.com>
parent 7b48de32
......@@ -30,6 +30,8 @@
#include "ntuser.h"
#include <stdlib.h>
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
void wayland_init_display_devices(void)
......@@ -39,6 +41,46 @@ void wayland_init_display_devices(void)
NtUserGetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &num_path, &num_mode);
}
struct output_info
{
int x, y;
struct wayland_output *output;
};
static int output_info_cmp_primary_x_y(const void *va, const void *vb)
{
const struct output_info *a = va;
const struct output_info *b = vb;
BOOL a_is_primary = a->x == 0 && a->y == 0;
BOOL b_is_primary = b->x == 0 && b->y == 0;
if (a_is_primary && !b_is_primary) return -1;
if (!a_is_primary && b_is_primary) return 1;
if (a->x < b->x) return -1;
if (a->x > b->x) return 1;
if (a->y < b->y) return -1;
if (a->y > b->y) return 1;
return strcmp(a->output->name, b->output->name);
}
static void output_info_array_arrange_physical_coords(struct wl_array *output_info_array)
{
struct output_info *info;
size_t num_outputs = output_info_array->size / sizeof(struct output_info);
/* Set physical pixel coordinates. */
wl_array_for_each(info, output_info_array)
{
info->x = info->output->logical_x;
info->y = info->output->logical_y;
}
/* Now that we have our physical pixel coordinates, sort from physical left
* to right, but ensure the primary output is first. */
qsort(output_info_array->data, num_outputs, sizeof(struct output_info),
output_info_cmp_primary_x_y);
}
static void wayland_add_device_gpu(const struct gdi_device_manager *device_manager,
void *param)
{
......@@ -68,13 +110,13 @@ static void wayland_add_device_adapter(const struct gdi_device_manager *device_m
}
static void wayland_add_device_monitor(const struct gdi_device_manager *device_manager,
void *param, struct wayland_output *output)
void *param, struct output_info *output_info)
{
struct gdi_monitor monitor = {0};
SetRect(&monitor.rc_monitor, 0, 0,
output->current_mode->width,
output->current_mode->height);
SetRect(&monitor.rc_monitor, output_info->x, output_info->y,
output_info->x + output_info->output->current_mode->width,
output_info->y + output_info->output->current_mode->height);
/* We don't have a direct way to get the work area in Wayland. */
monitor.rc_work = monitor.rc_monitor;
......@@ -82,7 +124,7 @@ static void wayland_add_device_monitor(const struct gdi_device_manager *device_m
monitor.state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE;
TRACE("name=%s rc_monitor=rc_work=%s state_flags=0x%x\n",
output->name, wine_dbgstr_rect(&monitor.rc_monitor),
output_info->output->name, wine_dbgstr_rect(&monitor.rc_monitor),
(UINT)monitor.state_flags);
device_manager->add_monitor(&monitor, param);
......@@ -101,16 +143,22 @@ static void populate_devmode(struct wayland_output_mode *output_mode, DEVMODEW *
}
static void wayland_add_device_modes(const struct gdi_device_manager *device_manager,
void *param, struct wayland_output *output)
void *param, struct output_info *output_info)
{
struct wayland_output_mode *output_mode;
RB_FOR_EACH_ENTRY(output_mode, &output->modes, struct wayland_output_mode, entry)
RB_FOR_EACH_ENTRY(output_mode, &output_info->output->modes,
struct wayland_output_mode, entry)
{
DEVMODEW mode = {.dmSize = sizeof(mode)};
BOOL mode_is_current = output_mode == output->current_mode;
BOOL mode_is_current = output_mode == output_info->output->current_mode;
populate_devmode(output_mode, &mode);
if (mode_is_current) mode.dmFields |= DM_POSITION;
if (mode_is_current)
{
mode.dmFields |= DM_POSITION;
mode.dmPosition.x = output_info->x;
mode.dmPosition.y = output_info->y;
}
device_manager->add_mode(&mode, mode_is_current, param);
}
}
......@@ -123,21 +171,37 @@ BOOL WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manage
{
struct wayland_output *output;
INT output_id = 0;
struct wl_array output_info_array;
struct output_info *output_info;
if (!force) return TRUE;
TRACE("force=%d\n", force);
wayland_add_device_gpu(device_manager, param);
wl_array_init(&output_info_array);
wl_list_for_each(output, &process_wayland->output_list, link)
{
if (!output->current_mode) continue;
output_info = wl_array_add(&output_info_array, sizeof(*output_info));
if (output_info) output_info->output = output;
else ERR("Failed to allocate space for output_info\n");
}
output_info_array_arrange_physical_coords(&output_info_array);
/* Populate GDI devices. */
wayland_add_device_gpu(device_manager, param);
wl_array_for_each(output_info, &output_info_array)
{
wayland_add_device_adapter(device_manager, param, output_id);
wayland_add_device_monitor(device_manager, param, output);
wayland_add_device_modes(device_manager, param, output);
wayland_add_device_monitor(device_manager, param, output_info);
wayland_add_device_modes(device_manager, param, output_info);
output_id++;
}
wl_array_release(&output_info_array);
return TRUE;
}
......@@ -101,7 +101,8 @@ static void wayland_output_done(struct wayland_output *output)
{
struct wayland_output_mode *mode;
TRACE("name=%s\n", output->name);
TRACE("name=%s logical=%d,%d\n",
output->name, output->logical_x, output->logical_y);
RB_FOR_EACH_ENTRY(mode, &output->modes, struct wayland_output_mode, entry)
{
......@@ -161,6 +162,10 @@ static void zxdg_output_v1_handle_logical_position(void *data,
int32_t x,
int32_t y)
{
struct wayland_output *output = data;
TRACE("logical_x=%d logical_y=%d\n", x, y);
output->logical_x = x;
output->logical_y = y;
}
static void zxdg_output_v1_handle_logical_size(void *data,
......
......@@ -70,6 +70,7 @@ struct wayland_output
struct rb_tree modes;
struct wayland_output_mode *current_mode;
char *name;
int logical_x, logical_y;
uint32_t global_id;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment