Display device handlers are used to initialize the display device registry data. Different handlers can be implemented according to the defined interface, for example, via Xinerama or XRandR. With those registry data, EnumDisplayDevices, EnumDisplayMonitors and GetMonitorInfo can be built on top of it.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- v2: Supersede 162308~162314, fix xinerama primary adapter reporting, fix registry data reinit failure. v3: Rebase v4: Merge patches. Rebase. Supersede 164594~164599, 164612~164613 v5: Fix explorer patch triggered user32 test failures. Supersede 165122~165128. v6: Restructure patches. Supersede 165134~165140 v7: Supersede 165307~165313. Add mutex to avoid init race. Remove old adapter keys during reinit. Add fallback monitor data in explorer. Simplify code.
dlls/winex11.drv/Makefile.in | 1 + dlls/winex11.drv/display.c | 82 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 15 +++++++ dlls/winex11.drv/x11drv_main.c | 1 + dlls/winex11.drv/xinerama.c | 7 +++ 5 files changed, 106 insertions(+) create mode 100644 dlls/winex11.drv/display.c
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in index 747f509b44..9ca2fc6efe 100644 --- a/dlls/winex11.drv/Makefile.in +++ b/dlls/winex11.drv/Makefile.in @@ -9,6 +9,7 @@ C_SRCS = \ brush.c \ clipboard.c \ desktop.c \ + display.c \ event.c \ graphics.c \ ime.c \ diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c new file mode 100644 index 0000000000..a82975bfb9 --- /dev/null +++ b/dlls/winex11.drv/display.c @@ -0,0 +1,82 @@ +/* + * X11DRV display device functions + * + * Copyright 2019 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "wine/debug.h" +#include "x11drv.h" + +WINE_DEFAULT_DEBUG_CHANNEL(x11drv); + +static const WCHAR video_keyW[] = { + 'H','A','R','D','W','A','R','E','\', + 'D','E','V','I','C','E','M','A','P','\', + 'V','I','D','E','O',0}; + +static struct x11drv_display_device_handler handler; + +void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *new_handler) +{ + if (new_handler->priority > handler.priority) + { + handler = *new_handler; + TRACE("Display device functions are now handled by: %s\n", handler.name); + } +} + +void X11DRV_DisplayDevices_Init(void) +{ + static const WCHAR init_mutexW[] = + {'_','_','x','1','1','_','d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0}; + HANDLE mutex; + HKEY video_hkey = NULL; + DWORD disposition = 0; + BOOL success = FALSE; + + mutex = CreateMutexW(NULL, FALSE, init_mutexW); + WaitForSingleObject(mutex, INFINITE); + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &video_hkey, + &disposition)) + goto fail; + + /* Avoid unnecessary reinit */ + if (disposition != REG_CREATED_NEW_KEY) + { + success = TRUE; + goto fail; + } + + TRACE("via %s\n", wine_dbgstr_a(handler.name)); + + success = TRUE; +fail: + RegCloseKey(video_hkey); + ReleaseMutex(mutex); + CloseHandle(mutex); + if (!success) + ERR("Failed to initialize display devices\n"); +} diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index c633102a38..fbc5a104f6 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -665,6 +665,21 @@ struct x11drv_mode_info *X11DRV_Settings_SetHandlers(const char *name, void X11DRV_XF86VM_Init(void) DECLSPEC_HIDDEN; void X11DRV_XRandR_Init(void) DECLSPEC_HIDDEN;
+/* X11 display device handler. Used to initialize display device registry data */ + +/* Required functions for display device registry initialization */ +struct x11drv_display_device_handler +{ + /* A name to tell what host driver is used */ + CHAR name[MAX_PATH]; + + /* Higher priority can override handlers with lower proprity */ + INT priority; +}; + +extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN; +extern void X11DRV_DisplayDevices_Init(void) DECLSPEC_HIDDEN; + /* XIM support */ extern BOOL X11DRV_InitXIM( const char *input_style ) DECLSPEC_HIDDEN; extern XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index e67a3c05a9..69478741f1 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -597,6 +597,7 @@ static BOOL process_attach(void) X11DRV_InitKeyboard( gdi_display ); if (use_xim) use_xim = X11DRV_InitXIM( input_style );
+ X11DRV_DisplayDevices_Init(); return TRUE; }
diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index 739b139736..35dd36049b 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -30,6 +30,8 @@ #include "wine/library.h" #include "x11drv.h" #include "wine/debug.h" +#include "wine/heap.h" +#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
@@ -201,6 +203,7 @@ RECT get_primary_monitor_rect(void)
void xinerama_init( unsigned int width, unsigned int height ) { + struct x11drv_display_device_handler handler; MONITORINFOEXW *primary; int i; RECT rect; @@ -234,6 +237,10 @@ void xinerama_init( unsigned int width, unsigned int height ) (monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" ); }
+ strcpy( handler.name, "Xinerama" ); + handler.priority = 100; + X11DRV_DisplayDevices_SetHandler( &handler ); + TRACE( "virtual size: %s primary: %s\n", wine_dbgstr_rect(&virtual_screen_rect), wine_dbgstr_rect(&primary->rcMonitor) ); }
On Tue, May 28, 2019 at 03:19:24PM +0800, Zhiyi Zhang wrote:
Display device handlers are used to initialize the display device registry data. Different handlers can be implemented according to the defined interface, for example, via Xinerama or XRandR. With those registry data, EnumDisplayDevices, EnumDisplayMonitors and GetMonitorInfo can be built on top of it.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com
v2: Supersede 162308~162314, fix xinerama primary adapter reporting, fix registry data reinit failure. v3: Rebase v4: Merge patches. Rebase. Supersede 164594~164599, 164612~164613 v5: Fix explorer patch triggered user32 test failures. Supersede 165122~165128. v6: Restructure patches. Supersede 165134~165140 v7: Supersede 165307~165313. Add mutex to avoid init race. Remove old adapter keys during reinit. Add fallback monitor data in explorer. Simplify code.
dlls/winex11.drv/Makefile.in | 1 + dlls/winex11.drv/display.c | 82 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 15 +++++++ dlls/winex11.drv/x11drv_main.c | 1 + dlls/winex11.drv/xinerama.c | 7 +++ 5 files changed, 106 insertions(+) create mode 100644 dlls/winex11.drv/display.c
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c new file mode 100644 index 0000000000..a82975bfb9 --- /dev/null +++ b/dlls/winex11.drv/display.c +void X11DRV_DisplayDevices_Init(void) +{
- static const WCHAR init_mutexW[] =
{'_','_','x','1','1','_','d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
- HANDLE mutex;
- HKEY video_hkey = NULL;
- DWORD disposition = 0;
- BOOL success = FALSE;
- mutex = CreateMutexW(NULL, FALSE, init_mutexW);
- WaitForSingleObject(mutex, INFINITE);
- if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &video_hkey,
&disposition))
goto fail;
- /* Avoid unnecessary reinit */
- if (disposition != REG_CREATED_NEW_KEY)
- {
success = TRUE;
goto fail;
I think you need to change the label name (to e.g. "end") ;-) Also, the success variable is unnecessary, issue the ERR() if RegCreateKeyExW fails and then goto end.
What's going to happen with two seats running on the same wineserver?
Huw.
On 5/29/19 6:31 PM, Huw Davies wrote:
On Tue, May 28, 2019 at 03:19:24PM +0800, Zhiyi Zhang wrote:
Display device handlers are used to initialize the display device registry data. Different handlers can be implemented according to the defined interface, for example, via Xinerama or XRandR. With those registry data, EnumDisplayDevices, EnumDisplayMonitors and GetMonitorInfo can be built on top of it.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com
v2: Supersede 162308~162314, fix xinerama primary adapter reporting, fix registry data reinit failure. v3: Rebase v4: Merge patches. Rebase. Supersede 164594~164599, 164612~164613 v5: Fix explorer patch triggered user32 test failures. Supersede 165122~165128. v6: Restructure patches. Supersede 165134~165140 v7: Supersede 165307~165313. Add mutex to avoid init race. Remove old adapter keys during reinit. Add fallback monitor data in explorer. Simplify code.
dlls/winex11.drv/Makefile.in | 1 + dlls/winex11.drv/display.c | 82 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 15 +++++++ dlls/winex11.drv/x11drv_main.c | 1 + dlls/winex11.drv/xinerama.c | 7 +++ 5 files changed, 106 insertions(+) create mode 100644 dlls/winex11.drv/display.c
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c new file mode 100644 index 0000000000..a82975bfb9 --- /dev/null +++ b/dlls/winex11.drv/display.c +void X11DRV_DisplayDevices_Init(void) +{
- static const WCHAR init_mutexW[] =
{'_','_','x','1','1','_','d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
- HANDLE mutex;
- HKEY video_hkey = NULL;
- DWORD disposition = 0;
- BOOL success = FALSE;
- mutex = CreateMutexW(NULL, FALSE, init_mutexW);
- WaitForSingleObject(mutex, INFINITE);
- if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &video_hkey,
&disposition))
goto fail;
- /* Avoid unnecessary reinit */
- if (disposition != REG_CREATED_NEW_KEY)
- {
success = TRUE;
goto fail;
I think you need to change the label name (to e.g. "end") ;-)
Sure.
Also, the success variable is unnecessary, issue the ERR() if RegCreateKeyExW fails and then goto end.
What's going to happen with two seats running on the same wineserver?
What do you mean by "two seats"? do you mean processes? The mutex should be able to protect against threads on different processes racing.
What mechanism would you use?
Thanks, Zhiyi
Huw.
On Wed, May 29, 2019 at 07:12:31PM +0800, Zhiyi Zhang wrote:
On 5/29/19 6:31 PM, Huw Davies wrote:
What's going to happen with two seats running on the same wineserver?
What do you mean by "two seats"? do you mean processes?
No, two sessions. e.g. a local user and that same user sshing in from a remote X server. To make things interesting, the local user could be using the mac driver.
Huw.
On 5/29/19 7:26 PM, Huw Davies wrote:
On Wed, May 29, 2019 at 07:12:31PM +0800, Zhiyi Zhang wrote:
On 5/29/19 6:31 PM, Huw Davies wrote:
What's going to happen with two seats running on the same wineserver?
What do you mean by "two seats"? do you mean processes?
No, two sessions. e.g. a local user and that same user sshing in from a remote X server. To make things interesting, the local user could be using the mac driver.
Huw.
In terms of X server, currently it will use the latest X connection to initialize the registry, if needed.
For example, if at first a local user doesn't have X connection and then a remote user ssh in from a remote X server. The registry will be initialized with the remote X connection. If local user have already initialized the registry, then remote user login shouldn't trigger a reinitialization, unless the remote user uses desktop mode, then registry will be initialized again with the remote X connection, overriding the local one.
On Windows, the adapter data stored in registry is always local. With X being a network protocol, there is no local or remote clients. So the first connection is treated as local.
I am not sure how much we can do about this since Windows graphics driver stack didn't build with X in mind. We could make EnumDisplayDeviceW report different adapters according to different X connection. But then that means EnumDisplayDeviceW may need to use a different approach, e.g., via user driver backend directly instead of storing the information under specific registry keys. And still we need to put a version of adapter information in registry as well because e.g., SetupAPI may be used to query the registry, so the problem didn't go away completely.
P.S. Alexandre didn't like the EnumDisplayDeviceW via user driver backend approach, which is how it was implemented the very first version.