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