From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 34 +++++++++++++++++++++++++++++++--- server/protocol.def | 17 +++++++++++++++++ server/trace.c | 18 ++++++++++++++++++ server/user.h | 2 ++ server/winstation.c | 22 ++++++++++++++++++++++ 5 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index dee0dd13d1b..84462f1d3e2 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1699,6 +1699,8 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW set_reg_value( source->key, modesW, REG_BINARY, modes, modes_count * sizeof(*modes) ); set_reg_value( source->key, mode_countW, REG_DWORD, &modes_count, sizeof(modes_count) ); source->mode_count = modes_count; + source->current = *current; + source->physical = physical;
free( virtual_modes ); } @@ -2153,15 +2155,41 @@ static UINT update_display_devices( struct device_manager_ctx *ctx ) return status; }
-static void add_vulkan_only_gpus( struct device_manager_ctx *ctx ) +static void commit_display_devices( struct device_manager_ctx *ctx ) { + struct monitor_info *infos, *info; struct vulkan_gpu *gpu, *next; + struct monitor *monitor; + UINT count, x, y;
LIST_FOR_EACH_ENTRY_SAFE( gpu, next, &ctx->vulkan_gpus, struct vulkan_gpu, entry ) { TRACE( "adding vulkan-only gpu uuid %s, name %s\n", debugstr_guid(&gpu->uuid), debugstr_a(gpu->name)); add_gpu( gpu->name, &gpu->pci_id, &gpu->uuid, ctx ); } + + if ((count = list_count( &monitors )) && (infos = info = calloc( count, sizeof(*infos) ))) + { + LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry ) + { + if (is_monitor_primary( monitor )) info->flags |= MONITOR_FLAG_PRIMARY; + if (!is_monitor_active( monitor )) info->flags |= MONITOR_FLAG_INACTIVE; + if (monitor->is_clone) info->flags |= MONITOR_FLAG_CLONE; + info->dpi = monitor_get_dpi( monitor, MDT_EFFECTIVE_DPI, &x, &y ); + info->virt = wine_server_rectangle( monitor_get_rect( monitor, 0, MDT_EFFECTIVE_DPI ) ); + info->raw = wine_server_rectangle( monitor_get_rect( monitor, 0, MDT_RAW_DPI ) ); + info++; + } + + SERVER_START_REQ( set_monitor_infos ) + { + wine_server_add_data( req, infos, count * sizeof(*infos) ); + wine_server_call( req ); + } + SERVER_END_REQ; + + free( infos ); + } }
BOOL update_display_cache( BOOL force ) @@ -2188,7 +2216,7 @@ BOOL update_display_cache( BOOL force ) else { if (!get_vulkan_gpus( &ctx.vulkan_gpus )) WARN( "Failed to find any vulkan GPU\n" ); - if (!(status = update_display_devices( &ctx ))) add_vulkan_only_gpus( &ctx ); + if (!(status = update_display_devices( &ctx ))) commit_display_devices( &ctx ); else WARN( "Failed to update display devices, status %#x\n", status ); release_display_manager_ctx( &ctx ); } @@ -2269,7 +2297,7 @@ static void release_display_dc( HDC hdc ) pthread_mutex_unlock( &display_dc_lock ); }
-/* display_lock must be held */ +/* display_lock must be held, keep in sync with server/window.c */ static struct monitor *get_monitor_from_rect( RECT rect, UINT flags, UINT dpi, MONITOR_DPI_TYPE type ) { struct monitor *monitor, *primary = NULL, *nearest = NULL, *found = NULL; diff --git a/server/protocol.def b/server/protocol.def index ac22f9853e5..4c2aeb65b1e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -896,6 +896,17 @@ struct directory_entry /* VARARG(type,unicode_str,type_len); */ };
+struct monitor_info +{ + rectangle_t raw; /* host / physical position of the monitor rect */ + rectangle_t virt; /* client / virtual position of the monitor rect */ + unsigned int flags; /* MONITOR_FLAG_* flags for the monitor */ + unsigned int dpi; /* physical DPI for the monitor */ +}; +#define MONITOR_FLAG_PRIMARY 0x01 +#define MONITOR_FLAG_CLONE 0x02 +#define MONITOR_FLAG_INACTIVE 0x04 + /****************************************************************/ /* shared session mapping structures */
@@ -2869,6 +2880,12 @@ enum coords_relative @END
+/* Update the winstation monitors */ +@REQ(set_monitor_infos) + VARARG(infos,monitor_infos); /* array of monitor_info */ +@END + + /* Get the thread current desktop */ @REQ(get_thread_desktop) thread_id_t tid; /* thread id */ diff --git a/server/trace.c b/server/trace.c index 7142c37218a..82e86313027 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1511,6 +1511,24 @@ static void dump_varargs_directory_entries( const char *prefix, data_size_t size fputc( '}', stderr ); }
+static void dump_varargs_monitor_infos( const char *prefix, data_size_t size ) +{ + const struct monitor_info *monitor = cur_data; + data_size_t len = size / sizeof(*monitor); + + fprintf( stderr,"%s{", prefix ); + while (len > 0) + { + dump_rectangle( "{raw:", &monitor->virt ); + dump_rectangle( ",virt:", &monitor->virt ); + fprintf( stderr, ",flags:%#x,dpi:%u", monitor->flags, monitor->dpi ); + fputc( '}', stderr ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + remove_data( size ); +} + typedef void (*dump_func)( const void *req );
/* Everything below this line is generated automatically by tools/make_requests */ diff --git a/server/user.h b/server/user.h index 6f9612ffb93..67b0ae2cc67 100644 --- a/server/user.h +++ b/server/user.h @@ -52,6 +52,8 @@ struct winstation struct clipboard *clipboard; /* clipboard information */ struct atom_table *atom_table; /* global atom table */ struct namespace *desktop_names; /* namespace for desktops of this winstation */ + struct monitor_info *monitors; /* monitors connected to the winstation */ + unsigned int monitor_count; /* number of connected monitors */ };
struct key_repeat diff --git a/server/winstation.c b/server/winstation.c index 109715d77b3..8265c720340 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -147,6 +147,8 @@ static struct winstation *create_winstation( struct object *root, const struct u winstation->input_desktop = NULL; winstation->clipboard = NULL; winstation->atom_table = NULL; + winstation->monitors = NULL; + winstation->monitor_count = 0; list_add_tail( &winstation_list, &winstation->entry ); list_init( &winstation->desktops ); if (!(winstation->desktop_names = create_namespace( 7 ))) @@ -208,6 +210,7 @@ static void winstation_destroy( struct object *obj ) if (winstation->clipboard) release_object( winstation->clipboard ); if (winstation->atom_table) release_object( winstation->atom_table ); free( winstation->desktop_names ); + free( winstation->monitors ); }
/* retrieve the process window station, checking the handle access rights */ @@ -662,6 +665,25 @@ DECL_HANDLER(set_process_winstation) } }
+/* set the winstation monitors */ +DECL_HANDLER(set_monitor_infos) +{ + struct desktop *desktop = get_thread_desktop( current, 0 ); + struct winstation *winstation = get_visible_winstation(); + unsigned int size = get_req_data_size(); + + if (!winstation) return; + + free( winstation->monitors ); + winstation->monitors = NULL; + winstation->monitor_count = 0; + + if ((winstation->monitors = memdup( get_req_data(), size ))) + winstation->monitor_count = size / sizeof(*winstation->monitors); + + release_object( desktop ); +} + /* create a desktop */ DECL_HANDLER(create_desktop) {