21 #include <winpr/sysinfo.h>
22 #include <winpr/cast.h>
26 #define TAG CLIENT_TAG("wayland.disp")
28 #define RESIZE_MIN_DELAY 200
30 struct s_wlfDispContext
33 DispClientContext* disp;
35 int eventBase, errorBase;
36 int lastSentWidth, lastSentHeight;
38 int targetWidth, targetHeight;
42 UINT16 lastSentDesktopOrientation;
43 UINT32 lastSentDesktopScaleFactor;
44 UINT32 lastSentDeviceScaleFactor;
47 static UINT wlf_disp_sendLayout(DispClientContext* disp,
const rdpMonitor* monitors,
50 static BOOL wlf_disp_settings_changed(wlfDispContext* wlfDisp)
52 rdpSettings* settings = NULL;
54 WINPR_ASSERT(wlfDisp);
55 WINPR_ASSERT(wlfDisp->wlc);
57 settings = wlfDisp->wlc->common.context.settings;
58 WINPR_ASSERT(settings);
60 if (wlfDisp->lastSentWidth != wlfDisp->targetWidth)
63 if (wlfDisp->lastSentHeight != wlfDisp->targetHeight)
66 if (wlfDisp->lastSentDesktopOrientation !=
70 if (wlfDisp->lastSentDesktopScaleFactor !=
74 if (wlfDisp->lastSentDeviceScaleFactor !=
78 if (wlfDisp->fullscreen != wlfDisp->wlc->fullscreen)
84 static BOOL wlf_update_last_sent(wlfDispContext* wlfDisp)
86 rdpSettings* settings = NULL;
88 WINPR_ASSERT(wlfDisp);
89 WINPR_ASSERT(wlfDisp->wlc);
91 settings = wlfDisp->wlc->common.context.settings;
92 WINPR_ASSERT(settings);
94 wlfDisp->lastSentWidth = wlfDisp->targetWidth;
95 wlfDisp->lastSentHeight = wlfDisp->targetHeight;
96 wlfDisp->lastSentDesktopOrientation =
98 wlfDisp->lastSentDesktopScaleFactor =
100 wlfDisp->lastSentDeviceScaleFactor =
102 wlfDisp->fullscreen = wlfDisp->wlc->fullscreen;
106 static BOOL wlf_disp_sendResize(wlfDispContext* wlfDisp)
110 rdpSettings* settings = NULL;
112 if (!wlfDisp || !wlfDisp->wlc)
116 settings = wlc->common.context.settings;
121 if (!wlfDisp->activated || !wlfDisp->disp)
124 if (GetTickCount64() - wlfDisp->lastSentDate < RESIZE_MIN_DELAY)
127 wlfDisp->lastSentDate = GetTickCount64();
129 if (!wlf_disp_settings_changed(wlfDisp))
142 wlfDisp->waitingResize = TRUE;
143 layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY;
144 layout.Top = layout.Left = 0;
145 layout.Width = WINPR_ASSERTING_INT_CAST(uint32_t, wlfDisp->targetWidth);
146 layout.Height = WINPR_ASSERTING_INT_CAST(uint32_t, wlfDisp->targetHeight);
148 layout.DesktopScaleFactor =
151 layout.PhysicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, wlfDisp->targetWidth);
152 layout.PhysicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, wlfDisp->targetHeight);
154 if (IFCALLRESULT(CHANNEL_RC_OK, wlfDisp->disp->SendMonitorLayout, wlfDisp->disp, 1,
155 &layout) != CHANNEL_RC_OK)
158 return wlf_update_last_sent(wlfDisp);
161 static BOOL wlf_disp_set_window_resizable(wlfDispContext* wlfDisp)
168 static BOOL wlf_disp_check_context(
void* context,
wlfContext** ppwlc, wlfDispContext** ppwlfDisp,
169 rdpSettings** ppSettings)
181 if (!wlc->common.context.settings)
185 *ppwlfDisp = wlc->disp;
186 *ppSettings = wlc->common.context.settings;
190 static void wlf_disp_OnActivated(
void* context,
const ActivatedEventArgs* e)
193 wlfDispContext* wlfDisp = NULL;
194 rdpSettings* settings = NULL;
196 if (!wlf_disp_check_context(context, &wlc, &wlfDisp, &settings))
199 wlfDisp->waitingResize = FALSE;
203 wlf_disp_set_window_resizable(wlfDisp);
205 if (e->firstActivation)
208 wlf_disp_sendResize(wlfDisp);
212 static void wlf_disp_OnGraphicsReset(
void* context,
const GraphicsResetEventArgs* e)
215 wlfDispContext* wlfDisp = NULL;
216 rdpSettings* settings = NULL;
219 if (!wlf_disp_check_context(context, &wlc, &wlfDisp, &settings))
222 wlfDisp->waitingResize = FALSE;
226 wlf_disp_set_window_resizable(wlfDisp);
227 wlf_disp_sendResize(wlfDisp);
231 static void wlf_disp_OnTimer(
void* context,
const TimerEventArgs* e)
234 wlfDispContext* wlfDisp = NULL;
235 rdpSettings* settings = NULL;
238 if (!wlf_disp_check_context(context, &wlc, &wlfDisp, &settings))
244 wlf_disp_sendResize(wlfDisp);
249 wlfDispContext* ret = NULL;
250 wPubSub* pubSub = NULL;
251 rdpSettings* settings = NULL;
253 if (!wlc || !wlc->common.context.settings || !wlc->common.context.pubSub)
256 settings = wlc->common.context.settings;
257 pubSub = wlc->common.context.pubSub;
258 ret = calloc(1,
sizeof(wlfDispContext));
264 ret->lastSentWidth = ret->targetWidth =
266 ret->lastSentHeight = ret->targetHeight =
268 PubSub_SubscribeActivated(pubSub, wlf_disp_OnActivated);
269 PubSub_SubscribeGraphicsReset(pubSub, wlf_disp_OnGraphicsReset);
270 PubSub_SubscribeTimer(pubSub, wlf_disp_OnTimer);
274 void wlf_disp_free(wlfDispContext* disp)
281 wPubSub* pubSub = disp->wlc->common.context.pubSub;
282 PubSub_UnsubscribeActivated(pubSub, wlf_disp_OnActivated);
283 PubSub_UnsubscribeGraphicsReset(pubSub, wlf_disp_OnGraphicsReset);
284 PubSub_UnsubscribeTimer(pubSub, wlf_disp_OnTimer);
290 UINT wlf_disp_sendLayout(DispClientContext* disp,
const rdpMonitor* monitors,
size_t nmonitors)
292 UINT ret = CHANNEL_RC_OK;
294 wlfDispContext* wlfDisp = NULL;
295 rdpSettings* settings = NULL;
298 WINPR_ASSERT(monitors);
299 WINPR_ASSERT(nmonitors > 0);
300 WINPR_ASSERT(nmonitors <= UINT32_MAX);
302 wlfDisp = (wlfDispContext*)disp->custom;
303 WINPR_ASSERT(wlfDisp);
304 WINPR_ASSERT(wlfDisp->wlc);
306 settings = wlfDisp->wlc->common.context.settings;
307 WINPR_ASSERT(settings);
312 return CHANNEL_RC_NO_MEMORY;
314 for (
size_t i = 0; i < nmonitors; i++)
319 layout->Flags = (monitor->is_primary ? DISPLAY_CONTROL_MONITOR_PRIMARY : 0);
320 layout->Left = monitor->x;
321 layout->Top = monitor->y;
322 layout->Width = WINPR_ASSERTING_INT_CAST(UINT32, monitor->width);
323 layout->Height = WINPR_ASSERTING_INT_CAST(UINT32, monitor->height);
324 layout->Orientation = ORIENTATION_LANDSCAPE;
325 layout->PhysicalWidth = monitor->attributes.physicalWidth;
326 layout->PhysicalHeight = monitor->attributes.physicalHeight;
328 switch (monitor->attributes.orientation)
331 layout->Orientation = ORIENTATION_PORTRAIT;
335 layout->Orientation = ORIENTATION_LANDSCAPE_FLIPPED;
339 layout->Orientation = ORIENTATION_PORTRAIT_FLIPPED;
351 layout->Orientation = ORIENTATION_LANDSCAPE;
355 layout->DesktopScaleFactor =
357 layout->DeviceScaleFactor =
361 ret = IFCALLRESULT(CHANNEL_RC_OK, disp->SendMonitorLayout, disp, (UINT32)nmonitors, layouts);
366 BOOL wlf_disp_handle_configure(wlfDispContext* disp, int32_t width, int32_t height)
371 disp->targetWidth = width;
372 disp->targetHeight = height;
373 return wlf_disp_sendResize(disp);
376 static UINT wlf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,
377 UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB)
380 wlfDispContext* wlfDisp = NULL;
381 rdpSettings* settings = NULL;
385 wlfDisp = (wlfDispContext*)disp->custom;
386 WINPR_ASSERT(wlfDisp);
387 WINPR_ASSERT(wlfDisp->wlc);
389 settings = wlfDisp->wlc->common.context.settings;
390 WINPR_ASSERT(settings);
393 "DisplayControlCapsPdu: MaxNumMonitors: %" PRIu32
" MaxMonitorAreaFactorA: %" PRIu32
394 " MaxMonitorAreaFactorB: %" PRIu32
"",
395 maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB);
396 wlfDisp->activated = TRUE;
399 return CHANNEL_RC_OK;
401 WLog_DBG(TAG,
"DisplayControlCapsPdu: setting the window as resizable");
402 return wlf_disp_set_window_resizable(wlfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY;
405 BOOL wlf_disp_init(wlfDispContext* wlfDisp, DispClientContext* disp)
407 rdpSettings* settings = NULL;
409 if (!wlfDisp || !wlfDisp->wlc || !disp)
412 settings = wlfDisp->wlc->common.context.settings;
417 wlfDisp->disp = disp;
418 disp->custom = (
void*)wlfDisp;
422 disp->DisplayControlCaps = wlf_DisplayControlCaps;
428 BOOL wlf_disp_uninit(wlfDispContext* wlfDisp, DispClientContext* disp)
430 if (!wlfDisp || !disp)
433 wlfDisp->disp = NULL;
439 uint32_t nmonitors = UwacDisplayGetNbOutputs(wlc->display);
441 for (uint32_t i = 0; i < nmonitors; i++)
443 const UwacOutput* monitor =
444 UwacDisplayGetOutput(wlc->display, WINPR_ASSERTING_INT_CAST(
int, i));
450 UwacOutputGetPosition(monitor, &pos);
451 UwacOutputGetResolution(monitor, &resolution);
453 printf(
" %s [%u] %dx%d\t+%d+%d\n", (i == 0) ?
"*" :
" ", i, resolution.width,
454 resolution.height, pos.x, pos.y);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.