FreeRDP
Loading...
Searching...
No Matches
wf_floatbar.c
1
20#include <winpr/crt.h>
21#include <winpr/windows.h>
22
23#include "wf_client.h"
24#include "wf_floatbar.h"
25
26#include "resource/resource.h"
27#include "wf_gdi.h"
28#ifdef _MSC_VER
29#pragma comment(lib, "Msimg32.lib")
30#endif
31
32#define TAG CLIENT_TAG("windows.floatbar")
33
34/* TIMERs */
35#define TIMER_HIDE 1
36#define TIMER_ANIMAT_SHOW 2
37#define TIMER_ANIMAT_HIDE 3
38
39/* Button Type */
40#define BUTTON_LOCKPIN 0
41#define BUTTON_MINIMIZE 1
42#define BUTTON_RESTORE 2
43#define BUTTON_CLOSE 3
44#define BTN_MAX 4
45
46/* bmp size */
47#define BACKGROUND_W 576
48#define BACKGROUND_H 27
49#define BUTTON_OFFSET 5
50#define BUTTON_Y 2
51#define BUTTON_WIDTH 23
52#define BUTTON_HEIGHT 21
53#define BUTTON_SPACING 1
54
55#define LOCK_X (BACKGROUND_H + BUTTON_OFFSET)
56#define CLOSE_X ((BACKGROUND_W - (BACKGROUND_H + BUTTON_OFFSET)) - BUTTON_WIDTH)
57#define RESTORE_X (CLOSE_X - (BUTTON_WIDTH + BUTTON_SPACING))
58#define MINIMIZE_X (RESTORE_X - (BUTTON_WIDTH + BUTTON_SPACING))
59#define TEXT_X (BACKGROUND_H + ((BUTTON_WIDTH + BUTTON_SPACING) * 3) + 5)
60
61typedef struct
62{
63 wfFloatBar* floatbar;
64 int type;
65 int x, y, h, w;
66 int active;
67 HBITMAP bmp;
68 HBITMAP bmp_act;
69
70 /* Lock Specified */
71 HBITMAP locked_bmp;
72 HBITMAP locked_bmp_act;
73 HBITMAP unlocked_bmp;
74 HBITMAP unlocked_bmp_act;
75} Button;
76
77struct s_FloatBar
78{
79 HINSTANCE root_window;
80 DWORD flags;
81 HWND parent;
82 HWND hwnd;
83 RECT rect;
84 LONG width;
85 LONG height;
86 LONG offset;
87 wfContext* wfc;
88 Button* buttons[BTN_MAX];
89 BOOL shown;
90 BOOL locked;
91 HDC hdcmem;
92 RECT textRect;
93 UINT_PTR animating;
94};
95
96static BOOL floatbar_kill_timers(wfFloatBar* floatbar)
97{
98 UINT_PTR timers[] = { TIMER_HIDE, TIMER_ANIMAT_HIDE, TIMER_ANIMAT_SHOW };
99
100 if (!floatbar)
101 return FALSE;
102
103 for (size_t x = 0; x < ARRAYSIZE(timers); x++)
104 KillTimer(floatbar->hwnd, timers[x]);
105
106 floatbar->animating = 0;
107 return TRUE;
108}
109
110static BOOL floatbar_animation(wfFloatBar* const floatbar, const BOOL show)
111{
112 UINT_PTR timer = show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE;
113
114 if (!floatbar)
115 return FALSE;
116
117 if (floatbar->shown == show)
118 return TRUE;
119
120 if (floatbar->animating == timer)
121 return TRUE;
122
123 floatbar->animating = timer;
124
125 if (SetTimer(floatbar->hwnd, timer, USER_TIMER_MINIMUM, NULL) == 0)
126 {
127 DWORD err = GetLastError();
128 WLog_ERR(TAG, "SetTimer failed with %08" PRIx32, err);
129 return FALSE;
130 }
131
132 return TRUE;
133}
134
135static BOOL floatbar_trigger_hide(wfFloatBar* floatbar)
136{
137 if (!floatbar_kill_timers(floatbar))
138 return FALSE;
139
140 if (!floatbar->locked && floatbar->shown)
141 {
142 if (SetTimer(floatbar->hwnd, TIMER_HIDE, 3000, NULL) == 0)
143 {
144 DWORD err = GetLastError();
145 WLog_ERR(TAG, "SetTimer failed with %08" PRIx32, err);
146 return FALSE;
147 }
148 }
149
150 return TRUE;
151}
152
153static BOOL floatbar_hide(wfFloatBar* floatbar)
154{
155 if (!floatbar_kill_timers(floatbar))
156 return FALSE;
157
158 floatbar->offset = floatbar->height - 2;
159
160 if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
161 floatbar->height, TRUE))
162 {
163 DWORD err = GetLastError();
164 WLog_ERR(TAG, "MoveWindow failed with %08" PRIx32, err);
165 return FALSE;
166 }
167
168 floatbar->shown = FALSE;
169
170 if (!floatbar_trigger_hide(floatbar))
171 return FALSE;
172
173 return TRUE;
174}
175
176static BOOL floatbar_show(wfFloatBar* floatbar)
177{
178 if (!floatbar_kill_timers(floatbar))
179 return FALSE;
180
181 floatbar->offset = 0;
182
183 if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
184 floatbar->height, TRUE))
185 {
186 DWORD err = GetLastError();
187 WLog_ERR(TAG, "MoveWindow failed with %08" PRIx32, err);
188 return FALSE;
189 }
190
191 floatbar->shown = TRUE;
192
193 if (!floatbar_trigger_hide(floatbar))
194 return FALSE;
195
196 return TRUE;
197}
198
199static BOOL button_set_locked(Button* button, BOOL locked)
200{
201 if (locked)
202 {
203 button->bmp = button->locked_bmp;
204 button->bmp_act = button->locked_bmp_act;
205 }
206 else
207 {
208 button->bmp = button->unlocked_bmp;
209 button->bmp_act = button->unlocked_bmp_act;
210 }
211
212 InvalidateRect(button->floatbar->hwnd, NULL, FALSE);
213 UpdateWindow(button->floatbar->hwnd);
214 return TRUE;
215}
216
217static BOOL update_locked_state(wfFloatBar* floatbar)
218{
219 Button* button;
220
221 if (!floatbar)
222 return FALSE;
223
224 button = floatbar->buttons[3];
225
226 if (!button_set_locked(button, floatbar->locked))
227 return FALSE;
228
229 return TRUE;
230}
231
232static int button_hit(Button* const button)
233{
234 wfFloatBar* const floatbar = button->floatbar;
235
236 switch (button->type)
237 {
238 case BUTTON_LOCKPIN:
239 floatbar->locked = !floatbar->locked;
240 update_locked_state(floatbar);
241 break;
242
243 case BUTTON_MINIMIZE:
244 ShowWindow(floatbar->parent, SW_MINIMIZE);
245 break;
246
247 case BUTTON_RESTORE:
248 wf_toggle_fullscreen(floatbar->wfc);
249 break;
250
251 case BUTTON_CLOSE:
252 SendMessage(floatbar->parent, WM_DESTROY, 0, 0);
253 break;
254
255 default:
256 return 0;
257 }
258
259 return 0;
260}
261
262static int button_paint(const Button* const button, const HDC hdc)
263{
264 if (button != NULL)
265 {
266 wfFloatBar* floatbar = button->floatbar;
267 BLENDFUNCTION bf;
268 SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp);
269 bf.BlendOp = AC_SRC_OVER;
270 bf.BlendFlags = 0;
271 bf.SourceConstantAlpha = 255;
272 bf.AlphaFormat = AC_SRC_ALPHA;
273 AlphaBlend(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0,
274 button->w, button->h, bf);
275 }
276
277 return 0;
278}
279
280static Button* floatbar_create_button(wfFloatBar* const floatbar, const int type, const int resid,
281 const int resid_act, const int x, const int y, const int h,
282 const int w)
283{
284 Button* button = (Button*)calloc(1, sizeof(Button));
285
286 if (!button)
287 return NULL;
288
289 button->floatbar = floatbar;
290 button->type = type;
291 button->x = x;
292 button->y = y;
293 button->w = w;
294 button->h = h;
295 button->active = FALSE;
296 button->bmp = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid), IMAGE_BITMAP, 0,
297 0, LR_DEFAULTCOLOR);
298 button->bmp_act = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid_act),
299 IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
300 return button;
301}
302
303static Button* floatbar_create_lock_button(wfFloatBar* const floatbar, const int unlock_resid,
304 const int unlock_resid_act, const int lock_resid,
305 const int lock_resid_act, const int x, const int y,
306 const int h, const int w)
307{
308 Button* button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid,
309 unlock_resid_act, x, y, h, w);
310
311 if (!button)
312 return NULL;
313
314 button->unlocked_bmp = button->bmp;
315 button->unlocked_bmp_act = button->bmp_act;
316 button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid),
317 IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
318 button->locked_bmp_act =
319 (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP,
320 0, 0, LR_DEFAULTCOLOR);
321 return button;
322}
323
324static Button* floatbar_get_button(const wfFloatBar* const floatbar, const int x, const int y)
325{
326 if ((y > BUTTON_Y) && (y < BUTTON_Y + BUTTON_HEIGHT))
327 {
328 for (int i = 0; i < BTN_MAX; i++)
329 {
330 if ((floatbar->buttons[i] != NULL) && (x > floatbar->buttons[i]->x) &&
331 (x < floatbar->buttons[i]->x + floatbar->buttons[i]->w))
332 {
333 return floatbar->buttons[i];
334 }
335 }
336 }
337
338 return NULL;
339}
340
341static BOOL floatbar_paint(wfFloatBar* const floatbar, const HDC hdc)
342{
343 HPEN hpen;
344 HGDIOBJECT orig;
345 /* paint background */
346 GRADIENT_RECT gradientRect = { 0, 1 };
347 COLORREF rgbTop = RGB(117, 154, 198);
348 COLORREF rgbBottom = RGB(6, 55, 120);
349 const int top = 0;
350 int left = 0;
351 int bottom = BACKGROUND_H - 1;
352 int right = BACKGROUND_W - 1;
353 const int angleOffset = BACKGROUND_H - 1;
354 TRIVERTEX triVertext[2] = { { left, top, GetRValue(rgbTop) << 8, GetGValue(rgbTop) << 8,
355 GetBValue(rgbTop) << 8, 0x0000 },
356 { right, bottom, GetRValue(rgbBottom) << 8,
357 GetGValue(rgbBottom) << 8, GetBValue(rgbBottom) << 8, 0x0000 } };
358
359 if (!floatbar)
360 return FALSE;
361
362 GradientFill(hdc, triVertext, 2, &gradientRect, 1, GRADIENT_FILL_RECT_V);
363 /* paint shadow */
364 hpen = CreatePen(PS_SOLID, 1, RGB(71, 71, 71));
365 orig = SelectObject(hdc, hpen);
366 MoveToEx(hdc, left, top, NULL);
367 LineTo(hdc, left + angleOffset, bottom);
368 LineTo(hdc, right - angleOffset, bottom);
369 LineTo(hdc, right + 1, top - 1);
370 DeleteObject(hpen);
371 hpen = CreatePen(PS_SOLID, 1, RGB(107, 141, 184));
372 SelectObject(hdc, hpen);
373 left += 1;
374 bottom -= 1;
375 right -= 1;
376 MoveToEx(hdc, left, top, NULL);
377 LineTo(hdc, left + (angleOffset - 1), bottom);
378 LineTo(hdc, right - (angleOffset - 1), bottom);
379 LineTo(hdc, right + 1, top - 1);
380 DeleteObject(hpen);
381 SelectObject(hdc, orig);
382
383 const size_t wlen = wcslen(floatbar->wfc->window_title);
384 DrawText(hdc, floatbar->wfc->window_title, WINPR_ASSERTING_INT_CAST(int, wlen),
385 &floatbar->textRect,
386 DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
387
388 /* paint buttons */
389
390 for (int i = 0; i < BTN_MAX; i++)
391 button_paint(floatbar->buttons[i], hdc);
392
393 return TRUE;
394}
395
396static LRESULT CALLBACK floatbar_proc(const HWND hWnd, const UINT Msg, const WPARAM wParam,
397 const LPARAM lParam)
398{
399 static int dragging = FALSE;
400 static int lbtn_dwn = FALSE;
401 static int btn_dwn_x = 0;
402 static wfFloatBar* floatbar;
403 static TRACKMOUSEEVENT tme;
404 PAINTSTRUCT ps;
405 Button* button;
406 HDC hdc;
407 int pos_x;
408 int pos_y;
409 NONCLIENTMETRICS ncm;
410 int xScreen = GetSystemMetrics(SM_CXSCREEN);
411
412 switch (Msg)
413 {
414 case WM_CREATE:
415 floatbar = ((wfFloatBar*)((CREATESTRUCT*)lParam)->lpCreateParams);
416 floatbar->hwnd = hWnd;
417 GetWindowRect(floatbar->hwnd, &floatbar->rect);
418 floatbar->width = floatbar->rect.right - floatbar->rect.left;
419 floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
420 hdc = GetDC(hWnd);
421 floatbar->hdcmem = CreateCompatibleDC(hdc);
422 ReleaseDC(hWnd, hdc);
423 tme.cbSize = sizeof(TRACKMOUSEEVENT);
424 tme.dwFlags = TME_LEAVE;
425 tme.hwndTrack = hWnd;
426 tme.dwHoverTime = HOVER_DEFAULT;
427 // Use caption font, white, draw transparent
428 GetClientRect(hWnd, &floatbar->textRect);
429 InflateRect(&floatbar->textRect, -TEXT_X, 0);
430 SetBkMode(hdc, TRANSPARENT);
431 SetTextColor(hdc, RGB(255, 255, 255));
432 ncm.cbSize = sizeof(NONCLIENTMETRICS);
433 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
434 SelectObject(hdc, CreateFontIndirect(&ncm.lfCaptionFont));
435 floatbar_trigger_hide(floatbar);
436 break;
437
438 case WM_PAINT:
439 hdc = BeginPaint(hWnd, &ps);
440 floatbar_paint(floatbar, hdc);
441 EndPaint(hWnd, &ps);
442 break;
443
444 case WM_LBUTTONDOWN:
445 pos_x = lParam & 0xffff;
446 pos_y = (lParam >> 16) & 0xffff;
447 button = floatbar_get_button(floatbar, pos_x, pos_y);
448
449 if (!button)
450 {
451 SetCapture(hWnd);
452 dragging = TRUE;
453 btn_dwn_x = lParam & 0xffff;
454 }
455 else
456 lbtn_dwn = TRUE;
457
458 break;
459
460 case WM_LBUTTONUP:
461 pos_x = lParam & 0xffff;
462 pos_y = (lParam >> 16) & 0xffff;
463 ReleaseCapture();
464 dragging = FALSE;
465
466 if (lbtn_dwn)
467 {
468 button = floatbar_get_button(floatbar, pos_x, pos_y);
469
470 if (button)
471 button_hit(button);
472
473 lbtn_dwn = FALSE;
474 }
475
476 break;
477
478 case WM_MOUSEMOVE:
479 pos_x = lParam & 0xffff;
480 pos_y = (lParam >> 16) & 0xffff;
481
482 if (!floatbar->locked)
483 floatbar_animation(floatbar, TRUE);
484
485 if (dragging)
486 {
487 floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x;
488
489 if (floatbar->rect.left < 0)
490 floatbar->rect.left = 0;
491 else if (floatbar->rect.left > xScreen - floatbar->width)
492 floatbar->rect.left = xScreen - floatbar->width;
493
494 MoveWindow(hWnd, floatbar->rect.left, 0, floatbar->width, floatbar->height, TRUE);
495 }
496 else
497 {
498 for (int i = 0; i < BTN_MAX; i++)
499 {
500 if (floatbar->buttons[i] != NULL)
501 {
502 floatbar->buttons[i]->active = FALSE;
503 }
504 }
505
506 button = floatbar_get_button(floatbar, pos_x, pos_y);
507
508 if (button)
509 button->active = TRUE;
510
511 InvalidateRect(hWnd, NULL, FALSE);
512 UpdateWindow(hWnd);
513 }
514
515 TrackMouseEvent(&tme);
516 break;
517
518 case WM_CAPTURECHANGED:
519 dragging = FALSE;
520 break;
521
522 case WM_MOUSELEAVE:
523 {
524 for (int i = 0; i < BTN_MAX; i++)
525 {
526 if (floatbar->buttons[i] != NULL)
527 {
528 floatbar->buttons[i]->active = FALSE;
529 }
530 }
531
532 InvalidateRect(hWnd, NULL, FALSE);
533 UpdateWindow(hWnd);
534 floatbar_trigger_hide(floatbar);
535 break;
536 }
537
538 case WM_TIMER:
539 switch (wParam)
540 {
541 case TIMER_HIDE:
542 floatbar_animation(floatbar, FALSE);
543 break;
544
545 case TIMER_ANIMAT_SHOW:
546 {
547 floatbar->offset--;
548 MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
549 floatbar->width, floatbar->height, TRUE);
550
551 if (floatbar->offset <= 0)
552 floatbar_show(floatbar);
553
554 break;
555 }
556
557 case TIMER_ANIMAT_HIDE:
558 {
559 floatbar->offset++;
560 MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
561 floatbar->width, floatbar->height, TRUE);
562
563 if (floatbar->offset >= floatbar->height - 2)
564 floatbar_hide(floatbar);
565
566 break;
567 }
568
569 default:
570 break;
571 }
572
573 break;
574
575 case WM_DESTROY:
576 DeleteDC(floatbar->hdcmem);
577 PostQuitMessage(0);
578 break;
579
580 default:
581 return DefWindowProc(hWnd, Msg, wParam, lParam);
582 }
583
584 return 0;
585}
586
587static BOOL floatbar_window_create(wfFloatBar* floatbar)
588{
589 WNDCLASSEX wnd_cls;
590 HWND barWnd;
591 HRGN hRgn;
592 POINT pt[4];
593 RECT rect;
594 LONG x;
595
596 if (!floatbar)
597 return FALSE;
598
599 if (!GetWindowRect(floatbar->parent, &rect))
600 return FALSE;
601
602 x = (rect.right - rect.left - BACKGROUND_W) / 2;
603 wnd_cls.cbSize = sizeof(WNDCLASSEX);
604 wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
605 wnd_cls.lpfnWndProc = floatbar_proc;
606 wnd_cls.cbClsExtra = 0;
607 wnd_cls.cbWndExtra = 0;
608 wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
609 wnd_cls.hCursor = LoadCursor(floatbar->root_window, IDC_ARROW);
610 wnd_cls.hbrBackground = NULL;
611 wnd_cls.lpszMenuName = NULL;
612 wnd_cls.lpszClassName = L"floatbar";
613 wnd_cls.hInstance = floatbar->root_window;
614 wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
615 RegisterClassEx(&wnd_cls);
616 barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W,
617 BACKGROUND_H, floatbar->parent, NULL, floatbar->root_window, floatbar);
618
619 if (barWnd == NULL)
620 return FALSE;
621
622 pt[0].x = 0;
623 pt[0].y = 0;
624 pt[1].x = BACKGROUND_W;
625 pt[1].y = 0;
626 pt[2].x = BACKGROUND_W - BACKGROUND_H;
627 pt[2].y = BACKGROUND_H;
628 pt[3].x = BACKGROUND_H;
629 pt[3].y = BACKGROUND_H;
630 hRgn = CreatePolygonRgn(pt, 4, ALTERNATE);
631 SetWindowRgn(barWnd, hRgn, TRUE);
632 return TRUE;
633}
634
635void wf_floatbar_free(wfFloatBar* floatbar)
636{
637 if (!floatbar)
638 return;
639
640 free(floatbar);
641}
642
643wfFloatBar* wf_floatbar_new(wfContext* wfc, HINSTANCE window, DWORD flags)
644{
645 wfFloatBar* floatbar;
646
647 /* Floatbar not enabled */
648 if ((flags & 0x0001) == 0)
649 return NULL;
650
651 if (!wfc)
652 return NULL;
653
654 // TODO: Disable for remote app
655 floatbar = (wfFloatBar*)calloc(1, sizeof(wfFloatBar));
656
657 if (!floatbar)
658 return NULL;
659
660 floatbar->root_window = window;
661 floatbar->flags = flags;
662 floatbar->wfc = wfc;
663 floatbar->locked = (flags & 0x0002) != 0;
664 floatbar->shown = (flags & 0x0006) != 0; /* If it is loked or shown show it */
665 floatbar->hwnd = NULL;
666 floatbar->parent = wfc->hwnd;
667 floatbar->hdcmem = NULL;
668
669 if (wfc->fullscreen_toggle)
670 {
671 floatbar->buttons[0] =
672 floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT,
673 MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
674 floatbar->buttons[1] =
675 floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT,
676 RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
677 }
678 else
679 {
680 floatbar->buttons[0] = NULL;
681 floatbar->buttons[1] = NULL;
682 }
683
684 floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT,
685 CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
686 floatbar->buttons[3] =
687 floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT,
688 LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
689
690 if (!floatbar_window_create(floatbar))
691 goto fail;
692
693 if (!update_locked_state(floatbar))
694 goto fail;
695
696 if (!wf_floatbar_toggle_fullscreen(
697 floatbar, freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_Fullscreen)))
698 goto fail;
699
700 return floatbar;
701fail:
702 wf_floatbar_free(floatbar);
703 return NULL;
704}
705
706BOOL wf_floatbar_toggle_fullscreen(wfFloatBar* floatbar, BOOL fullscreen)
707{
708 BOOL show_fs, show_wn;
709
710 if (!floatbar)
711 return FALSE;
712
713 show_fs = (floatbar->flags & 0x0010) != 0;
714 show_wn = (floatbar->flags & 0x0020) != 0;
715
716 if ((show_fs && fullscreen) || (show_wn && !fullscreen))
717 {
718 ShowWindow(floatbar->hwnd, SW_SHOWNORMAL);
719 Sleep(10);
720
721 if (floatbar->shown)
722 floatbar_show(floatbar);
723 else
724 floatbar_hide(floatbar);
725 }
726 else
727 {
728 ShowWindow(floatbar->hwnd, SW_HIDE);
729 }
730
731 return TRUE;
732}
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.