21#include <X11/extensions/shape.h>
22#include <X11/cursorfont.h>
24#include <winpr/assert.h>
25#include <winpr/cast.h>
27#include "xf_floatbar.h"
29#include "resource/close.xbm"
30#include "resource/lock.xbm"
31#include "resource/unlock.xbm"
32#include "resource/minimize.xbm"
33#include "resource/restore.xbm"
35#include <freerdp/log.h>
36#define TAG CLIENT_TAG("x11")
38#define FLOATBAR_HEIGHT 26
39#define FLOATBAR_DEFAULT_WIDTH 576
40#define FLOATBAR_MIN_WIDTH 200
41#define FLOATBAR_BORDER 24
42#define FLOATBAR_BUTTON_WIDTH 24
43#define FLOATBAR_COLOR_BACKGROUND "RGB:31/6c/a9"
44#define FLOATBAR_COLOR_BORDER "RGB:75/9a/c8"
45#define FLOATBAR_COLOR_FOREGROUND "RGB:FF/FF/FF"
47#define XF_FLOATBAR_MODE_NONE 0
48#define XF_FLOATBAR_MODE_DRAGGING 1
49#define XF_FLOATBAR_MODE_RESIZE_LEFT 2
50#define XF_FLOATBAR_MODE_RESIZE_RIGHT 3
52#define XF_FLOATBAR_BUTTON_CLOSE 1
53#define XF_FLOATBAR_BUTTON_RESTORE 2
54#define XF_FLOATBAR_BUTTON_MINIMIZE 3
55#define XF_FLOATBAR_BUTTON_LOCKED 4
57typedef BOOL (*OnClick)(xfFloatbar*);
77 int last_motion_x_root;
78 int last_motion_y_root;
80 xfFloatbarButton* buttons[4];
92static xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar,
int type);
94static BOOL xf_floatbar_button_onclick_close(xfFloatbar* floatbar)
99 return freerdp_abort_connect_context(&floatbar->xfc->common.context);
102static BOOL xf_floatbar_button_onclick_minimize(xfFloatbar* floatbar)
104 xfContext* xfc =
nullptr;
106 if (!floatbar || !floatbar->xfc)
110 xf_SetWindowMinimized(xfc, xfc->window);
114static BOOL xf_floatbar_button_onclick_restore(xfFloatbar* floatbar)
119 xf_toggle_fullscreen(floatbar->xfc);
123static BOOL xf_floatbar_button_onclick_locked(xfFloatbar* floatbar)
128 floatbar->locked = !((floatbar->locked));
129 return xf_floatbar_hide_and_show(floatbar);
132BOOL xf_floatbar_set_root_y(xfFloatbar* floatbar,
int y)
137 floatbar->last_motion_y_root = y;
141BOOL xf_floatbar_hide_and_show(xfFloatbar* floatbar)
143 xfContext* xfc =
nullptr;
145 if (!floatbar || !floatbar->xfc)
148 if (!floatbar->created)
153 WINPR_ASSERT(xfc->display);
155 if (!floatbar->locked)
157 if ((floatbar->mode == XF_FLOATBAR_MODE_NONE) && (floatbar->last_motion_y_root > 10) &&
158 (floatbar->y > (FLOATBAR_HEIGHT * -1)))
160 floatbar->y = floatbar->y - 1;
161 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, floatbar->x,
164 else if (floatbar->y < 0 && (floatbar->last_motion_y_root < 10))
166 floatbar->y = floatbar->y + 1;
167 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, floatbar->x,
175static BOOL create_floatbar(xfFloatbar* floatbar)
177 xfContext* xfc =
nullptr;
179 XWindowAttributes attr = WINPR_C_ARRAY_INIT;
181 WINPR_ASSERT(floatbar);
182 if (floatbar->created)
187 WINPR_ASSERT(xfc->display);
189 status = XGetWindowAttributes(xfc->display, floatbar->root_window, &attr);
192 WLog_WARN(TAG,
"XGetWindowAttributes failed");
195 floatbar->x = attr.x + attr.width / 2 - FLOATBAR_DEFAULT_WIDTH / 2;
198 if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
199 floatbar->y = -FLOATBAR_HEIGHT + 1;
201 floatbar->handle = LogDynAndXCreateWindow(
202 xfc->log, xfc->display, floatbar->root_window, floatbar->x, 0, FLOATBAR_DEFAULT_WIDTH,
203 FLOATBAR_HEIGHT, 0, CopyFromParent, InputOutput, CopyFromParent, 0,
nullptr);
204 floatbar->width = FLOATBAR_DEFAULT_WIDTH;
205 floatbar->height = FLOATBAR_HEIGHT;
206 floatbar->mode = XF_FLOATBAR_MODE_NONE;
207 floatbar->buttons[0] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_CLOSE);
208 floatbar->buttons[1] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_RESTORE);
209 floatbar->buttons[2] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_MINIMIZE);
210 floatbar->buttons[3] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_LOCKED);
211 XSelectInput(xfc->display, floatbar->handle,
212 ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
213 FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask |
215 floatbar->created = TRUE;
219BOOL xf_floatbar_toggle_fullscreen(xfFloatbar* floatbar,
bool fullscreen)
222 bool visible = False;
223 xfContext* xfc =
nullptr;
225 if (!floatbar || !floatbar->xfc)
229 WINPR_ASSERT(xfc->display);
232 if (floatbar->flags & 0x0001)
235 visible |= ((floatbar->flags & 0x0010) != 0) && fullscreen;
237 visible |= ((floatbar->flags & 0x0020) != 0) && !fullscreen;
242 if (!create_floatbar(floatbar))
245 LogDynAndXMapWindow(xfc->log, xfc->display, floatbar->handle);
246 size = ARRAYSIZE(floatbar->buttons);
248 for (
int i = 0; i < size; i++)
250 xfFloatbarButton* button = floatbar->buttons[i];
251 LogDynAndXMapWindow(xfc->log, xfc->display, button->handle);
255 if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
256 floatbar->y = -FLOATBAR_HEIGHT + 1;
258 xf_floatbar_hide_and_show(floatbar);
260 else if (floatbar->created)
262 XUnmapSubwindows(xfc->display, floatbar->handle);
263 LogDynAndXUnmapWindow(xfc->log, xfc->display, floatbar->handle);
269xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar,
int type)
271 xfFloatbarButton* button =
nullptr;
273 WINPR_ASSERT(floatbar);
274 WINPR_ASSERT(floatbar->xfc);
275 WINPR_ASSERT(floatbar->xfc->display);
276 WINPR_ASSERT(floatbar->handle);
278 button = (xfFloatbarButton*)calloc(1,
sizeof(xfFloatbarButton));
283 case XF_FLOATBAR_BUTTON_CLOSE:
284 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
285 button->onclick = xf_floatbar_button_onclick_close;
288 case XF_FLOATBAR_BUTTON_RESTORE:
289 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
290 button->onclick = xf_floatbar_button_onclick_restore;
293 case XF_FLOATBAR_BUTTON_MINIMIZE:
294 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
295 button->onclick = xf_floatbar_button_onclick_minimize;
298 case XF_FLOATBAR_BUTTON_LOCKED:
299 button->x = FLOATBAR_BORDER;
300 button->onclick = xf_floatbar_button_onclick_locked;
308 button->focus = FALSE;
310 LogDynAndXCreateWindow(floatbar->xfc->log, floatbar->xfc->display, floatbar->handle,
311 button->x, 0, FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH, 0,
312 CopyFromParent, InputOutput, CopyFromParent, 0,
nullptr);
313 XSelectInput(floatbar->xfc->display, button->handle,
314 ExposureMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
315 LeaveWindowMask | EnterWindowMask | StructureNotifyMask);
319xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window,
const char* title, DWORD flags)
322 WINPR_ASSERT(xfc->display);
326 if ((flags & 0x0001) == 0)
336 xfFloatbar* floatbar = (xfFloatbar*)calloc(1,
sizeof(xfFloatbar));
341 floatbar->title = _strdup(title);
343 if (!floatbar->title)
346 floatbar->root_window = window;
347 floatbar->flags = flags;
349 floatbar->locked = (flags & 0x0002) != 0;
350 xf_floatbar_toggle_fullscreen(floatbar, FALSE);
353 char** missingList =
nullptr;
354 int missingCount = 0;
355 char* defString =
nullptr;
356 floatbar->fontSet = XCreateFontSet(floatbar->xfc->display,
"-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
357 &missingList, &missingCount, &defString);
359 if (floatbar->fontSet ==
nullptr)
361 WLog_ERR(TAG,
"Failed to create fontset");
363 XFreeStringList(missingList);
367 WINPR_PRAGMA_DIAG_PUSH
368 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
369 xf_floatbar_free(floatbar);
370 WINPR_PRAGMA_DIAG_POP
374static unsigned long xf_floatbar_get_color(xfFloatbar* floatbar,
char* rgb_value)
378 WINPR_ASSERT(floatbar);
379 WINPR_ASSERT(floatbar->xfc);
381 Display* display = floatbar->xfc->display;
382 WINPR_ASSERT(display);
384 Colormap cmap = DefaultColormap(display, XDefaultScreen(display));
385 XParseColor(display, cmap, rgb_value, &color);
386 XAllocColor(display, cmap, &color);
390static void xf_floatbar_event_expose(xfFloatbar* floatbar)
393 GC shape_gc =
nullptr;
395 XPoint shape[5] = WINPR_C_ARRAY_INIT;
396 XPoint border[5] = WINPR_C_ARRAY_INIT;
398 WINPR_ASSERT(floatbar);
399 WINPR_ASSERT(floatbar->xfc);
401 Display* display = floatbar->xfc->display;
402 WINPR_ASSERT(display);
405 pmap = LogDynAndXCreatePixmap(floatbar->xfc->log, display, floatbar->handle,
406 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->width),
407 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height), 1);
408 gc = LogDynAndXCreateGC(floatbar->xfc->log, display, floatbar->handle, 0, 0);
409 shape_gc = LogDynAndXCreateGC(floatbar->xfc->log, display, pmap, 0, 0);
413 shape[1].x = WINPR_ASSERTING_INT_CAST(
short, floatbar->width);
415 shape[2].x = WINPR_ASSERTING_INT_CAST(
short, shape[1].x - FLOATBAR_BORDER);
416 shape[2].y = FLOATBAR_HEIGHT;
417 shape[3].x = WINPR_ASSERTING_INT_CAST(
short, shape[0].x + FLOATBAR_BORDER);
418 shape[3].y = FLOATBAR_HEIGHT;
419 shape[4].x = shape[0].x;
420 shape[4].y = shape[0].y;
422 border[0].x = shape[0].x;
423 border[0].y = WINPR_ASSERTING_INT_CAST(
short, shape[0].y - 1);
424 border[1].x = WINPR_ASSERTING_INT_CAST(
short, shape[1].x - 1);
425 border[1].y = WINPR_ASSERTING_INT_CAST(
short, shape[1].y - 1);
426 border[2].x = shape[2].x;
427 border[2].y = WINPR_ASSERTING_INT_CAST(
short, shape[2].y - 1);
428 border[3].x = WINPR_ASSERTING_INT_CAST(
short, shape[3].x - 1);
429 border[3].y = WINPR_ASSERTING_INT_CAST(
short, shape[3].y - 1);
430 border[4].x = border[0].x;
431 border[4].y = border[0].y;
433 LogDynAndXSetForeground(floatbar->xfc->log, display, shape_gc, 0);
434 LogDynAndXFillRectangle(floatbar->xfc->log, display, pmap, shape_gc, 0, 0,
435 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->width),
436 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height));
438 LogDynAndXSetForeground(floatbar->xfc->log, display, shape_gc, 1);
439 XFillPolygon(display, pmap, shape_gc, shape, 5, 0, CoordModeOrigin);
440 XShapeCombineMask(display, floatbar->handle, ShapeBounding, 0, 0, pmap, ShapeSet);
442 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
443 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
444 XFillPolygon(display, floatbar->handle, gc, shape, 4, 0, CoordModeOrigin);
446 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
447 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
448 XDrawLines(display, floatbar->handle, gc, border, 5, CoordModeOrigin);
450 const size_t len = strnlen(floatbar->title, MAX_PATH);
451 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
452 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
454 WINPR_ASSERT(len <= INT32_MAX / 2);
455 const int fx = floatbar->width / 2 - (int)len * 2;
456 if (floatbar->fontSet !=
nullptr)
458 XmbDrawString(display, floatbar->handle, floatbar->fontSet, gc, fx, 15, floatbar->title,
463 XDrawString(display, floatbar->handle, gc, fx, 15, floatbar->title, (
int)len);
465 LogDynAndXFreeGC(floatbar->xfc->log, display, gc);
466 LogDynAndXFreeGC(floatbar->xfc->log, display, shape_gc);
469static xfFloatbarButton* xf_floatbar_get_button(xfFloatbar* floatbar, Window window)
471 WINPR_ASSERT(floatbar);
472 const size_t size = ARRAYSIZE(floatbar->buttons);
474 for (
size_t i = 0; i < size; i++)
476 xfFloatbarButton* button = floatbar->buttons[i];
477 if (button->handle == window)
486static void xf_floatbar_button_update_positon(xfFloatbar* floatbar)
488 xfFloatbarButton* button =
nullptr;
489 WINPR_ASSERT(floatbar);
490 xfContext* xfc = floatbar->xfc;
491 const size_t size = ARRAYSIZE(floatbar->buttons);
493 for (
size_t i = 0; i < size; i++)
495 button = floatbar->buttons[i];
497 switch (button->type)
499 case XF_FLOATBAR_BUTTON_CLOSE:
501 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
504 case XF_FLOATBAR_BUTTON_RESTORE:
506 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
509 case XF_FLOATBAR_BUTTON_MINIMIZE:
511 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
519 WINPR_ASSERT(xfc->display);
520 LogDynAndXMoveWindow(xfc->log, xfc->display, button->handle, button->x, button->y);
521 xf_floatbar_event_expose(floatbar);
525static void xf_floatbar_button_event_expose(xfFloatbar* floatbar, Window window)
527 xfFloatbarButton* button = xf_floatbar_get_button(floatbar, window);
528 static unsigned char* bits;
531 xfContext* xfc = floatbar->xfc;
537 WINPR_ASSERT(xfc->display);
538 WINPR_ASSERT(xfc->window);
540 gc = LogDynAndXCreateGC(xfc->log, xfc->display, button->handle, 0, 0);
541 floatbar = xfc->window->floatbar;
542 WINPR_ASSERT(floatbar);
544 switch (button->type)
546 case XF_FLOATBAR_BUTTON_CLOSE:
550 case XF_FLOATBAR_BUTTON_RESTORE:
554 case XF_FLOATBAR_BUTTON_MINIMIZE:
555 bits = minimize_bits;
558 case XF_FLOATBAR_BUTTON_LOCKED:
559 if (floatbar->locked)
570 pattern = XCreateBitmapFromData(xfc->display, button->handle, (
const char*)bits,
571 FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH);
573 if (!(button->focus))
574 LogDynAndXSetForeground(floatbar->xfc->log, xfc->display, gc,
575 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
577 LogDynAndXSetForeground(floatbar->xfc->log, xfc->display, gc,
578 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
580 LogDynAndXSetBackground(xfc->log, xfc->display, gc,
581 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
582 XCopyPlane(xfc->display, pattern, button->handle, gc, 0, 0, FLOATBAR_BUTTON_WIDTH,
583 FLOATBAR_BUTTON_WIDTH, 0, 0, 1);
584 LogDynAndXFreePixmap(xfc->log, xfc->display, pattern);
585 LogDynAndXFreeGC(xfc->log, xfc->display, gc);
588static void xf_floatbar_button_event_buttonpress(xfFloatbar* floatbar,
const XButtonEvent* event)
591 xfFloatbarButton* button = xf_floatbar_get_button(floatbar, event->window);
594 button->clicked = TRUE;
597static void xf_floatbar_button_event_buttonrelease(xfFloatbar* floatbar,
const XButtonEvent* event)
599 xfFloatbarButton* button =
nullptr;
601 WINPR_ASSERT(floatbar);
604 button = xf_floatbar_get_button(floatbar, event->window);
609 button->onclick(floatbar);
610 button->clicked = FALSE;
614static void xf_floatbar_event_buttonpress(xfFloatbar* floatbar,
const XButtonEvent* event)
616 WINPR_ASSERT(floatbar);
619 switch (event->button)
622 if (event->x <= FLOATBAR_BORDER)
623 floatbar->mode = XF_FLOATBAR_MODE_RESIZE_LEFT;
624 else if (event->x >= (floatbar->width - FLOATBAR_BORDER))
625 floatbar->mode = XF_FLOATBAR_MODE_RESIZE_RIGHT;
627 floatbar->mode = XF_FLOATBAR_MODE_DRAGGING;
636static void xf_floatbar_event_buttonrelease(xfFloatbar* floatbar,
const XButtonEvent* event)
638 WINPR_ASSERT(floatbar);
641 switch (event->button)
644 floatbar->mode = XF_FLOATBAR_MODE_NONE;
652static void xf_floatbar_resize(xfFloatbar* floatbar,
const XMotionEvent* event)
658 WINPR_ASSERT(floatbar);
661 xfContext* xfc = floatbar->xfc;
663 WINPR_ASSERT(xfc->display);
666 movement =
event->x_root - floatbar->last_motion_x_root;
669 if (floatbar->mode == XF_FLOATBAR_MODE_RESIZE_LEFT)
671 x = floatbar->x + movement;
672 width = floatbar->width + movement * -1;
677 width = floatbar->width + movement;
681 if (FLOATBAR_MIN_WIDTH < width)
683 LogDynAndXMoveResizeWindow(xfc->log, xfc->display, floatbar->handle, x, 0,
684 WINPR_ASSERTING_INT_CAST(uint32_t, width),
685 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height));
687 floatbar->width = width;
691static void xf_floatbar_dragging(xfFloatbar* floatbar,
const XMotionEvent* event)
696 WINPR_ASSERT(floatbar);
698 xfContext* xfc = floatbar->xfc;
700 WINPR_ASSERT(xfc->window);
701 WINPR_ASSERT(xfc->display);
704 movement =
event->x_root - floatbar->last_motion_x_root;
705 x = floatbar->x + movement;
708 if (x < 0 || (x + floatbar->width) > xfc->window->width)
712 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, x, 0);
714 floatbar->last_motion_x_root = floatbar->last_motion_x_root + movement;
718static void xf_floatbar_event_motionnotify(xfFloatbar* floatbar,
const XMotionEvent* event)
723 WINPR_ASSERT(floatbar);
726 xfContext* xfc = floatbar->xfc;
728 WINPR_ASSERT(xfc->display);
730 mode = floatbar->mode;
731 cursor = XCreateFontCursor(xfc->display, XC_arrow);
733 if ((event->state & Button1Mask) && (mode > XF_FLOATBAR_MODE_DRAGGING))
735 xf_floatbar_resize(floatbar, event);
737 else if ((event->state & Button1Mask) && (mode == XF_FLOATBAR_MODE_DRAGGING))
739 xf_floatbar_dragging(floatbar, event);
743 if (event->x <= FLOATBAR_BORDER || event->x >= floatbar->width - FLOATBAR_BORDER)
744 cursor = XCreateFontCursor(xfc->display, XC_sb_h_double_arrow);
747 XDefineCursor(xfc->display, xfc->window->handle, cursor);
748 XFreeCursor(xfc->display, cursor);
749 floatbar->last_motion_x_root =
event->x_root;
752static void xf_floatbar_button_event_focusin(xfFloatbar* floatbar,
const XAnyEvent* event)
754 xfFloatbarButton* button =
nullptr;
756 WINPR_ASSERT(floatbar);
759 button = xf_floatbar_get_button(floatbar, event->window);
763 button->focus = TRUE;
764 xf_floatbar_button_event_expose(floatbar, event->window);
768static void xf_floatbar_button_event_focusout(xfFloatbar* floatbar,
const XAnyEvent* event)
770 xfFloatbarButton* button =
nullptr;
772 WINPR_ASSERT(floatbar);
775 button = xf_floatbar_get_button(floatbar, event->window);
779 button->focus = FALSE;
780 xf_floatbar_button_event_expose(floatbar, event->window);
784static void xf_floatbar_event_focusout(xfFloatbar* floatbar)
786 WINPR_ASSERT(floatbar);
787 xfContext* xfc = floatbar->xfc;
792 WINPR_ASSERT(xfc->window);
793 WINPR_ASSERT(xfc->pointer);
794 XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
798BOOL xf_floatbar_check_event(xfFloatbar* floatbar,
const XEvent* event)
800 if (!floatbar || !floatbar->xfc || !event)
803 if (!floatbar->created)
806 if (event->xany.window == floatbar->handle)
809 size_t size = ARRAYSIZE(floatbar->buttons);
811 for (
size_t i = 0; i < size; i++)
813 const xfFloatbarButton* button = floatbar->buttons[i];
815 if (event->xany.window == button->handle)
822BOOL xf_floatbar_event_process(xfFloatbar* floatbar,
const XEvent* event)
824 if (!floatbar || !floatbar->xfc || !event)
827 if (!floatbar->created)
833 if (event->xexpose.window == floatbar->handle)
834 xf_floatbar_event_expose(floatbar);
836 xf_floatbar_button_event_expose(floatbar, event->xexpose.window);
841 xf_floatbar_event_motionnotify(floatbar, &event->xmotion);
845 if (event->xany.window == floatbar->handle)
846 xf_floatbar_event_buttonpress(floatbar, &event->xbutton);
848 xf_floatbar_button_event_buttonpress(floatbar, &event->xbutton);
853 if (event->xany.window == floatbar->handle)
854 xf_floatbar_event_buttonrelease(floatbar, &event->xbutton);
856 xf_floatbar_button_event_buttonrelease(floatbar, &event->xbutton);
861 floatbar->entered = TRUE;
864 if (event->xany.window != floatbar->handle)
865 xf_floatbar_button_event_focusin(floatbar, &event->xany);
870 floatbar->entered = FALSE;
873 if (event->xany.window == floatbar->handle)
874 xf_floatbar_event_focusout(floatbar);
876 xf_floatbar_button_event_focusout(floatbar, &event->xany);
880 case ConfigureNotify:
881 if (event->xany.window == floatbar->handle)
882 xf_floatbar_button_update_positon(floatbar);
887 if (event->xany.window == floatbar->handle)
888 xf_floatbar_button_update_positon(floatbar);
896 return floatbar->handle ==
event->xany.window;
899static void xf_floatbar_button_free(xfContext* xfc, xfFloatbarButton* button)
907 WINPR_ASSERT(xfc->display);
908 LogDynAndXUnmapWindow(xfc->log, xfc->display, button->handle);
909 LogDynAndXDestroyWindow(xfc->log, xfc->display, button->handle);
915void xf_floatbar_free(xfFloatbar* floatbar)
918 xfContext* xfc =
nullptr;
923 free(floatbar->title);
927 size = ARRAYSIZE(floatbar->buttons);
929 for (
size_t i = 0; i < size; i++)
931 xf_floatbar_button_free(xfc, floatbar->buttons[i]);
932 floatbar->buttons[i] =
nullptr;
935 if (floatbar->handle)
937 WINPR_ASSERT(xfc->display);
938 LogDynAndXUnmapWindow(xfc->log, xfc->display, floatbar->handle);
939 LogDynAndXDestroyWindow(xfc->log, xfc->display, floatbar->handle);
945BOOL xf_floatbar_is_locked(xfFloatbar* floatbar)
949 return floatbar->mode != XF_FLOATBAR_MODE_NONE;
952BOOL xf_floatbar_is_window(xfFloatbar* floatbar, Window window)
956 if (floatbar->handle == window)
958 return floatbar->entered;
961BOOL xfc_is_floatbar_window(xfContext* xfc, Window window)
963 if (!xfc || !xfc->window)
965 return xf_floatbar_is_window(xfc->window->floatbar, window);