1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Win32 Display Drivers for GUIX Studio */
18 /** */
19 /**************************************************************************/
20 #ifdef WIN32
21 #include "tx_api.h"
22 #include "gx_api.h"
23 #include "gx_system.h"
24 #include "gx_display.h"
25 #include "windows.h"
26 #include "gx_win32_studio_display_driver.h"
27
28 extern BOOL win32_graphics_data_initialized;
29 extern GX_WIN32_DISPLAY_DRIVER_DATA win32_instance_data[GX_MAX_WIN32_DISPLAYS];
30
31
32 /**************************************************************************/
33 /* Do cleanup operation for specific display driver. */
34 /**************************************************************************/
win32_graphics_driver_cleanup(GX_DISPLAY * display)35 VOID win32_graphics_driver_cleanup(GX_DISPLAY* display)
36 {
37 GX_WIN32_DISPLAY_DRIVER_DATA* instance;
38
39 instance = (GX_WIN32_DISPLAY_DRIVER_DATA*)display->gx_display_driver_data;
40
41 /* mark this instance as not used: */
42 instance->win32_driver_type = 0;
43 }
44
45 /**************************************************************************/
46 /* Get win32 instance data pointer. */
47 /**************************************************************************/
gx_win32_get_data_instance_head(void)48 GX_WIN32_DISPLAY_DRIVER_DATA* gx_win32_get_data_instance_head(void)
49 {
50 return win32_instance_data;
51 }
52
53 /**************************************************************************/
54 /* Get win32 instance data by thread id. */
55 /**************************************************************************/
gx_win32_get_data_instance_by_thread_id(LONG thread_id)56 GX_WIN32_DISPLAY_DRIVER_DATA *gx_win32_get_data_instance_by_thread_id(LONG thread_id)
57 {
58 int index;
59
60 if (!win32_graphics_data_initialized || !thread_id)
61 {
62 return(NULL);
63 }
64
65 for (index = 0; index < GX_MAX_WIN32_DISPLAYS; index++)
66 {
67 if (win32_instance_data[index].win32_driver_type == 0)
68 {
69 continue;
70 }
71
72 if (win32_instance_data[index].win32_window_ThreadId == thread_id ||
73 win32_instance_data[index].win32_guix_ThreadId == thread_id)
74 {
75 return(&win32_instance_data[index]);
76 }
77 }
78 return(0);
79 }
80
81 /**************************************************************************/
82 /* Set window handler for win32 dirver. */
83 /**************************************************************************/
gx_win32_set_win_handle(VOID * driver_data,HWND handle)84 VOID gx_win32_set_win_handle(VOID* driver_data, HWND handle)
85 {
86 GX_WIN32_DISPLAY_DRIVER_DATA* data = (GX_WIN32_DISPLAY_DRIVER_DATA*)driver_data;
87 data->win32_driver_winhandle = handle;
88 }
89
90 /**************************************************************************/
91 /* Set thread id for win32 driver. */
92 /**************************************************************************/
gx_win32_set_thread_id(VOID * driver_data,INT thread_id)93 VOID gx_win32_set_thread_id(VOID* driver_data, INT thread_id)
94 {
95 GX_WIN32_DISPLAY_DRIVER_DATA* data = (GX_WIN32_DISPLAY_DRIVER_DATA*)driver_data;
96 data->win32_window_ThreadId = thread_id;
97 }
98
99 /**************************************************************************/
100 /* Handle windows message. */
101 /**************************************************************************/
gx_win32_studio_event_process(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)102 LRESULT CALLBACK gx_win32_studio_event_process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
103 {
104 GX_WIN32_DISPLAY_DRIVER_DATA *driver_data;
105
106 driver_data = gx_win32_get_data_instance_by_win_handle(hwnd);
107
108 switch (message)
109 {
110 case WM_DESTROY:
111 {
112 RECT rect;
113 GetWindowRect(hwnd, &rect);
114
115 if (driver_data)
116 {
117 driver_data -> win32_window_xpos = rect.left;
118 driver_data -> win32_window_ypos = rect.top;
119 }
120 }
121 }
122 return gx_win32_event_process(hwnd, message, wParam, lParam);
123 }
124
125
126 /**************************************************************************/
127 /* Create window for guix and start guix thread in window. */
128 /**************************************************************************/
gx_win32_studio_driver_thread_entry(ULONG thread_input)129 void gx_win32_studio_driver_thread_entry(ULONG thread_input)
130 {
131 /* create a MS Windows window to serve as our physical display
132 This HAS to be done in the context of the win32 thread,
133 otherwise we don't get messages from MS Windows. Would prefer
134 to do this as part of the win32_graphics_driver function,
135 but that runs in the context of the GUIX thread so we can't do
136 it there.
137 */
138 GX_WIN32_DISPLAY_DRIVER_DATA *instance = (GX_WIN32_DISPLAY_DRIVER_DATA *)thread_input;
139
140 if (instance->win32_window_xpos < 0 ||
141 instance->win32_window_xpos >= (GetSystemMetrics(SM_CXVIRTUALSCREEN) - 10))
142 {
143 instance->win32_window_xpos = 20;
144 }
145
146 if (instance->win32_window_ypos < 0 ||
147 instance->win32_window_ypos >= (GetSystemMetrics(SM_CYVIRTUALSCREEN) - 10))
148 {
149 instance->win32_window_ypos = 20;
150 }
151
152 /* Create Win32 window. */
153 instance->win32_driver_winhandle = gx_win32_window_create(instance, gx_win32_studio_event_process,
154 instance->win32_window_xpos,
155 instance->win32_window_ypos);
156
157
158 /* Initialize thread. */
159 gx_win32_driver_thread_initialize(instance);
160 }
161 #endif /* WIN32 */
162
163