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 = LogDynAndXGetWindowAttributes(xfc->log, xfc->display, floatbar->root_window, &attr);
193 floatbar->x = attr.x + attr.width / 2 - FLOATBAR_DEFAULT_WIDTH / 2;
196 if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
197 floatbar->y = -FLOATBAR_HEIGHT + 1;
199 floatbar->handle = LogDynAndXCreateWindow(
200 xfc->log, xfc->display, floatbar->root_window, floatbar->x, 0, FLOATBAR_DEFAULT_WIDTH,
201 FLOATBAR_HEIGHT, 0, CopyFromParent, InputOutput, CopyFromParent, 0,
nullptr);
202 floatbar->width = FLOATBAR_DEFAULT_WIDTH;
203 floatbar->height = FLOATBAR_HEIGHT;
204 floatbar->mode = XF_FLOATBAR_MODE_NONE;
205 floatbar->buttons[0] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_CLOSE);
206 floatbar->buttons[1] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_RESTORE);
207 floatbar->buttons[2] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_MINIMIZE);
208 floatbar->buttons[3] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_LOCKED);
209 LogDynAndXSelectInput(xfc->log, xfc->display, floatbar->handle,
210 ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
211 FocusChangeMask | LeaveWindowMask | EnterWindowMask |
212 StructureNotifyMask | PropertyChangeMask);
213 floatbar->created = TRUE;
217BOOL xf_floatbar_toggle_fullscreen(xfFloatbar* floatbar,
bool fullscreen)
220 bool visible = False;
221 xfContext* xfc =
nullptr;
223 if (!floatbar || !floatbar->xfc)
227 WINPR_ASSERT(xfc->display);
230 if (floatbar->flags & 0x0001)
233 visible |= ((floatbar->flags & 0x0010) != 0) && fullscreen;
235 visible |= ((floatbar->flags & 0x0020) != 0) && !fullscreen;
240 if (!create_floatbar(floatbar))
243 LogDynAndXMapWindow(xfc->log, xfc->display, floatbar->handle);
244 size = ARRAYSIZE(floatbar->buttons);
246 for (
int i = 0; i < size; i++)
248 xfFloatbarButton* button = floatbar->buttons[i];
249 LogDynAndXMapWindow(xfc->log, xfc->display, button->handle);
253 if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
254 floatbar->y = -FLOATBAR_HEIGHT + 1;
256 xf_floatbar_hide_and_show(floatbar);
258 else if (floatbar->created)
260 XUnmapSubwindows(xfc->display, floatbar->handle);
261 LogDynAndXUnmapWindow(xfc->log, xfc->display, floatbar->handle);
267xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar,
int type)
269 xfFloatbarButton* button =
nullptr;
271 WINPR_ASSERT(floatbar);
272 WINPR_ASSERT(floatbar->xfc);
273 WINPR_ASSERT(floatbar->xfc->display);
274 WINPR_ASSERT(floatbar->handle);
276 button = (xfFloatbarButton*)calloc(1,
sizeof(xfFloatbarButton));
281 case XF_FLOATBAR_BUTTON_CLOSE:
282 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
283 button->onclick = xf_floatbar_button_onclick_close;
286 case XF_FLOATBAR_BUTTON_RESTORE:
287 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
288 button->onclick = xf_floatbar_button_onclick_restore;
291 case XF_FLOATBAR_BUTTON_MINIMIZE:
292 button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
293 button->onclick = xf_floatbar_button_onclick_minimize;
296 case XF_FLOATBAR_BUTTON_LOCKED:
297 button->x = FLOATBAR_BORDER;
298 button->onclick = xf_floatbar_button_onclick_locked;
306 button->focus = FALSE;
308 LogDynAndXCreateWindow(floatbar->xfc->log, floatbar->xfc->display, floatbar->handle,
309 button->x, 0, FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH, 0,
310 CopyFromParent, InputOutput, CopyFromParent, 0,
nullptr);
311 LogDynAndXSelectInput(floatbar->xfc->log, floatbar->xfc->display, button->handle,
312 ExposureMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
313 LeaveWindowMask | EnterWindowMask | StructureNotifyMask);
317xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window,
const char* title, DWORD flags)
320 WINPR_ASSERT(xfc->display);
324 if ((flags & 0x0001) == 0)
334 xfFloatbar* floatbar = (xfFloatbar*)calloc(1,
sizeof(xfFloatbar));
339 floatbar->title = _strdup(title);
341 if (!floatbar->title)
344 floatbar->root_window = window;
345 floatbar->flags = flags;
347 floatbar->locked = (flags & 0x0002) != 0;
348 xf_floatbar_toggle_fullscreen(floatbar, FALSE);
351 char** missingList =
nullptr;
352 int missingCount = 0;
353 char* defString =
nullptr;
354 floatbar->fontSet = XCreateFontSet(floatbar->xfc->display,
"-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
355 &missingList, &missingCount, &defString);
357 if (floatbar->fontSet ==
nullptr)
359 WLog_ERR(TAG,
"Failed to create fontset");
361 XFreeStringList(missingList);
365 WINPR_PRAGMA_DIAG_PUSH
366 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
367 xf_floatbar_free(floatbar);
368 WINPR_PRAGMA_DIAG_POP
372static unsigned long xf_floatbar_get_color(xfFloatbar* floatbar,
char* rgb_value)
376 WINPR_ASSERT(floatbar);
377 WINPR_ASSERT(floatbar->xfc);
379 Display* display = floatbar->xfc->display;
380 WINPR_ASSERT(display);
382 Colormap cmap = DefaultColormap(display, XDefaultScreen(display));
383 XParseColor(display, cmap, rgb_value, &color);
384 XAllocColor(display, cmap, &color);
388static void xf_floatbar_event_expose(xfFloatbar* floatbar)
391 GC shape_gc =
nullptr;
393 XPoint shape[5] = WINPR_C_ARRAY_INIT;
394 XPoint border[5] = WINPR_C_ARRAY_INIT;
396 WINPR_ASSERT(floatbar);
397 WINPR_ASSERT(floatbar->xfc);
399 Display* display = floatbar->xfc->display;
400 WINPR_ASSERT(display);
403 pmap = LogDynAndXCreatePixmap(floatbar->xfc->log, display, floatbar->handle,
404 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->width),
405 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height), 1);
406 gc = LogDynAndXCreateGC(floatbar->xfc->log, display, floatbar->handle, 0, 0);
407 shape_gc = LogDynAndXCreateGC(floatbar->xfc->log, display, pmap, 0, 0);
411 shape[1].x = WINPR_ASSERTING_INT_CAST(
short, floatbar->width);
413 shape[2].x = WINPR_ASSERTING_INT_CAST(
short, shape[1].x - FLOATBAR_BORDER);
414 shape[2].y = FLOATBAR_HEIGHT;
415 shape[3].x = WINPR_ASSERTING_INT_CAST(
short, shape[0].x + FLOATBAR_BORDER);
416 shape[3].y = FLOATBAR_HEIGHT;
417 shape[4].x = shape[0].x;
418 shape[4].y = shape[0].y;
420 border[0].x = shape[0].x;
421 border[0].y = WINPR_ASSERTING_INT_CAST(
short, shape[0].y - 1);
422 border[1].x = WINPR_ASSERTING_INT_CAST(
short, shape[1].x - 1);
423 border[1].y = WINPR_ASSERTING_INT_CAST(
short, shape[1].y - 1);
424 border[2].x = shape[2].x;
425 border[2].y = WINPR_ASSERTING_INT_CAST(
short, shape[2].y - 1);
426 border[3].x = WINPR_ASSERTING_INT_CAST(
short, shape[3].x - 1);
427 border[3].y = WINPR_ASSERTING_INT_CAST(
short, shape[3].y - 1);
428 border[4].x = border[0].x;
429 border[4].y = border[0].y;
431 LogDynAndXSetForeground(floatbar->xfc->log, display, shape_gc, 0);
432 LogDynAndXFillRectangle(floatbar->xfc->log, display, pmap, shape_gc, 0, 0,
433 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->width),
434 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height));
436 LogDynAndXSetForeground(floatbar->xfc->log, display, shape_gc, 1);
437 XFillPolygon(display, pmap, shape_gc, shape, 5, 0, CoordModeOrigin);
438 XShapeCombineMask(display, floatbar->handle, ShapeBounding, 0, 0, pmap, ShapeSet);
440 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
441 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
442 XFillPolygon(display, floatbar->handle, gc, shape, 4, 0, CoordModeOrigin);
444 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
445 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
446 XDrawLines(display, floatbar->handle, gc, border, 5, CoordModeOrigin);
448 const size_t len = strnlen(floatbar->title, MAX_PATH);
449 LogDynAndXSetForeground(floatbar->xfc->log, display, gc,
450 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
452 WINPR_ASSERT(len <= INT32_MAX / 2);
453 const int fx = floatbar->width / 2 - (int)len * 2;
454 if (floatbar->fontSet !=
nullptr)
456 XmbDrawString(display, floatbar->handle, floatbar->fontSet, gc, fx, 15, floatbar->title,
461 XDrawString(display, floatbar->handle, gc, fx, 15, floatbar->title, (
int)len);
463 LogDynAndXFreeGC(floatbar->xfc->log, display, gc);
464 LogDynAndXFreeGC(floatbar->xfc->log, display, shape_gc);
467static xfFloatbarButton* xf_floatbar_get_button(xfFloatbar* floatbar, Window window)
469 WINPR_ASSERT(floatbar);
470 const size_t size = ARRAYSIZE(floatbar->buttons);
472 for (
size_t i = 0; i < size; i++)
474 xfFloatbarButton* button = floatbar->buttons[i];
475 if (button->handle == window)
484static void xf_floatbar_button_update_positon(xfFloatbar* floatbar)
486 xfFloatbarButton* button =
nullptr;
487 WINPR_ASSERT(floatbar);
488 xfContext* xfc = floatbar->xfc;
489 const size_t size = ARRAYSIZE(floatbar->buttons);
491 for (
size_t i = 0; i < size; i++)
493 button = floatbar->buttons[i];
495 switch (button->type)
497 case XF_FLOATBAR_BUTTON_CLOSE:
499 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
502 case XF_FLOATBAR_BUTTON_RESTORE:
504 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
507 case XF_FLOATBAR_BUTTON_MINIMIZE:
509 floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
517 WINPR_ASSERT(xfc->display);
518 LogDynAndXMoveWindow(xfc->log, xfc->display, button->handle, button->x, button->y);
519 xf_floatbar_event_expose(floatbar);
523static void xf_floatbar_button_event_expose(xfFloatbar* floatbar, Window window)
525 xfFloatbarButton* button = xf_floatbar_get_button(floatbar, window);
526 static unsigned char* bits;
529 xfContext* xfc = floatbar->xfc;
535 WINPR_ASSERT(xfc->display);
536 WINPR_ASSERT(xfc->window);
538 gc = LogDynAndXCreateGC(xfc->log, xfc->display, button->handle, 0, 0);
539 floatbar = xfc->window->floatbar;
540 WINPR_ASSERT(floatbar);
542 switch (button->type)
544 case XF_FLOATBAR_BUTTON_CLOSE:
548 case XF_FLOATBAR_BUTTON_RESTORE:
552 case XF_FLOATBAR_BUTTON_MINIMIZE:
553 bits = minimize_bits;
556 case XF_FLOATBAR_BUTTON_LOCKED:
557 if (floatbar->locked)
568 pattern = XCreateBitmapFromData(xfc->display, button->handle, (
const char*)bits,
569 FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH);
571 if (!(button->focus))
572 LogDynAndXSetForeground(floatbar->xfc->log, xfc->display, gc,
573 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
575 LogDynAndXSetForeground(floatbar->xfc->log, xfc->display, gc,
576 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
578 LogDynAndXSetBackground(xfc->log, xfc->display, gc,
579 xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
580 XCopyPlane(xfc->display, pattern, button->handle, gc, 0, 0, FLOATBAR_BUTTON_WIDTH,
581 FLOATBAR_BUTTON_WIDTH, 0, 0, 1);
582 LogDynAndXFreePixmap(xfc->log, xfc->display, pattern);
583 LogDynAndXFreeGC(xfc->log, xfc->display, gc);
586static void xf_floatbar_button_event_buttonpress(xfFloatbar* floatbar,
const XButtonEvent* event)
589 xfFloatbarButton* button = xf_floatbar_get_button(floatbar, event->window);
592 button->clicked = TRUE;
595static void xf_floatbar_button_event_buttonrelease(xfFloatbar* floatbar,
const XButtonEvent* event)
597 xfFloatbarButton* button =
nullptr;
599 WINPR_ASSERT(floatbar);
602 button = xf_floatbar_get_button(floatbar, event->window);
607 button->onclick(floatbar);
608 button->clicked = FALSE;
612static void xf_floatbar_event_buttonpress(xfFloatbar* floatbar,
const XButtonEvent* event)
614 WINPR_ASSERT(floatbar);
617 switch (event->button)
620 if (event->x <= FLOATBAR_BORDER)
621 floatbar->mode = XF_FLOATBAR_MODE_RESIZE_LEFT;
622 else if (event->x >= (floatbar->width - FLOATBAR_BORDER))
623 floatbar->mode = XF_FLOATBAR_MODE_RESIZE_RIGHT;
625 floatbar->mode = XF_FLOATBAR_MODE_DRAGGING;
634static void xf_floatbar_event_buttonrelease(xfFloatbar* floatbar,
const XButtonEvent* event)
636 WINPR_ASSERT(floatbar);
639 switch (event->button)
642 floatbar->mode = XF_FLOATBAR_MODE_NONE;
650static void xf_floatbar_resize(xfFloatbar* floatbar,
const XMotionEvent* event)
656 WINPR_ASSERT(floatbar);
659 xfContext* xfc = floatbar->xfc;
661 WINPR_ASSERT(xfc->display);
664 movement =
event->x_root - floatbar->last_motion_x_root;
667 if (floatbar->mode == XF_FLOATBAR_MODE_RESIZE_LEFT)
669 x = floatbar->x + movement;
670 width = floatbar->width + movement * -1;
675 width = floatbar->width + movement;
679 if (FLOATBAR_MIN_WIDTH < width)
681 LogDynAndXMoveResizeWindow(xfc->log, xfc->display, floatbar->handle, x, 0,
682 WINPR_ASSERTING_INT_CAST(uint32_t, width),
683 WINPR_ASSERTING_INT_CAST(uint32_t, floatbar->height));
685 floatbar->width = width;
689static void xf_floatbar_dragging(xfFloatbar* floatbar,
const XMotionEvent* event)
694 WINPR_ASSERT(floatbar);
696 xfContext* xfc = floatbar->xfc;
698 WINPR_ASSERT(xfc->window);
699 WINPR_ASSERT(xfc->display);
702 movement =
event->x_root - floatbar->last_motion_x_root;
703 x = floatbar->x + movement;
706 if (x < 0 || (x + floatbar->width) > xfc->window->width)
710 LogDynAndXMoveWindow(xfc->log, xfc->display, floatbar->handle, x, 0);
712 floatbar->last_motion_x_root = floatbar->last_motion_x_root + movement;
716static void xf_floatbar_event_motionnotify(xfFloatbar* floatbar,
const XMotionEvent* event)
721 WINPR_ASSERT(floatbar);
724 xfContext* xfc = floatbar->xfc;
726 WINPR_ASSERT(xfc->display);
728 mode = floatbar->mode;
729 cursor = XCreateFontCursor(xfc->display, XC_arrow);
731 if ((event->state & Button1Mask) && (mode > XF_FLOATBAR_MODE_DRAGGING))
733 xf_floatbar_resize(floatbar, event);
735 else if ((event->state & Button1Mask) && (mode == XF_FLOATBAR_MODE_DRAGGING))
737 xf_floatbar_dragging(floatbar, event);
741 if (event->x <= FLOATBAR_BORDER || event->x >= floatbar->width - FLOATBAR_BORDER)
742 cursor = XCreateFontCursor(xfc->display, XC_sb_h_double_arrow);
745 XDefineCursor(xfc->display, xfc->window->handle, cursor);
746 XFreeCursor(xfc->display, cursor);
747 floatbar->last_motion_x_root =
event->x_root;
750static void xf_floatbar_button_event_focusin(xfFloatbar* floatbar,
const XAnyEvent* event)
752 xfFloatbarButton* button =
nullptr;
754 WINPR_ASSERT(floatbar);
757 button = xf_floatbar_get_button(floatbar, event->window);
761 button->focus = TRUE;
762 xf_floatbar_button_event_expose(floatbar, event->window);
766static void xf_floatbar_button_event_focusout(xfFloatbar* floatbar,
const XAnyEvent* event)
768 xfFloatbarButton* button =
nullptr;
770 WINPR_ASSERT(floatbar);
773 button = xf_floatbar_get_button(floatbar, event->window);
777 button->focus = FALSE;
778 xf_floatbar_button_event_expose(floatbar, event->window);
782static void xf_floatbar_event_focusout(xfFloatbar* floatbar)
784 WINPR_ASSERT(floatbar);
785 xfContext* xfc = floatbar->xfc;
790 WINPR_ASSERT(xfc->window);
791 WINPR_ASSERT(xfc->pointer);
792 XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
796BOOL xf_floatbar_check_event(xfFloatbar* floatbar,
const XEvent* event)
798 if (!floatbar || !floatbar->xfc || !event)
801 if (!floatbar->created)
804 if (event->xany.window == floatbar->handle)
807 size_t size = ARRAYSIZE(floatbar->buttons);
809 for (
size_t i = 0; i < size; i++)
811 const xfFloatbarButton* button = floatbar->buttons[i];
813 if (event->xany.window == button->handle)
820BOOL xf_floatbar_event_process(xfFloatbar* floatbar,
const XEvent* event)
822 if (!floatbar || !floatbar->xfc || !event)
825 if (!floatbar->created)
831 if (event->xexpose.window == floatbar->handle)
832 xf_floatbar_event_expose(floatbar);
834 xf_floatbar_button_event_expose(floatbar, event->xexpose.window);
839 xf_floatbar_event_motionnotify(floatbar, &event->xmotion);
843 if (event->xany.window == floatbar->handle)
844 xf_floatbar_event_buttonpress(floatbar, &event->xbutton);
846 xf_floatbar_button_event_buttonpress(floatbar, &event->xbutton);
851 if (event->xany.window == floatbar->handle)
852 xf_floatbar_event_buttonrelease(floatbar, &event->xbutton);
854 xf_floatbar_button_event_buttonrelease(floatbar, &event->xbutton);
859 floatbar->entered = TRUE;
862 if (event->xany.window != floatbar->handle)
863 xf_floatbar_button_event_focusin(floatbar, &event->xany);
868 floatbar->entered = FALSE;
871 if (event->xany.window == floatbar->handle)
872 xf_floatbar_event_focusout(floatbar);
874 xf_floatbar_button_event_focusout(floatbar, &event->xany);
878 case ConfigureNotify:
879 if (event->xany.window == floatbar->handle)
880 xf_floatbar_button_update_positon(floatbar);
885 if (event->xany.window == floatbar->handle)
886 xf_floatbar_button_update_positon(floatbar);
894 return floatbar->handle ==
event->xany.window;
897static void xf_floatbar_button_free(xfContext* xfc, xfFloatbarButton* button)
905 WINPR_ASSERT(xfc->display);
906 LogDynAndXUnmapWindow(xfc->log, xfc->display, button->handle);
907 LogDynAndXDestroyWindow(xfc->log, xfc->display, button->handle);
913void xf_floatbar_free(xfFloatbar* floatbar)
916 xfContext* xfc =
nullptr;
921 free(floatbar->title);
925 size = ARRAYSIZE(floatbar->buttons);
927 for (
size_t i = 0; i < size; i++)
929 xf_floatbar_button_free(xfc, floatbar->buttons[i]);
930 floatbar->buttons[i] =
nullptr;
933 if (floatbar->handle)
935 WINPR_ASSERT(xfc->display);
936 LogDynAndXUnmapWindow(xfc->log, xfc->display, floatbar->handle);
937 LogDynAndXDestroyWindow(xfc->log, xfc->display, floatbar->handle);
943BOOL xf_floatbar_is_locked(xfFloatbar* floatbar)
947 return floatbar->mode != XF_FLOATBAR_MODE_NONE;
950BOOL xf_floatbar_is_window(xfFloatbar* floatbar, Window window)
954 if (floatbar->handle == window)
956 return floatbar->entered;
959BOOL xfc_is_floatbar_window(xfContext* xfc, Window window)
961 if (!xfc || !xfc->window)
963 return xf_floatbar_is_window(xfc->window->floatbar, window);