21#include <winpr/windows.h>
24#include "wf_floatbar.h"
26#include "resource/resource.h"
29#pragma comment(lib, "Msimg32.lib")
32#define TAG CLIENT_TAG("windows.floatbar")
36#define TIMER_ANIMAT_SHOW 2
37#define TIMER_ANIMAT_HIDE 3
40#define BUTTON_LOCKPIN 0
41#define BUTTON_MINIMIZE 1
42#define BUTTON_RESTORE 2
47#define BACKGROUND_W 576
48#define BACKGROUND_H 27
49#define BUTTON_OFFSET 5
51#define BUTTON_WIDTH 23
52#define BUTTON_HEIGHT 21
53#define BUTTON_SPACING 1
54#define RESTORE_DRAG_BAR_MULTIPLIER 2
55#define RESIZE_GRIP_WIDTH 8
56#define MIN_LABEL_WIDTH 260
58#define LOCK_X (BACKGROUND_H + BUTTON_OFFSET)
59#define CLOSE_X ((BACKGROUND_W - (BACKGROUND_H + BUTTON_OFFSET)) - BUTTON_WIDTH)
60#define RESTORE_X (CLOSE_X - (BUTTON_WIDTH + BUTTON_SPACING))
61#define MINIMIZE_X (RESTORE_X - (BUTTON_WIDTH + BUTTON_SPACING))
62#define TEXT_X (BACKGROUND_H + ((BUTTON_WIDTH + BUTTON_SPACING) * 3) + 5)
63#define MIN_FLOATBAR_WIDTH ((TEXT_X * 2) + MIN_LABEL_WIDTH)
67#define DRAG_RESIZE_LEFT 2
68#define DRAG_RESIZE_RIGHT 3
81 HBITMAP locked_bmp_act;
83 HBITMAP unlocked_bmp_act;
88 HINSTANCE root_window;
97 Button* buttons[BTN_MAX];
105static BOOL floatbar_kill_timers(wfFloatBar* floatbar)
107 UINT_PTR timers[] = { TIMER_HIDE, TIMER_ANIMAT_HIDE, TIMER_ANIMAT_SHOW };
112 for (
size_t x = 0; x < ARRAYSIZE(timers); x++)
113 KillTimer(floatbar->hwnd, timers[x]);
115 floatbar->animating = 0;
119static BOOL floatbar_animation(wfFloatBar*
const floatbar,
const BOOL show)
121 UINT_PTR timer = show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE;
126 if (floatbar->shown == show)
129 if (floatbar->animating == timer)
132 floatbar->animating = timer;
134 if (SetTimer(floatbar->hwnd, timer, USER_TIMER_MINIMUM,
nullptr) == 0)
136 DWORD err = GetLastError();
137 WLog_ERR(TAG,
"SetTimer failed with %08" PRIx32, err);
144static BOOL floatbar_trigger_hide(wfFloatBar* floatbar)
146 if (!floatbar_kill_timers(floatbar))
149 if (!floatbar->locked && floatbar->shown)
151 if (SetTimer(floatbar->hwnd, TIMER_HIDE, 3000,
nullptr) == 0)
153 DWORD err = GetLastError();
154 WLog_ERR(TAG,
"SetTimer failed with %08" PRIx32, err);
162static BOOL floatbar_hide(wfFloatBar* floatbar)
164 if (!floatbar_kill_timers(floatbar))
167 floatbar->offset = floatbar->height - 2;
169 if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
170 floatbar->height, TRUE))
172 DWORD err = GetLastError();
173 WLog_ERR(TAG,
"MoveWindow failed with %08" PRIx32, err);
177 floatbar->shown = FALSE;
179 if (!floatbar_trigger_hide(floatbar))
185static BOOL floatbar_show(wfFloatBar* floatbar)
187 if (!floatbar_kill_timers(floatbar))
190 floatbar->offset = 0;
192 if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset, floatbar->width,
193 floatbar->height, TRUE))
195 DWORD err = GetLastError();
196 WLog_ERR(TAG,
"MoveWindow failed with %08" PRIx32, err);
200 floatbar->shown = TRUE;
202 if (!floatbar_trigger_hide(floatbar))
208static BOOL button_set_locked(Button* button, BOOL locked)
212 button->bmp = button->locked_bmp;
213 button->bmp_act = button->locked_bmp_act;
217 button->bmp = button->unlocked_bmp;
218 button->bmp_act = button->unlocked_bmp_act;
221 InvalidateRect(button->floatbar->hwnd,
nullptr, FALSE);
222 UpdateWindow(button->floatbar->hwnd);
226static BOOL update_locked_state(wfFloatBar* floatbar)
233 button = floatbar->buttons[3];
235 if (!button_set_locked(button, floatbar->locked))
241static int button_hit(Button*
const button)
243 wfFloatBar*
const floatbar = button->floatbar;
245 switch (button->type)
248 floatbar->locked = !floatbar->locked;
249 update_locked_state(floatbar);
252 case BUTTON_MINIMIZE:
253 ShowWindow(floatbar->parent, SW_MINIMIZE);
257 wf_toggle_fullscreen(floatbar->wfc);
261 SendMessage(floatbar->parent, WM_DESTROY, 0, 0);
271static int button_paint(
const Button*
const button,
const HDC hdc)
273 if (button !=
nullptr)
275 wfFloatBar* floatbar = button->floatbar;
277 SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp);
278 bf.BlendOp = AC_SRC_OVER;
280 bf.SourceConstantAlpha = 255;
281 bf.AlphaFormat = AC_SRC_ALPHA;
282 AlphaBlend(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0,
283 button->w, button->h, bf);
289static Button* floatbar_create_button(wfFloatBar*
const floatbar,
const int type,
const int resid,
290 const int resid_act,
const int x,
const int y,
const int h,
293 Button* button = (Button*)calloc(1,
sizeof(Button));
298 button->floatbar = floatbar;
304 button->active = FALSE;
305 button->bmp = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid), IMAGE_BITMAP, 0,
307 button->bmp_act = (HBITMAP)LoadImage(floatbar->root_window, MAKEINTRESOURCE(resid_act),
308 IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
312static Button* floatbar_create_lock_button(wfFloatBar*
const floatbar,
const int unlock_resid,
313 const int unlock_resid_act,
const int lock_resid,
314 const int lock_resid_act,
const int x,
const int y,
315 const int h,
const int w)
317 Button* button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid,
318 unlock_resid_act, x, y, h, w);
323 button->unlocked_bmp = button->bmp;
324 button->unlocked_bmp_act = button->bmp_act;
325 button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid),
326 IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
327 button->locked_bmp_act =
328 (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP,
329 0, 0, LR_DEFAULTCOLOR);
333static Button* floatbar_get_button(
const wfFloatBar*
const floatbar,
const int x,
const int y)
335 if ((y > BUTTON_Y) && (y < BUTTON_Y + BUTTON_HEIGHT))
337 for (
int i = 0; i < BTN_MAX; i++)
339 if ((floatbar->buttons[i] !=
nullptr) && (x > floatbar->buttons[i]->x) &&
340 (x < floatbar->buttons[i]->x + floatbar->buttons[i]->w))
342 return floatbar->buttons[i];
350static Button* floatbar_get_button_by_type(
const wfFloatBar*
const floatbar,
const int type)
355 for (
int i = 0; i < BTN_MAX; i++)
357 Button* button = floatbar->buttons[i];
359 if (button && (button->type == type))
366static LONG floatbar_parent_width(
const wfFloatBar*
const floatbar)
368 RECT rect = WINPR_C_ARRAY_INIT;
370 if (!floatbar || !floatbar->parent || !GetWindowRect(floatbar->parent, &rect))
371 return GetSystemMetrics(SM_CXSCREEN);
373 return rect.right - rect.left;
376static BOOL floatbar_update_layout(wfFloatBar* floatbar)
381 Button* close = floatbar_get_button_by_type(floatbar, BUTTON_CLOSE);
382 Button* restore = floatbar_get_button_by_type(floatbar, BUTTON_RESTORE);
383 Button* minimize = floatbar_get_button_by_type(floatbar, BUTTON_MINIMIZE);
386 close->x = (floatbar->width - (BACKGROUND_H + BUTTON_OFFSET)) - BUTTON_WIDTH;
388 if (restore && close)
389 restore->x = close->x - (BUTTON_WIDTH + BUTTON_SPACING);
391 if (minimize && restore)
392 minimize->x = restore->x - (BUTTON_WIDTH + BUTTON_SPACING);
394 SetRect(&floatbar->textRect, TEXT_X, 0, floatbar->width - TEXT_X, floatbar->height);
398static BOOL floatbar_update_region(wfFloatBar* floatbar)
400 if (!floatbar || !floatbar->hwnd)
403 HRGN hRgn = CreateRectRgn(0, 0, floatbar->width, floatbar->height);
407 if (!SetWindowRgn(floatbar->hwnd, hRgn, TRUE))
416static BOOL floatbar_resize(wfFloatBar* floatbar, LONG left, LONG width)
421 LONG parentWidth = floatbar_parent_width(floatbar);
423 if (width < MIN_FLOATBAR_WIDTH)
424 width = MIN_FLOATBAR_WIDTH;
426 if (width > parentWidth)
435 if (left + width > parentWidth)
436 width = parentWidth - left;
438 if (width < MIN_FLOATBAR_WIDTH)
440 width = MIN_FLOATBAR_WIDTH;
441 left = parentWidth - width;
447 floatbar->rect.left = left;
448 floatbar->width = width;
450 if (!floatbar_update_layout(floatbar))
453 if (!MoveWindow(floatbar->hwnd, floatbar->rect.left,
454 -WINPR_ASSERTING_INT_CAST(
int, floatbar->offset), floatbar->width,
455 floatbar->height, TRUE))
457 DWORD err = GetLastError();
458 WLog_ERR(TAG,
"MoveWindow failed with %08" PRIx32, err);
462 if (!floatbar_update_region(floatbar))
465 InvalidateRect(floatbar->hwnd,
nullptr, FALSE);
469static int floatbar_get_resize_mode(
const wfFloatBar*
const floatbar,
const int x,
const int y)
471 if (!floatbar || (y < 0) || (y > floatbar->height))
474 if (floatbar_get_button(floatbar, x, y))
477 if (x <= RESIZE_GRIP_WIDTH)
478 return DRAG_RESIZE_LEFT;
480 if (x >= floatbar->width - RESIZE_GRIP_WIDTH)
481 return DRAG_RESIZE_RIGHT;
486static BOOL floatbar_update_hover(wfFloatBar* floatbar,
const Button* activeButton)
488 BOOL changed = FALSE;
493 for (
int i = 0; i < BTN_MAX; i++)
495 Button* button = floatbar->buttons[i];
496 const int active = (button == activeButton) ? TRUE : FALSE;
498 if (button && (button->active != active))
500 button->active = active;
507 InvalidateRect(floatbar->hwnd,
nullptr, FALSE);
508 UpdateWindow(floatbar->hwnd);
514static BOOL floatbar_paint(wfFloatBar*
const floatbar,
const HDC hdc)
520 GRADIENT_RECT gradientRect = { 0, 1 };
521 COLORREF rgbTop = RGB(117, 154, 198);
522 COLORREF rgbBottom = RGB(6, 55, 120);
524 int bottom = BACKGROUND_H - 1;
526 const int angleOffset = BACKGROUND_H - 1;
528 int right = floatbar->width - 1;
532 pt[1].x = floatbar->width;
534 pt[2].x = floatbar->width - BACKGROUND_H;
535 pt[2].y = BACKGROUND_H;
536 pt[3].x = BACKGROUND_H;
537 pt[3].y = BACKGROUND_H;
538 HRGN clipRgn = CreatePolygonRgn(pt, 4, ALTERNATE);
542 SelectClipRgn(hdc, clipRgn);
544 TRIVERTEX triVertext[2];
545 triVertext[0].x = left;
546 triVertext[0].y = top;
547 triVertext[0].Red = GetRValue(rgbTop) << 8;
548 triVertext[0].Green = GetGValue(rgbTop) << 8;
549 triVertext[0].Blue = GetBValue(rgbTop) << 8;
550 triVertext[0].Alpha = 0x0000;
551 triVertext[1].x = right;
552 triVertext[1].y = bottom;
553 triVertext[1].Red = GetRValue(rgbBottom) << 8;
554 triVertext[1].Green = GetGValue(rgbBottom) << 8;
555 triVertext[1].Blue = GetBValue(rgbBottom) << 8;
556 triVertext[1].Alpha = 0x0000;
558 GradientFill(hdc, triVertext, 2, &gradientRect, 1, GRADIENT_FILL_RECT_V);
560 HPEN hpen = CreatePen(PS_SOLID, 1, RGB(71, 71, 71));
562 MoveToEx(hdc, left, top,
nullptr);
563 LineTo(hdc, left + angleOffset, bottom);
564 LineTo(hdc, right - angleOffset, bottom);
565 LineTo(hdc, right + 1, top - 1);
567 hpen = CreatePen(PS_SOLID, 1, RGB(107, 141, 184));
568 SelectObject(hdc, hpen);
572 MoveToEx(hdc, left, top,
nullptr);
573 LineTo(hdc, left + (angleOffset - 1), bottom);
574 LineTo(hdc, right - (angleOffset - 1), bottom);
575 LineTo(hdc, right + 1, top - 1);
577 SelectObject(hdc, orig);
579 const size_t wlen = wcslen(floatbar->wfc->window_title);
580 DrawText(hdc, floatbar->wfc->window_title, WINPR_ASSERTING_INT_CAST(
int, wlen),
582 DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
586 for (
int i = 0; i < BTN_MAX; i++)
587 button_paint(floatbar->buttons[i], hdc);
589 SelectClipRgn(hdc,
nullptr);
590 DeleteObject(clipRgn);
594static LRESULT CALLBACK floatbar_proc(
const HWND hWnd,
const UINT Msg,
const WPARAM wParam,
597 static int drag_mode = DRAG_NONE;
598 static int lbtn_dwn = FALSE;
599 static int btn_dwn_x = 0;
600 static int btn_dwn_y = 0;
601 static int btn_dwn_screen_x = 0;
602 static LONG drag_start_left = 0;
603 static LONG drag_start_width = 0;
604 static wfFloatBar* floatbar =
nullptr;
605 static TRACKMOUSEEVENT tme = WINPR_C_ARRAY_INIT;
606 PAINTSTRUCT ps = WINPR_C_ARRAY_INIT;
607 POINT pt = WINPR_C_ARRAY_INIT;
608 Button* button =
nullptr;
612 NONCLIENTMETRICS ncm = WINPR_C_ARRAY_INIT;
617 floatbar = ((wfFloatBar*)((CREATESTRUCT*)lParam)->lpCreateParams);
618 floatbar->hwnd = hWnd;
619 GetWindowRect(floatbar->hwnd, &floatbar->rect);
620 floatbar->width = floatbar->rect.right - floatbar->rect.left;
621 floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
622 floatbar_update_layout(floatbar);
624 floatbar->hdcmem = CreateCompatibleDC(hdc);
625 ReleaseDC(hWnd, hdc);
626 tme.cbSize =
sizeof(TRACKMOUSEEVENT);
627 tme.dwFlags = TME_LEAVE;
628 tme.hwndTrack = hWnd;
629 tme.dwHoverTime = HOVER_DEFAULT;
631 SetBkMode(hdc, TRANSPARENT);
632 SetTextColor(hdc, RGB(255, 255, 255));
633 ncm.cbSize =
sizeof(NONCLIENTMETRICS);
634 SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(NONCLIENTMETRICS), &ncm, 0);
635 SelectObject(hdc, CreateFontIndirect(&ncm.lfCaptionFont));
636 floatbar_trigger_hide(floatbar);
640 hdc = BeginPaint(hWnd, &ps);
641 floatbar_paint(floatbar, hdc);
649 pos_x = LOWORD(lParam);
650 pos_y = HIWORD(lParam);
651 button = floatbar_get_button(floatbar, pos_x, pos_y);
657 ClientToScreen(hWnd, &pt);
659 floatbar_kill_timers(floatbar);
660 drag_mode = floatbar_get_resize_mode(floatbar, pos_x, pos_y);
661 if (drag_mode == DRAG_NONE)
662 drag_mode = DRAG_MOVE;
664 SetCursor(LoadCursor(
nullptr, IDC_SIZEWE));
667 btn_dwn_screen_x = pt.x;
668 drag_start_left = floatbar->rect.left;
669 drag_start_width = floatbar->width;
677 pos_x = LOWORD(lParam);
678 pos_y = HIWORD(lParam);
679 const BOOL was_dragging = drag_mode != DRAG_NONE;
680 drag_mode = DRAG_NONE;
683 floatbar_trigger_hide(floatbar);
687 button = floatbar_get_button(floatbar, pos_x, pos_y);
697 case WM_LBUTTONDBLCLK:
698 pos_x = LOWORD(lParam);
699 pos_y = HIWORD(lParam);
701 if (!floatbar_get_button(floatbar, pos_x, pos_y) && floatbar->wfc->fullscreen_toggle &&
702 floatbar->wfc->fullscreen)
703 wf_toggle_fullscreen(floatbar->wfc);
707 pos_x = LOWORD(lParam);
708 pos_y = HIWORD(lParam);
710 if (!floatbar->locked)
711 floatbar_animation(floatbar, TRUE);
713 if (drag_mode != DRAG_NONE)
718 ClientToScreen(hWnd, &pt);
720 if (drag_mode == DRAG_MOVE)
722 const int dy = pos_y - btn_dwn_y;
723 const int dy_threshold = floatbar->height * RESTORE_DRAG_BAR_MULTIPLIER;
725 if (dy > dy_threshold && floatbar->wfc->fullscreen_toggle &&
726 floatbar->wfc->fullscreen)
728 drag_mode = DRAG_NONE;
730 wf_toggle_fullscreen(floatbar->wfc);
734 const int xScreen = floatbar_parent_width(floatbar);
735 floatbar->rect.left = floatbar->rect.left + pos_x - btn_dwn_x;
737 if (floatbar->rect.left < 0)
738 floatbar->rect.left = 0;
739 else if (floatbar->rect.left > xScreen - floatbar->width)
740 floatbar->rect.left = xScreen - floatbar->width;
742 MoveWindow(hWnd, floatbar->rect.left, 0, floatbar->width, floatbar->height,
747 const int dx = pt.x - btn_dwn_screen_x;
748 LONG left = drag_start_left;
749 LONG width = drag_start_width;
751 if (drag_mode == DRAG_RESIZE_LEFT)
753 left = drag_start_left + dx;
754 width = drag_start_width - dx;
756 if (width < MIN_FLOATBAR_WIDTH)
758 width = MIN_FLOATBAR_WIDTH;
759 left = drag_start_left + drag_start_width - width;
762 else if (drag_mode == DRAG_RESIZE_RIGHT)
764 width = drag_start_width + dx;
767 floatbar_resize(floatbar, left, width);
773 button = floatbar_get_button(floatbar, pos_x, pos_y);
774 floatbar_update_hover(floatbar, button);
777 TrackMouseEvent(&tme);
780 case WM_CAPTURECHANGED:
781 if (drag_mode != DRAG_NONE)
782 floatbar_trigger_hide(floatbar);
784 drag_mode = DRAG_NONE;
788 if (LOWORD(lParam) == HTCLIENT)
791 ScreenToClient(hWnd, &pt);
793 if ((drag_mode == DRAG_RESIZE_LEFT) || (drag_mode == DRAG_RESIZE_RIGHT) ||
794 (floatbar_get_resize_mode(floatbar, pt.x, pt.y) != DRAG_NONE))
795 SetCursor(LoadCursor(
nullptr, IDC_SIZEWE));
797 SetCursor(LoadCursor(
nullptr, IDC_ARROW));
802 return DefWindowProc(hWnd, Msg, wParam, lParam);
806 floatbar_update_hover(floatbar,
nullptr);
807 floatbar_trigger_hide(floatbar);
815 floatbar_animation(floatbar, FALSE);
818 case TIMER_ANIMAT_SHOW:
821 MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
822 floatbar->width, floatbar->height, TRUE);
824 if (floatbar->offset <= 0)
825 floatbar_show(floatbar);
830 case TIMER_ANIMAT_HIDE:
833 MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->offset,
834 floatbar->width, floatbar->height, TRUE);
836 if (floatbar->offset >= floatbar->height - 2)
837 floatbar_hide(floatbar);
849 DeleteDC(floatbar->hdcmem);
854 return DefWindowProc(hWnd, Msg, wParam, lParam);
860static BOOL floatbar_window_create(wfFloatBar* floatbar)
870 if (!GetWindowRect(floatbar->parent, &rect))
873 x = (rect.right - rect.left - BACKGROUND_W) / 2;
874 wnd_cls.cbSize =
sizeof(WNDCLASSEX);
875 wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
876 wnd_cls.lpfnWndProc = floatbar_proc;
877 wnd_cls.cbClsExtra = 0;
878 wnd_cls.cbWndExtra = 0;
879 wnd_cls.hIcon = LoadIcon(
nullptr, IDI_APPLICATION);
880 wnd_cls.hCursor = LoadCursor(floatbar->root_window, IDC_ARROW);
881 wnd_cls.hbrBackground =
nullptr;
882 wnd_cls.lpszMenuName =
nullptr;
883 wnd_cls.lpszClassName = L
"floatbar";
884 wnd_cls.hInstance = floatbar->root_window;
885 wnd_cls.hIconSm = LoadIcon(
nullptr, IDI_APPLICATION);
886 RegisterClassEx(&wnd_cls);
888 CreateWindowEx(WS_EX_TOPMOST, L
"floatbar", L
"floatbar", WS_CHILD, x, 0, BACKGROUND_W,
889 BACKGROUND_H, floatbar->parent,
nullptr, floatbar->root_window, floatbar);
891 if (barWnd ==
nullptr)
894 return floatbar_update_region(floatbar);
897void wf_floatbar_free(wfFloatBar* floatbar)
905wfFloatBar* wf_floatbar_new(wfContext* wfc, HINSTANCE window, DWORD flags)
907 wfFloatBar* floatbar;
910 if ((flags & 0x0001) == 0)
917 floatbar = (wfFloatBar*)calloc(1,
sizeof(wfFloatBar));
922 floatbar->root_window = window;
923 floatbar->flags = flags;
925 floatbar->locked = (flags & 0x0002) != 0;
926 floatbar->shown = (flags & 0x0006) != 0;
927 floatbar->hwnd =
nullptr;
928 floatbar->parent = wfc->hwnd;
929 floatbar->hdcmem =
nullptr;
931 if (wfc->fullscreen_toggle)
933 floatbar->buttons[0] =
934 floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT,
935 MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
936 floatbar->buttons[1] =
937 floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT,
938 RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
942 floatbar->buttons[0] =
nullptr;
943 floatbar->buttons[1] =
nullptr;
946 floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT,
947 CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
948 floatbar->buttons[3] =
949 floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT,
950 LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
952 if (!floatbar_window_create(floatbar))
955 if (!update_locked_state(floatbar))
958 if (!wf_floatbar_toggle_fullscreen(
964 wf_floatbar_free(floatbar);
968BOOL wf_floatbar_toggle_fullscreen(wfFloatBar* floatbar, BOOL fullscreen)
970 BOOL show_fs, show_wn;
975 show_fs = (floatbar->flags & 0x0010) != 0;
976 show_wn = (floatbar->flags & 0x0020) != 0;
978 if ((show_fs && fullscreen) || (show_wn && !fullscreen))
980 ShowWindow(floatbar->hwnd, SW_SHOWNORMAL);
984 floatbar_show(floatbar);
986 floatbar_hide(floatbar);
990 ShowWindow(floatbar->hwnd, SW_HIDE);
996BOOL wf_floatbar_reset_position(wfFloatBar* floatbar)
998 RECT rect = WINPR_C_ARRAY_INIT;
1000 if (!floatbar || !floatbar->parent || !floatbar->hwnd)
1003 const int y = -WINPR_ASSERTING_INT_CAST(
int, floatbar->offset);
1005 if (!GetWindowRect(floatbar->parent, &rect))
1008 floatbar->rect.left = ((rect.right - rect.left) - floatbar->width) / 2;
1009 if (floatbar->rect.left < 0)
1010 floatbar->rect.left = 0;
1012 if (!MoveWindow(floatbar->hwnd, floatbar->rect.left, y, floatbar->width, floatbar->height,
1015 DWORD err = GetLastError();
1016 WLog_ERR(TAG,
"MoveWindow failed with %08" PRIx32, err);
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.