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];
91static xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar,
int type);
93static BOOL xf_floatbar_button_onclick_close(xfFloatbar* floatbar)
98 return freerdp_abort_connect_context(&floatbar->xfc->common.context);
101static BOOL xf_floatbar_button_onclick_minimize(xfFloatbar* floatbar)
103 xfContext* xfc = NULL;
105 if (!floatbar || !floatbar->xfc)
109 xf_SetWindowMinimized(xfc, xfc->window);
113static BOOL xf_floatbar_button_onclick_restore(xfFloatbar* floatbar)
118 xf_toggle_fullscreen(floatbar->xfc);
122static BOOL xf_floatbar_button_onclick_locked(xfFloatbar* floatbar)
127 floatbar->locked = (floatbar->locked) ? FALSE : TRUE;
128 return xf_floatbar_hide_and_show(floatbar);
131BOOL xf_floatbar_set_root_y(xfFloatbar* floatbar,
int y)
136 floatbar->last_motion_y_root = y;
140BOOL xf_floatbar_hide_and_show(xfFloatbar* floatbar)
142 xfContext* xfc = NULL;
144 if (!floatbar || !floatbar->xfc)
147 if (!floatbar->created)
152 WINPR_ASSERT(xfc->display);
154 if (!floatbar->locked)
156 if ((floatbar->mode == XF_FLOATBAR_MODE_NONE) && (floatbar->last_motion_y_root > 10) &&
157 (floatbar->y > (FLOATBAR_HEIGHT * -1)))
159 floatbar->y = floatbar->y - 1;
160 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, floatbar->x,
163 else if (floatbar->y < 0 && (floatbar->last_motion_y_root < 10))
165 floatbar->y = floatbar->y + 1;
166 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, floatbar->x,
174static BOOL create_floatbar(xfFloatbar* floatbar)
176 xfContext* xfc = NULL;
178 XWindowAttributes attr = { 0 };
180 WINPR_ASSERT(floatbar);
181 if (floatbar->created)
186 WINPR_ASSERT(xfc->display);
188 status = XGetWindowAttributes(xfc->display, floatbar->root_window, &attr);
191 WLog_WARN(TAG,
"XGetWindowAttributes failed");
194 floatbar->x = attr.x + attr.width / 2 - FLOATBAR_DEFAULT_WIDTH / 2;
197 if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
198 floatbar->y = -FLOATBAR_HEIGHT + 1;
200 floatbar->handle = LogDynAndXCreateWindow(
201 xfc->log, xfc->display, floatbar->root_window, floatbar->x, 0, FLOATBAR_DEFAULT_WIDTH,
202 FLOATBAR_HEIGHT, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
203 floatbar->width = FLOATBAR_DEFAULT_WIDTH;
204 floatbar->height = FLOATBAR_HEIGHT;
205 floatbar->mode = XF_FLOATBAR_MODE_NONE;
206 floatbar->buttons[0] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_CLOSE);
207 floatbar->buttons[1] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_RESTORE);
208 floatbar->buttons[2] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_MINIMIZE);
209 floatbar->buttons[3] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_LOCKED);
210 XSelectInput(xfc->display, floatbar->handle,
211 ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
212 FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask |
214 floatbar->created = TRUE;
218BOOL xf_floatbar_toggle_fullscreen(xfFloatbar* floatbar,
bool fullscreen)
221 bool visible = False;
222 xfContext* xfc = NULL;
224 if (!floatbar || !floatbar->xfc)
228 WINPR_ASSERT(xfc->display);
231 if (floatbar->flags & 0x0001)
234 visible |= ((floatbar->flags & 0x0010) != 0) && fullscreen;
236 visible |= ((floatbar->flags & 0x0020) != 0) && !fullscreen;
241 if (!create_floatbar(floatbar))
244 LogDynAndXMapWindow(xfc->log, xfc->display, floatbar->handle);
245 size = ARRAYSIZE(floatbar->buttons);
247 for (
int i = 0; i < size; i++)
249 xfFloatbarButton* button = floatbar->buttons[i];
250 LogDynAndXMapWindow(xfc->log, xfc->display, button->handle);
254 if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
255 floatbar->y = -FLOATBAR_HEIGHT + 1;
257 xf_floatbar_hide_and_show(floatbar);
259 else if (floatbar->created)
261 XUnmapSubwindows(xfc->display, floatbar->handle);
262 LogDynAndXUnmapWindow(xfc->log, xfc->display, floatbar->handle);
268xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar,
int type)
270 xfFloatbarButton* button = NULL;
272 WINPR_ASSERT(floatbar);
273 WINPR_ASSERT(floatbar->xfc);
274 WINPR_ASSERT(floatbar->xfc->display);
275 WINPR_ASSERT(floatbar->handle);
277 button = (xfFloatbarButton*)calloc(1,
sizeof(xfFloatbarButton));
282 case XF_FLOATBAR_BUTTON_CLOSE:
283 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
284 button->onclick = xf_floatbar_button_onclick_close;
287 case XF_FLOATBAR_BUTTON_RESTORE:
288 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
289 button->onclick = xf_floatbar_button_onclick_restore;
292 case XF_FLOATBAR_BUTTON_MINIMIZE:
293 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
294 button->onclick = xf_floatbar_button_onclick_minimize;
297 case XF_FLOATBAR_BUTTON_LOCKED:
298 button->x = FLOATBAR_BORDER;
299 button->onclick = xf_floatbar_button_onclick_locked;
307 button->focus = FALSE;
309 LogDynAndXCreateWindow(floatbar->xfc->log, floatbar->xfc->display, floatbar->handle,
310 button->x, 0, FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH, 0,
311 CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
312 XSelectInput(floatbar->xfc->display, button->handle,
313 ExposureMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
314 LeaveWindowMask | EnterWindowMask | StructureNotifyMask);
318xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window,
const char* name, DWORD flags)
321 WINPR_ASSERT(xfc->display);
325 if ((flags & 0x0001) == 0)
335 xfFloatbar* floatbar = (xfFloatbar*)calloc(1,
sizeof(xfFloatbar));
340 floatbar->title = _strdup(name);
342 if (!floatbar->title)
345 floatbar->root_window = window;
346 floatbar->flags = flags;
348 floatbar->locked = (flags & 0x0002) != 0 ? TRUE : FALSE;
349 xf_floatbar_toggle_fullscreen(floatbar, FALSE);
350 char** missingList = NULL;
351 int missingCount = 0;
352 char* defString = NULL;
353 floatbar->fontSet = XCreateFontSet(floatbar->xfc->display,
"-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
354 &missingList, &missingCount, &defString);
355 if (floatbar->fontSet == NULL)
357 WLog_ERR(TAG,
"Failed to create fontset");
359 XFreeStringList(missingList);
362 WINPR_PRAGMA_DIAG_PUSH
363 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
364 xf_floatbar_free(floatbar);
365 WINPR_PRAGMA_DIAG_POP
369static unsigned long xf_floatbar_get_color(xfFloatbar* floatbar,
char* rgb_value)
373 WINPR_ASSERT(floatbar);
374 WINPR_ASSERT(floatbar->xfc);
376 Display* display = floatbar->xfc->display;
377 WINPR_ASSERT(display);
379 Colormap cmap = DefaultColormap(display, XDefaultScreen(display));
380 XParseColor(display, cmap, rgb_value, &color);
381 XAllocColor(display, cmap, &color);
385static void xf_floatbar_event_expose(xfFloatbar* floatbar)
390 XPoint shape[5] = { 0 };
391 XPoint border[5] = { 0 };
393 WINPR_ASSERT(floatbar);
394 WINPR_ASSERT(floatbar->xfc);
396 Display* display = floatbar->xfc->display;
397 WINPR_ASSERT(display);
400 pmap = LogDynAndXCreatePixmap(floatbar->xfc->log, display, floatbar->handle,
401 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->width),
402 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height), 1);
403 gc = LogDynAndXCreateGC(floatbar->xfc->log, display, floatbar->handle, 0, 0);
404 shape_gc = LogDynAndXCreateGC(floatbar->xfc->log, display, pmap, 0, 0);
408 shape[1].x = WINPR_ASSERTING_INT_CAST(
short, floatbar->width);
410 shape[2].x = WINPR_ASSERTING_INT_CAST(
short, shape[1].x - FLOATBAR_BORDER);
411 shape[2].y = FLOATBAR_HEIGHT;
412 shape[3].x = WINPR_ASSERTING_INT_CAST(
short, shape[0].x + FLOATBAR_BORDER);
413 shape[3].y = FLOATBAR_HEIGHT;
414 shape[4].x = shape[0].x;
415 shape[4].y = shape[0].y;
417 border[0].x = shape[0].x;
418 border[0].y = WINPR_ASSERTING_INT_CAST(
short, shape[0].y - 1);
419 border[1].x = WINPR_ASSERTING_INT_CAST(
short, shape[1].x - 1);
420 border[1].y = WINPR_ASSERTING_INT_CAST(
short, shape[1].y - 1);
421 border[2].x = shape[2].x;
422 border[2].y = WINPR_ASSERTING_INT_CAST(
short, shape[2].y - 1);
423 border[3].x = WINPR_ASSERTING_INT_CAST(
short, shape[3].x - 1);
424 border[3].y = WINPR_ASSERTING_INT_CAST(
short, shape[3].y - 1);
425 border[4].x = border[0].x;
426 border[4].y = border[0].y;
428 LogDynAndXSetForeground(floatbar->xfc->log, display, shape_gc, 0);
429 LogDynAndXFillRectangle(floatbar->xfc->log, display, pmap, shape_gc, 0, 0,
430 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->width),
431 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height));
433 LogDynAndXSetForeground(floatbar->xfc->log, display, shape_gc, 1);
434 XFillPolygon(display, pmap, shape_gc, shape, 5, 0, CoordModeOrigin);
435 XShapeCombineMask(display, floatbar->handle, ShapeBounding, 0, 0, pmap, ShapeSet);
437 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
438 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
439 XFillPolygon(display, floatbar->handle, gc, shape, 4, 0, CoordModeOrigin);
441 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
442 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
443 XDrawLines(display, floatbar->handle, gc, border, 5, CoordModeOrigin);
445 const size_t len = strnlen(floatbar->title, MAX_PATH);
446 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
447 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
449 WINPR_ASSERT(len <= INT32_MAX / 2);
450 const int fx = floatbar->width / 2 - (int)len * 2;
451 if (floatbar->fontSet != NULL)
453 XmbDrawString(display, floatbar->handle, floatbar->fontSet, gc, fx, 15, floatbar->title,
458 XDrawString(display, floatbar->handle, gc, fx, 15, floatbar->title, (
int)len);
460 LogDynAndXFreeGC(floatbar->xfc->log, display, gc);
461 LogDynAndXFreeGC(floatbar->xfc->log, display, shape_gc);
464static xfFloatbarButton* xf_floatbar_get_button(xfFloatbar* floatbar, Window window)
466 WINPR_ASSERT(floatbar);
467 const size_t size = ARRAYSIZE(floatbar->buttons);
469 for (
size_t i = 0; i < size; i++)
471 xfFloatbarButton* button = floatbar->buttons[i];
472 if (button->handle == window)
481static void xf_floatbar_button_update_positon(xfFloatbar* floatbar)
483 xfFloatbarButton* button = NULL;
484 WINPR_ASSERT(floatbar);
485 xfContext* xfc = floatbar->xfc;
486 const size_t size = ARRAYSIZE(floatbar->buttons);
488 for (
size_t i = 0; i < size; i++)
490 button = floatbar->buttons[i];
492 switch (button->type)
494 case XF_FLOATBAR_BUTTON_CLOSE:
496 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
499 case XF_FLOATBAR_BUTTON_RESTORE:
501 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
504 case XF_FLOATBAR_BUTTON_MINIMIZE:
506 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
514 WINPR_ASSERT(xfc->display);
515 LogDynAndXMoveWindow(xfc->log, xfc->display, button->handle, button->x, button->y);
516 xf_floatbar_event_expose(floatbar);
520static void xf_floatbar_button_event_expose(xfFloatbar* floatbar, Window window)
522 xfFloatbarButton* button = xf_floatbar_get_button(floatbar, window);
523 static unsigned char* bits;
526 xfContext* xfc = floatbar->xfc;
532 WINPR_ASSERT(xfc->display);
533 WINPR_ASSERT(xfc->window);
535 gc = LogDynAndXCreateGC(xfc->log, xfc->display, button->handle, 0, 0);
536 floatbar = xfc->window->floatbar;
537 WINPR_ASSERT(floatbar);
539 switch (button->type)
541 case XF_FLOATBAR_BUTTON_CLOSE:
545 case XF_FLOATBAR_BUTTON_RESTORE:
549 case XF_FLOATBAR_BUTTON_MINIMIZE:
550 bits = minimize_bits;
553 case XF_FLOATBAR_BUTTON_LOCKED:
554 if (floatbar->locked)
565 pattern = XCreateBitmapFromData(xfc->display, button->handle, (
const char*)bits,
566 FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH);
568 if (!(button->focus))
569 LogDynAndXSetForeground(floatbar->xfc->log, xfc->display, gc,
570 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
572 LogDynAndXSetForeground(floatbar->xfc->log, xfc->display, gc,
573 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
575 LogDynAndXSetBackground(xfc->log, xfc->display, gc,
576 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
577 XCopyPlane(xfc->display, pattern, button->handle, gc, 0, 0, FLOATBAR_BUTTON_WIDTH,
578 FLOATBAR_BUTTON_WIDTH, 0, 0, 1);
579 LogDynAndXFreePixmap(xfc->log, xfc->display, pattern);
580 LogDynAndXFreeGC(xfc->log, xfc->display, gc);
583static void xf_floatbar_button_event_buttonpress(xfFloatbar* floatbar,
const XButtonEvent* event)
586 xfFloatbarButton* button = xf_floatbar_get_button(floatbar, event->window);
589 button->clicked = TRUE;
592static void xf_floatbar_button_event_buttonrelease(xfFloatbar* floatbar,
const XButtonEvent* event)
594 xfFloatbarButton* button = NULL;
596 WINPR_ASSERT(floatbar);
599 button = xf_floatbar_get_button(floatbar, event->window);
604 button->onclick(floatbar);
605 button->clicked = FALSE;
609static void xf_floatbar_event_buttonpress(xfFloatbar* floatbar,
const XButtonEvent* event)
611 WINPR_ASSERT(floatbar);
614 switch (event->button)
617 if (event->x <= FLOATBAR_BORDER)
618 floatbar->mode = XF_FLOATBAR_MODE_RESIZE_LEFT;
619 else if (event->x >= (floatbar->width - FLOATBAR_BORDER))
620 floatbar->mode = XF_FLOATBAR_MODE_RESIZE_RIGHT;
622 floatbar->mode = XF_FLOATBAR_MODE_DRAGGING;
631static void xf_floatbar_event_buttonrelease(xfFloatbar* floatbar,
const XButtonEvent* event)
633 WINPR_ASSERT(floatbar);
636 switch (event->button)
639 floatbar->mode = XF_FLOATBAR_MODE_NONE;
647static void xf_floatbar_resize(xfFloatbar* floatbar,
const XMotionEvent* event)
653 WINPR_ASSERT(floatbar);
656 xfContext* xfc = floatbar->xfc;
658 WINPR_ASSERT(xfc->display);
661 movement =
event->x_root - floatbar->last_motion_x_root;
664 if (floatbar->mode == XF_FLOATBAR_MODE_RESIZE_LEFT)
666 x = floatbar->x + movement;
667 width = floatbar->width + movement * -1;
672 width = floatbar->width + movement;
676 if (FLOATBAR_MIN_WIDTH < width)
678 LogDynAndXMoveResizeWindow(xfc->log, xfc->display, floatbar->handle, x, 0,
679 WINPR_ASSERTING_INT_CAST(uint32_t, width),
680 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height));
682 floatbar->width = width;
686static void xf_floatbar_dragging(xfFloatbar* floatbar,
const XMotionEvent* event)
691 WINPR_ASSERT(floatbar);
693 xfContext* xfc = floatbar->xfc;
695 WINPR_ASSERT(xfc->window);
696 WINPR_ASSERT(xfc->display);
699 movement =
event->x_root - floatbar->last_motion_x_root;
700 x = floatbar->x + movement;
703 if (x < 0 || (x + floatbar->width) > xfc->window->width)
707 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, x, 0);
709 floatbar->last_motion_x_root = floatbar->last_motion_x_root + movement;
713static void xf_floatbar_event_motionnotify(xfFloatbar* floatbar,
const XMotionEvent* event)
718 WINPR_ASSERT(floatbar);
721 xfContext* xfc = floatbar->xfc;
723 WINPR_ASSERT(xfc->display);
725 mode = floatbar->mode;
726 cursor = XCreateFontCursor(xfc->display, XC_arrow);
728 if ((event->state & Button1Mask) && (mode > XF_FLOATBAR_MODE_DRAGGING))
730 xf_floatbar_resize(floatbar, event);
732 else if ((event->state & Button1Mask) && (mode == XF_FLOATBAR_MODE_DRAGGING))
734 xf_floatbar_dragging(floatbar, event);
738 if (event->x <= FLOATBAR_BORDER || event->x >= floatbar->width - FLOATBAR_BORDER)
739 cursor = XCreateFontCursor(xfc->display, XC_sb_h_double_arrow);
742 XDefineCursor(xfc->display, xfc->window->handle, cursor);
743 XFreeCursor(xfc->display, cursor);
744 floatbar->last_motion_x_root =
event->x_root;
747static void xf_floatbar_button_event_focusin(xfFloatbar* floatbar,
const XAnyEvent* event)
749 xfFloatbarButton* button = NULL;
751 WINPR_ASSERT(floatbar);
754 button = xf_floatbar_get_button(floatbar, event->window);
758 button->focus = TRUE;
759 xf_floatbar_button_event_expose(floatbar, event->window);
763static void xf_floatbar_button_event_focusout(xfFloatbar* floatbar,
const XAnyEvent* event)
765 xfFloatbarButton* button = NULL;
767 WINPR_ASSERT(floatbar);
770 button = xf_floatbar_get_button(floatbar, event->window);
774 button->focus = FALSE;
775 xf_floatbar_button_event_expose(floatbar, event->window);
779static void xf_floatbar_event_focusout(xfFloatbar* floatbar)
781 WINPR_ASSERT(floatbar);
782 xfContext* xfc = floatbar->xfc;
787 WINPR_ASSERT(xfc->window);
788 WINPR_ASSERT(xfc->pointer);
789 XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
793BOOL xf_floatbar_check_event(xfFloatbar* floatbar,
const XEvent* event)
795 if (!floatbar || !floatbar->xfc || !event)
798 if (!floatbar->created)
801 if (event->xany.window == floatbar->handle)
804 size_t size = ARRAYSIZE(floatbar->buttons);
806 for (
size_t i = 0; i < size; i++)
808 const xfFloatbarButton* button = floatbar->buttons[i];
810 if (event->xany.window == button->handle)
817BOOL xf_floatbar_event_process(xfFloatbar* floatbar,
const XEvent* event)
819 if (!floatbar || !floatbar->xfc || !event)
822 if (!floatbar->created)
828 if (event->xexpose.window == floatbar->handle)
829 xf_floatbar_event_expose(floatbar);
831 xf_floatbar_button_event_expose(floatbar, event->xexpose.window);
836 xf_floatbar_event_motionnotify(floatbar, &event->xmotion);
840 if (event->xany.window == floatbar->handle)
841 xf_floatbar_event_buttonpress(floatbar, &event->xbutton);
843 xf_floatbar_button_event_buttonpress(floatbar, &event->xbutton);
848 if (event->xany.window == floatbar->handle)
849 xf_floatbar_event_buttonrelease(floatbar, &event->xbutton);
851 xf_floatbar_button_event_buttonrelease(floatbar, &event->xbutton);
857 if (event->xany.window != floatbar->handle)
858 xf_floatbar_button_event_focusin(floatbar, &event->xany);
864 if (event->xany.window == floatbar->handle)
865 xf_floatbar_event_focusout(floatbar);
867 xf_floatbar_button_event_focusout(floatbar, &event->xany);
871 case ConfigureNotify:
872 if (event->xany.window == floatbar->handle)
873 xf_floatbar_button_update_positon(floatbar);
878 if (event->xany.window == floatbar->handle)
879 xf_floatbar_button_update_positon(floatbar);
887 return floatbar->handle ==
event->xany.window;
890static void xf_floatbar_button_free(xfContext* xfc, xfFloatbarButton* button)
898 WINPR_ASSERT(xfc->display);
899 LogDynAndXUnmapWindow(xfc->log, xfc->display, button->handle);
900 LogDynAndXDestroyWindow(xfc->log, xfc->display, button->handle);
906void xf_floatbar_free(xfFloatbar* floatbar)
909 xfContext* xfc = NULL;
914 free(floatbar->title);
918 size = ARRAYSIZE(floatbar->buttons);
920 for (
size_t i = 0; i < size; i++)
922 xf_floatbar_button_free(xfc, floatbar->buttons[i]);
923 floatbar->buttons[i] = NULL;
926 if (floatbar->handle)
928 WINPR_ASSERT(xfc->display);
929 LogDynAndXUnmapWindow(xfc->log, xfc->display, floatbar->handle);
930 LogDynAndXDestroyWindow(xfc->log, xfc->display, floatbar->handle);
936BOOL xf_floatbar_is_locked(xfFloatbar* floatbar)
940 return floatbar->mode != XF_FLOATBAR_MODE_NONE;