FreeRDP
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 
61 typedef 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 
77 struct 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 
96 static 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 
110 static 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 
135 static 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 
153 static 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 
176 static 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 
199 static 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 
217 static 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 
232 static 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 
262 static 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 
280 static 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 
303 static 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 
324 static 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 
341 static 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  DrawText(hdc, floatbar->wfc->window_title, wcslen(floatbar->wfc->window_title),
383  &floatbar->textRect,
384  DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
385 
386  /* paint buttons */
387 
388  for (int i = 0; i < BTN_MAX; i++)
389  button_paint(floatbar->buttons[i], hdc);
390 
391  return TRUE;
392 }
393 
394 static LRESULT CALLBACK floatbar_proc(const HWND hWnd, const UINT Msg, const WPARAM wParam,
395  const LPARAM lParam)
396 {
397  static int dragging = FALSE;
398  static int lbtn_dwn = FALSE;
399  static int btn_dwn_x = 0;
400  static wfFloatBar* floatbar;
401  static TRACKMOUSEEVENT tme;
402  PAINTSTRUCT ps;
403  Button* button;
404  HDC hdc;
405  int pos_x;
406  int pos_y;
407  NONCLIENTMETRICS ncm;
408  int xScreen = GetSystemMetrics(SM_CXSCREEN);
409 
410  switch (Msg)
411  {
412  case WM_CREATE:
413  floatbar = ((wfFloatBar*)((CREATESTRUCT*)lParam)->lpCreateParams);
414  floatbar->hwnd = hWnd;
415  GetWindowRect(floatbar->hwnd, &floatbar->rect);
416  floatbar->width = floatbar->rect.right - floatbar->rect.left;
417  floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
418  hdc = GetDC(hWnd);
419  floatbar->hdcmem = CreateCompatibleDC(hdc);
420  ReleaseDC(hWnd, hdc);
421  tme.cbSize = sizeof(TRACKMOUSEEVENT);
422  tme.dwFlags = TME_LEAVE;
423  tme.hwndTrack = hWnd;
424  tme.dwHoverTime = HOVER_DEFAULT;
425  // Use caption font, white, draw transparent
426  GetClientRect(hWnd, &floatbar->textRect);
427  InflateRect(&floatbar->textRect, -TEXT_X, 0);
428  SetBkMode(hdc, TRANSPARENT);
429  SetTextColor(hdc, RGB(255, 255, 255));
430  ncm.cbSize = sizeof(NONCLIENTMETRICS);
431  SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
432  SelectObject(hdc, CreateFontIndirect(&ncm.lfCaptionFont));
433  floatbar_trigger_hide(floatbar);
434  break;
435 
436  case WM_PAINT:
437  hdc = BeginPaint(hWnd, &ps);
438  floatbar_paint(floatbar, hdc);
439  EndPaint(hWnd, &ps);
440  break;
441 
442  case WM_LBUTTONDOWN:
443  pos_x = lParam & 0xffff;
444  pos_y = (lParam >> 16) & 0xffff;
445  button = floatbar_get_button(floatbar, pos_x, pos_y);
446 
447  if (!button)
448  {
449  SetCapture(hWnd);
450  dragging = TRUE;
451  btn_dwn_x = lParam & 0xffff;
452  }
453  else
454  lbtn_dwn = TRUE;
455 
456  break;
457 
458  case WM_LBUTTONUP:
459  pos_x = lParam & 0xffff;
460  pos_y = (lParam >> 16) & 0xffff;
461  ReleaseCapture();
462  dragging = FALSE;
463 
464  if (lbtn_dwn)
465  {
466  button = floatbar_get_button(floatbar, pos_x, pos_y);
467 
468  if (button)
469  button_hit(button);
470 
471  lbtn_dwn = FALSE;
472  }
473 
474  break;
475 
476  case WM_MOUSEMOVE:
477  pos_x = lParam & 0xffff;
478  pos_y = (lParam >> 16) & 0xffff;
479 
480  if (!floatbar->locked)
481  floatbar_animation(floatbar, TRUE);
482 
483  if (dragging)
484  {
485  floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x;
486 
487  if (floatbar->rect.left < 0)
488  floatbar->rect.left = 0;
489  else if (floatbar->rect.left > xScreen - floatbar->width)
490  floatbar->rect.left = xScreen - floatbar->width;
491 
492  MoveWindow(hWnd, floatbar->rect.left, 0, floatbar->width, floatbar->height, TRUE);
493  }
494  else
495  {
496  for (int i = 0; i < BTN_MAX; i++)
497  {
498  if (floatbar->buttons[i] != NULL)
499  {
500  floatbar->buttons[i]->active = FALSE;
501  }
502  }
503 
504  button = floatbar_get_button(floatbar, pos_x, pos_y);
505 
506  if (button)
507  button->active = TRUE;
508 
509  InvalidateRect(hWnd, NULL, FALSE);
510  UpdateWindow(hWnd);
511  }
512 
513  TrackMouseEvent(&tme);
514  break;
515 
516  case WM_CAPTURECHANGED:
517  dragging = FALSE;
518  break;
519 
520  case WM_MOUSELEAVE:
521  {
522  for (int i = 0; i < BTN_MAX; i++)
523  {
524  if (floatbar->buttons[i] != NULL)
525  {
526  floatbar->buttons[i]->active = FALSE;
527  }
528  }
529 
530  InvalidateRect(hWnd, NULL, FALSE);
531  UpdateWindow(hWnd);
532  floatbar_trigger_hide(floatbar);
533  break;
534  }
535 
536  case WM_TIMER:
537  switch (wParam)
538  {
539  case TIMER_HIDE:
540  floatbar_animation(floatbar, FALSE);
541  break;
542 
543  case TIMER_ANIMAT_SHOW:
544  {
545  floatbar->offset--;
546  MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
547  floatbar->width, floatbar->height, TRUE);
548 
549  if (floatbar->offset <= 0)
550  floatbar_show(floatbar);
551 
552  break;
553  }
554 
555  case TIMER_ANIMAT_HIDE:
556  {
557  floatbar->offset++;
558  MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
559  floatbar->width, floatbar->height, TRUE);
560 
561  if (floatbar->offset >= floatbar->height - 2)
562  floatbar_hide(floatbar);
563 
564  break;
565  }
566 
567  default:
568  break;
569  }
570 
571  break;
572 
573  case WM_DESTROY:
574  DeleteDC(floatbar->hdcmem);
575  PostQuitMessage(0);
576  break;
577 
578  default:
579  return DefWindowProc(hWnd, Msg, wParam, lParam);
580  }
581 
582  return 0;
583 }
584 
585 static BOOL floatbar_window_create(wfFloatBar* floatbar)
586 {
587  WNDCLASSEX wnd_cls;
588  HWND barWnd;
589  HRGN hRgn;
590  POINT pt[4];
591  RECT rect;
592  LONG x;
593 
594  if (!floatbar)
595  return FALSE;
596 
597  if (!GetWindowRect(floatbar->parent, &rect))
598  return FALSE;
599 
600  x = (rect.right - rect.left - BACKGROUND_W) / 2;
601  wnd_cls.cbSize = sizeof(WNDCLASSEX);
602  wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
603  wnd_cls.lpfnWndProc = floatbar_proc;
604  wnd_cls.cbClsExtra = 0;
605  wnd_cls.cbWndExtra = 0;
606  wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
607  wnd_cls.hCursor = LoadCursor(floatbar->root_window, IDC_ARROW);
608  wnd_cls.hbrBackground = NULL;
609  wnd_cls.lpszMenuName = NULL;
610  wnd_cls.lpszClassName = L"floatbar";
611  wnd_cls.hInstance = floatbar->root_window;
612  wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
613  RegisterClassEx(&wnd_cls);
614  barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W,
615  BACKGROUND_H, floatbar->parent, NULL, floatbar->root_window, floatbar);
616 
617  if (barWnd == NULL)
618  return FALSE;
619 
620  pt[0].x = 0;
621  pt[0].y = 0;
622  pt[1].x = BACKGROUND_W;
623  pt[1].y = 0;
624  pt[2].x = BACKGROUND_W - BACKGROUND_H;
625  pt[2].y = BACKGROUND_H;
626  pt[3].x = BACKGROUND_H;
627  pt[3].y = BACKGROUND_H;
628  hRgn = CreatePolygonRgn(pt, 4, ALTERNATE);
629  SetWindowRgn(barWnd, hRgn, TRUE);
630  return TRUE;
631 }
632 
633 void wf_floatbar_free(wfFloatBar* floatbar)
634 {
635  if (!floatbar)
636  return;
637 
638  free(floatbar);
639 }
640 
641 wfFloatBar* wf_floatbar_new(wfContext* wfc, HINSTANCE window, DWORD flags)
642 {
643  wfFloatBar* floatbar;
644 
645  /* Floatbar not enabled */
646  if ((flags & 0x0001) == 0)
647  return NULL;
648 
649  if (!wfc)
650  return NULL;
651 
652  // TODO: Disable for remote app
653  floatbar = (wfFloatBar*)calloc(1, sizeof(wfFloatBar));
654 
655  if (!floatbar)
656  return NULL;
657 
658  floatbar->root_window = window;
659  floatbar->flags = flags;
660  floatbar->wfc = wfc;
661  floatbar->locked = (flags & 0x0002) != 0;
662  floatbar->shown = (flags & 0x0006) != 0; /* If it is loked or shown show it */
663  floatbar->hwnd = NULL;
664  floatbar->parent = wfc->hwnd;
665  floatbar->hdcmem = NULL;
666 
667  if (wfc->fullscreen_toggle)
668  {
669  floatbar->buttons[0] =
670  floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT,
671  MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
672  floatbar->buttons[1] =
673  floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT,
674  RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
675  }
676  else
677  {
678  floatbar->buttons[0] = NULL;
679  floatbar->buttons[1] = NULL;
680  }
681 
682  floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT,
683  CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
684  floatbar->buttons[3] =
685  floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT,
686  LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
687 
688  if (!floatbar_window_create(floatbar))
689  goto fail;
690 
691  if (!update_locked_state(floatbar))
692  goto fail;
693 
694  if (!wf_floatbar_toggle_fullscreen(
695  floatbar, freerdp_settings_get_bool(wfc->common.context.settings, FreeRDP_Fullscreen)))
696  goto fail;
697 
698  return floatbar;
699 fail:
700  wf_floatbar_free(floatbar);
701  return NULL;
702 }
703 
704 BOOL wf_floatbar_toggle_fullscreen(wfFloatBar* floatbar, BOOL fullscreen)
705 {
706  BOOL show_fs, show_wn;
707 
708  if (!floatbar)
709  return FALSE;
710 
711  show_fs = (floatbar->flags & 0x0010) != 0;
712  show_wn = (floatbar->flags & 0x0020) != 0;
713 
714  if ((show_fs && fullscreen) || (show_wn && !fullscreen))
715  {
716  ShowWindow(floatbar->hwnd, SW_SHOWNORMAL);
717  Sleep(10);
718 
719  if (floatbar->shown)
720  floatbar_show(floatbar);
721  else
722  floatbar_hide(floatbar);
723  }
724  else
725  {
726  ShowWindow(floatbar->hwnd, SW_HIDE);
727  }
728 
729  return TRUE;
730 }
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.