From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 42 +++++++++++++++++++++++++++++++++++++++-- server/protocol.def | 17 +++++++++++++++++ server/trace.c | 18 ++++++++++++++++++ server/user.h | 2 ++ server/winstation.c | 24 +++++++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index dee0dd13d1b..60667a39cf8 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 ); } @@ -1813,6 +1815,37 @@ static void monitor_get_info( struct monitor *monitor, MONITORINFO *info, UINT d } }
+/* display_lock must be held */ +static void set_winstation_monitors(void) +{ + struct monitor_info *infos, *info; + struct monitor *monitor; + UINT count, x, y; + + if (!(count = list_count( &monitors ))) return; + if (!(info = infos = calloc( count, sizeof(*infos) ))) return; + + 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_winstation_monitors ) + { + wine_server_add_data( req, infos, count * sizeof(*infos) ); + wine_server_call( req ); + } + SERVER_END_REQ; + + free( infos ); +} + static void enum_device_keys( const char *root, const WCHAR *classW, UINT class_size, void (*callback)(const char *) ) { char buffer[1024]; @@ -1979,6 +2012,8 @@ static BOOL update_display_cache_from_registry(void)
if ((ret = !list_empty( &sources ) && !list_empty( &monitors ))) last_query_display_time = key.LastWriteTime.QuadPart; + + set_winstation_monitors(); pthread_mutex_unlock( &display_lock ); release_display_device_init_mutex( mutex ); return ret; @@ -2153,7 +2188,7 @@ 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 vulkan_gpu *gpu, *next;
@@ -2162,6 +2197,8 @@ static void add_vulkan_only_gpus( struct device_manager_ctx *ctx ) 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 ); } + + set_winstation_monitors(); }
BOOL update_display_cache( BOOL force ) @@ -2180,6 +2217,7 @@ BOOL update_display_cache( BOOL force ) pthread_mutex_lock( &display_lock ); clear_display_devices(); list_add_tail( &monitors, &virtual_monitor.entry ); + set_winstation_monitors(); pthread_mutex_unlock( &display_lock ); return TRUE; } @@ -2188,7 +2226,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 ); } diff --git a/server/protocol.def b/server/protocol.def index ac22f9853e5..9ecb14cbac4 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 */
@@ -2802,6 +2813,12 @@ enum coords_relative @END
+/* Update the process current window station monitors */ +@REQ(set_winstation_monitors) + VARARG(infos,monitor_infos); /* window station monitors */ +@END + + /* Get the process current window station */ @REQ(get_process_winstation) @REPLY 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..7a61fa70214 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 */ + unsigned int monitor_count; /* number of monitors */ + struct monitor_info *monitors; /* window station monitors */ };
struct key_repeat diff --git a/server/winstation.c b/server/winstation.c index e5f4bfec357..1cd7d325fd1 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 ))) @@ -203,6 +205,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 */ @@ -636,6 +639,27 @@ DECL_HANDLER(close_winstation) }
+/* set the process current window station monitors */ +DECL_HANDLER(set_winstation_monitors) +{ + struct winstation *winstation; + unsigned int size; + + if (!(winstation = (struct winstation *)get_handle_obj( current->process, current->process->winstation, + 0, &winstation_ops ))) + return; + + free( winstation->monitors ); + winstation->monitors = NULL; + winstation->monitor_count = 0; + + if ((size = get_req_data_size()) && (winstation->monitors = memdup( get_req_data(), size ))) + winstation->monitor_count = size / sizeof(*winstation->monitors); + + release_object( winstation ); +} + + /* get the process current window station */ DECL_HANDLER(get_process_winstation) {