21#include <freerdp/config.h>
22#include "xf_reconnect.h"
30#include <winpr/assert.h>
31#include <winpr/path.h>
33#include <freerdp/log.h>
34#include <freerdp/locale/keyboard.h>
38#include "xf_cliprdr.h"
42#include "xf_graphics.h"
48#define CLAMP_COORDINATES(x, y) \
57static const DWORD mouseLogLevel = WLOG_TRACE;
59const char* x11_event_string(
int event)
73 return "ButtonRelease";
76 return "MotionNotify";
91 return "KeymapNotify";
97 return "GraphicsExpose";
102 case VisibilityNotify:
103 return "VisibilityNotify";
106 return "CreateNotify";
109 return "DestroyNotify";
112 return "UnmapNotify";
121 return "ReparentNotify";
123 case ConfigureNotify:
124 return "ConfigureNotify";
126 case ConfigureRequest:
127 return "ConfigureRequest";
130 return "GravityNotify";
133 return "ResizeRequest";
135 case CirculateNotify:
136 return "CirculateNotify";
138 case CirculateRequest:
139 return "CirculateRequest";
142 return "PropertyNotify";
145 return "SelectionClear";
147 case SelectionRequest:
148 return "SelectionRequest";
150 case SelectionNotify:
151 return "SelectionNotify";
154 return "ColormapNotify";
157 return "ClientMessage";
160 return "MappingNotify";
163 return "GenericEvent";
170static BOOL xf_action_script_append(xfContext* xfc,
const char* buffer,
size_t size,
171 WINPR_ATTR_UNUSED
void* user,
const char* what,
const char* arg)
177 if (!buffer || (size == 0))
180 if (!ArrayList_Append(xfc->xevents, buffer))
182 ArrayList_Clear(xfc->xevents);
188BOOL xf_event_action_script_init(xfContext* xfc)
192 xf_event_action_script_free(xfc);
194 char* val = getConfigOption(TRUE,
"isActionScriptAllowed");
197 xfc->isActionScriptAllowed = !val || (_stricmp(val,
"true") == 0);
200 if (!xfc->isActionScriptAllowed)
203 xfc->xevents = ArrayList_New(TRUE);
208 wObject* obj = ArrayList_Object(xfc->xevents);
213 return run_action_script(xfc,
"xevent",
nullptr, xf_action_script_append,
nullptr);
216void xf_event_action_script_free(xfContext* xfc)
220 ArrayList_Free(xfc->xevents);
221 xfc->xevents =
nullptr;
225static BOOL action_script_run(xfContext* xfc,
const char* buffer,
size_t size,
void* user,
226 const char* what,
const char* arg)
229 if (!xfc->isActionScriptAllowed)
239 WLog_Print(xfc->log, WLOG_WARN,
"ActionScript xevent: script did not return data");
243 if (winpr_PathFileExists(buffer))
247 winpr_asprintf(&cmd, &cmdlen,
"%s %s %s", buffer, what, arg);
252 FILE* fp = popen(cmd,
"w");
256 WLog_Print(xfc->log, WLOG_ERROR,
"Failed to execute '%s'", buffer);
260 *pstatus = pclose(fp);
263 WLog_Print(xfc->log, WLOG_ERROR,
"Command '%s' returned %d", buffer, *pstatus);
269 WLog_Print(xfc->log, WLOG_WARN,
"ActionScript xevent: No such file '%s'", buffer);
276static BOOL xf_event_execute_action_script(xfContext* xfc,
const XEvent* event)
279 char* name =
nullptr;
281 const char* xeventName =
nullptr;
283 if (!xfc->actionScriptExists || !xfc->xevents || !xfc->window)
286 if (event->type > LASTEvent)
289 xeventName = x11_event_string(event->type);
290 count = ArrayList_Count(xfc->xevents);
292 for (
size_t index = 0; index < count; index++)
294 name = (
char*)ArrayList_GetItem(xfc->xevents, index);
296 if (_stricmp(name, xeventName) == 0)
306 char command[2048] = WINPR_C_ARRAY_INIT;
307 char arg[2048] = WINPR_C_ARRAY_INIT;
308 (void)_snprintf(command,
sizeof(command),
"xevent %s", xeventName);
309 (void)_snprintf(arg,
sizeof(arg),
"%lu", (
unsigned long)xfc->window->handle);
310 return run_action_script(xfc, command, arg, action_script_run,
nullptr);
313void xf_adjust_coordinates_to_screen(xfContext* xfc, UINT32* x, UINT32* y)
315 if (!xfc || !xfc->common.context.settings || !y || !x)
318 rdpSettings* settings = xfc->common.context.settings;
321 if (!xfc->remote_app)
325 if (xf_picture_transform_required(xfc))
329 double xScalingFactor = xfc->scaledWidth / dw;
330 double yScalingFactor = xfc->scaledHeight / dh;
331 tx = (INT64)lround((1.0 * (*x) + xfc->offset_x) * xScalingFactor);
332 ty = (INT64)lround((1.0 * (*y) + xfc->offset_y) * yScalingFactor);
338 CLAMP_COORDINATES(tx, ty);
343void xf_event_adjust_coordinates(xfContext* xfc,
int* x,
int* y)
345 if (!xfc || !xfc->common.context.settings || !y || !x)
348 if (!xfc->remote_app)
351 rdpSettings* settings = xfc->common.context.settings;
352 if (xf_picture_transform_required(xfc))
355 (double)xfc->scaledWidth;
357 (double)xfc->scaledHeight;
358 *x = (int)((*x - xfc->offset_x) * xScalingFactor);
359 *y = (int)((*y - xfc->offset_y) * yScalingFactor);
365 CLAMP_COORDINATES(*x, *y);
368static BOOL xf_event_Expose(xfContext* xfc,
const XExposeEvent* event, BOOL app)
373 rdpSettings* settings = xfc->common.context.settings;
374 WINPR_ASSERT(settings);
379 xfc->exposedArea.x = 0;
380 xfc->exposedArea.y = 0;
381 xfc->exposedArea.w = WINPR_ASSERTING_INT_CAST(
383 xfc->exposedArea.h = WINPR_ASSERTING_INT_CAST(
388 xfc->exposedArea.x =
event->x;
389 xfc->exposedArea.y =
event->y;
390 xfc->exposedArea.w =
event->width;
391 xfc->exposedArea.h =
event->height;
394 xfc->exposedWindow =
event->window;
395 xfc->exposeRequested =
true;
400static BOOL xf_event_VisibilityNotify(xfContext* xfc,
const XVisibilityEvent* event, BOOL app)
403 xfc->unobscured =
event->state == VisibilityUnobscured;
407BOOL xf_generic_MotionNotify_(xfContext* xfc,
int x,
int y, Window window, BOOL app,
408 const char* file,
const char* fkt,
size_t line)
410 Window childWindow = None;
412 if (WLog_IsLevelActive(xfc->log, mouseLogLevel))
413 WLog_PrintTextMessage(xfc->log, mouseLogLevel, line, file, fkt,
414 "%s: x=%d, y=%d, window=0x%08lx, app=%d", __func__, x, y, window,
418 WINPR_ASSERT(xfc->common.context.settings);
423 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, window);
424 xf_rail_return_window(appWindow, FALSE);
429 XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y, &x, &y,
433 xf_event_adjust_coordinates(xfc, &x, &y);
434 freerdp_client_send_button_event(&xfc->common, FALSE, PTR_FLAGS_MOVE, x, y);
436 if (xfc->fullscreen && !app)
439 XSetInputFocus(xfc->display, xfc->window->handle, RevertToPointerRoot, CurrentTime);
445BOOL xf_generic_RawMotionNotify_(xfContext* xfc,
int x,
int y, WINPR_ATTR_UNUSED Window window,
446 BOOL app,
const char* file,
const char* fkt,
size_t line)
450 if (WLog_IsLevelActive(xfc->log, mouseLogLevel))
451 WLog_PrintTextMessage(xfc->log, mouseLogLevel, line, file, fkt,
452 "%s: x=%d, y=%d, window=0x%08lx, app=%d", __func__, x, y, window,
457 WLog_Print(xfc->log, WLOG_ERROR,
458 "Relative mouse input is not supported with remoate app mode!");
462 return freerdp_client_send_button_event(&xfc->common, TRUE, PTR_FLAGS_MOVE, x, y);
465static BOOL xf_event_MotionNotify(xfContext* xfc,
const XMotionEvent* event, BOOL app)
470 xf_floatbar_set_root_y(xfc->window->floatbar, event->y);
472 if (xfc->xi_event || xfc->xi_rawevent || (xfc->common.mouse_grabbed && xf_use_rel_mouse(xfc)))
475 return xf_generic_MotionNotify(xfc, event->x, event->y, event->window, app);
478BOOL xf_generic_ButtonEvent_(xfContext* xfc,
int x,
int y,
int button, Window window, BOOL app,
479 BOOL down,
const char* file,
const char* fkt,
size_t line)
482 Window childWindow = None;
484 if (WLog_IsLevelActive(xfc->log, mouseLogLevel))
485 WLog_PrintTextMessage(xfc->log, mouseLogLevel, line, file, fkt,
486 "%s: x=%d, y=%d, button=%d, window=0x%08lx, app=%d, down=%d",
487 __func__, x, y, button, window, app, down);
493 for (
size_t i = 0; i < ARRAYSIZE(xfc->button_map); i++)
497 if (cur->button == (UINT32)button)
506 if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
510 if (!xf_keyboard_flush_deferred_alt(xfc))
512 freerdp_client_send_wheel_event(&xfc->common, flags);
517 BOOL extended = FALSE;
519 if (flags & (PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2))
524 flags |= PTR_XFLAGS_DOWN;
526 else if (flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))
529 flags |= PTR_FLAGS_DOWN;
535 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, window);
536 xf_rail_return_window(appWindow, FALSE);
541 XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y,
542 &x, &y, &childWindow);
545 xf_event_adjust_coordinates(xfc, &x, &y);
547 if (!xf_keyboard_flush_deferred_alt(xfc))
550 freerdp_client_send_extended_button_event(&xfc->common, FALSE, flags, x, y);
552 freerdp_client_send_button_event(&xfc->common, FALSE, flags, x, y);
559static BOOL xf_grab_mouse(xfContext* xfc)
568 XGrabPointer(xfc->display, xfc->window->handle, False,
569 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask |
570 EnterWindowMask | LeaveWindowMask,
571 GrabModeAsync, GrabModeAsync, xfc->window->handle, None, CurrentTime);
572 xfc->common.mouse_grabbed = TRUE;
577static BOOL xf_grab_kbd(xfContext* xfc)
584 XGrabKeyboard(xfc->display, xfc->window->handle, TRUE, GrabModeAsync, GrabModeAsync,
589static BOOL xf_event_ButtonPress(xfContext* xfc,
const XButtonEvent* event, BOOL app)
593 if (xfc->xi_event || xfc->xi_rawevent || (xfc->common.mouse_grabbed && xf_use_rel_mouse(xfc)))
595 if (!app && xfc_is_floatbar_window(xfc, event->window))
597 return xf_generic_ButtonEvent(xfc, event->x, event->y,
598 WINPR_ASSERTING_INT_CAST(
int, event->button), event->window, app,
602static BOOL xf_event_ButtonRelease(xfContext* xfc,
const XButtonEvent* event, BOOL app)
606 if (xfc->xi_event || xfc->xi_rawevent || (xfc->common.mouse_grabbed && xf_use_rel_mouse(xfc)))
608 return xf_generic_ButtonEvent(xfc, event->x, event->y,
609 WINPR_ASSERTING_INT_CAST(
int, event->button), event->window, app,
613static BOOL xf_event_KeyPress(xfContext* xfc,
const XKeyEvent* event, BOOL app)
616 char str[256] = WINPR_C_ARRAY_INIT;
619 const XKeyEvent* cev;
624 XLookupString(cnv.ev, str,
sizeof(str), &keysym,
nullptr);
625 xf_keyboard_key_press(xfc, event, keysym);
629static BOOL xf_event_KeyRelease(xfContext* xfc,
const XKeyEvent* event, BOOL app)
632 char str[256] = WINPR_C_ARRAY_INIT;
635 const XKeyEvent* cev;
641 XLookupString(cnv.ev, str,
sizeof(str), &keysym,
nullptr);
642 xf_keyboard_key_release(xfc, event, keysym);
648static BOOL xf_event_KeyReleaseOrIgnore(xfContext* xfc,
const XKeyEvent* event, BOOL app)
653 if ((event->type == KeyRelease) && XEventsQueued(xfc->display, QueuedAfterReading))
655 XEvent nev = WINPR_C_ARRAY_INIT;
656 XPeekEvent(xfc->display, &nev);
658 if ((nev.type == KeyPress) && (nev.xkey.time == event->time) &&
659 (nev.xkey.keycode == event->keycode))
666 return xf_event_KeyRelease(xfc, event, app);
669static BOOL xf_event_FocusIn(xfContext* xfc,
const XFocusInEvent* event, BOOL app)
671 if (event->mode == NotifyGrab)
676 if (xfc->mouse_active && !app)
679 if (!xf_grab_kbd(xfc))
686 xf_keyboard_release_all_keypress(xfc);
700 xf_pointer_update_scale(xfc);
704 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
709 xf_rail_adjust_position(xfc, appWindow);
710 xf_rail_return_window(appWindow, FALSE);
713 xf_keyboard_focus_in(xfc);
717static BOOL xf_event_FocusOut(xfContext* xfc,
const XFocusOutEvent* event, BOOL app)
719 if (event->mode == NotifyUngrab)
722 xfc->focused = FALSE;
724 if (event->mode == NotifyWhileGrabbed)
725 XUngrabKeyboard(xfc->display, CurrentTime);
728 xf_keyboard_release_all_keypress(xfc);
742static BOOL xf_event_MappingNotify(xfContext* xfc,
const XMappingEvent* event, BOOL app)
746 switch (event->request)
748 case MappingModifier:
749 return xf_keyboard_update_modifier_map(xfc);
750 case MappingKeyboard:
751 WLog_Print(xfc->log, WLOG_TRACE,
"[%d] MappingKeyboard", event->request);
752 return xf_keyboard_init(xfc);
754 WLog_Print(xfc->log, WLOG_TRACE,
"[%d] MappingPointer", event->request);
755 xf_button_map_init(xfc);
758 WLog_Print(xfc->log, WLOG_WARN,
759 "[%d] Unsupported MappingNotify::request, must be one "
760 "of[MappingModifier(%d), MappingKeyboard(%d), MappingPointer(%d)]",
761 event->request, MappingModifier, MappingKeyboard, MappingPointer);
766static BOOL xf_event_ClientMessage(xfContext* xfc,
const XClientMessageEvent* event, BOOL app)
768 if ((event->message_type == xfc->WM_PROTOCOLS) &&
769 ((Atom)event->data.l[0] == xfc->WM_DELETE_WINDOW))
774 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
777 rc = xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_CLOSE);
778 xf_rail_return_window(appWindow, FALSE);
783 WLog_Print(xfc->log, WLOG_TRACE,
"Main window closed");
791static BOOL xf_event_EnterNotify(xfContext* xfc,
const XEnterWindowEvent* event, BOOL app)
798 xfc->mouse_active = TRUE;
801 XSetInputFocus(xfc->display, xfc->window->handle, RevertToPointerRoot, CurrentTime);
808 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
811 xfc->appWindow = appWindow;
812 xf_rail_return_window(appWindow, FALSE);
818static BOOL xf_event_LeaveNotify(xfContext* xfc,
const XLeaveWindowEvent* event, BOOL app)
820 if (event->mode == NotifyGrab || event->mode == NotifyUngrab)
824 xfc->mouse_active = FALSE;
825 XUngrabKeyboard(xfc->display, CurrentTime);
829 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
832 if (xfc->appWindow == appWindow)
833 xfc->appWindow =
nullptr;
834 xf_rail_return_window(appWindow, FALSE);
839static BOOL xf_event_ConfigureNotify(xfContext* xfc,
const XConfigureEvent* event, BOOL app)
841 Window childWindow = None;
842 xfAppWindow* appWindow =
nullptr;
847 const rdpSettings* settings = xfc->common.context.settings;
848 WINPR_ASSERT(settings);
850 WLog_Print(xfc->log, WLOG_DEBUG,
"x=%" PRId32
", y=%" PRId32
", w=%" PRId32
", h=%" PRId32,
851 event->x, event->y, event->width, event->height);
858 if (xfc->window->left != event->x)
859 xfc->window->left =
event->x;
861 if (xfc->window->top != event->y)
862 xfc->window->top =
event->y;
864 if (xfc->window->width != event->width || xfc->window->height != event->height)
866 xfc->window->width =
event->width;
867 xfc->window->height =
event->height;
875 xfc->scaledWidth = xfc->window->width;
876 xfc->scaledHeight = xfc->window->height;
879 WINPR_ASSERTING_INT_CAST(
881 WINPR_ASSERTING_INT_CAST(
886 xfc->scaledWidth = WINPR_ASSERTING_INT_CAST(
888 xfc->scaledHeight = WINPR_ASSERTING_INT_CAST(
897 const int alignedWidth = (xfc->window->width / 2) * 2;
898 const int alignedHeight = (xfc->window->height / 2) * 2;
900 xf_disp_handle_configureNotify(xfc, alignedWidth, alignedHeight);
905 appWindow = xf_AppWindowFromX11Window(xfc, event->window);
913 XTranslateCoordinates(xfc->display, appWindow->handle, RootWindowOfScreen(xfc->screen),
914 0, 0, &appWindow->x, &appWindow->y, &childWindow);
915 appWindow->width =
event->width;
916 appWindow->height =
event->height;
918 xf_AppWindowResize(xfc, appWindow);
926 if (appWindow->decorations)
929 xf_rail_adjust_position(xfc, appWindow);
933 if ((!event->send_event || appWindow->local_move.state == LMS_NOT_ACTIVE) &&
934 !appWindow->rail_ignore_configure && xfc->focused)
935 xf_rail_adjust_position(xfc, appWindow);
938 xf_rail_return_window(appWindow, FALSE);
940 return xf_pointer_update_scale(xfc);
943static BOOL xf_event_MapNotify(xfContext* xfc,
const XMapEvent* event, BOOL app)
948 if (!gdi_send_suppress_output(xfc->common.context.gdi, FALSE))
953 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
963 appWindow->is_mapped = TRUE;
964 if (appWindow->surfaceStale)
966 const UINT64 windowId = appWindow->windowId;
967 const UINT32 surfaceId = appWindow->surfaceId;
968 xf_rail_return_window(appWindow, FALSE);
969 return xf_AppWindowRepaintFromSurface(xfc, windowId, surfaceId);
972 xf_rail_return_window(appWindow, FALSE);
978static BOOL xf_event_UnmapNotify(xfContext* xfc,
const XUnmapEvent* event, BOOL app)
984 xf_keyboard_release_all_keypress(xfc);
987 return gdi_send_suppress_output(xfc->common.context.gdi, TRUE);
990 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
993 appWindow->is_mapped = FALSE;
994 xf_rail_return_window(appWindow, FALSE);
1000static BOOL xf_event_PropertyNotify(xfContext* xfc,
const XPropertyEvent* event, BOOL app)
1004 WINPR_ASSERT(event);
1006 const Window root = DefaultRootWindow(xfc->display);
1007 if ((event->window == root) &&
1008 ((event->atom == xfc->NET_WORKAREA) || (event->atom == xfc->NET_CURRENT_DESKTOP)))
1010 if (xfc->remote_app && xfc->rail)
1011 return xf_rail_schedule_workarea(xfc);
1019 if (((event->atom == xfc->NET_WM_STATE) && (event->state != PropertyDelete)) ||
1020 ((event->atom == xfc->WM_STATE) && (event->state != PropertyDelete)))
1022 BOOL status = FALSE;
1023 BOOL minimized = FALSE;
1024 BOOL minimizedChanged = FALSE;
1025 BOOL fullscreen = FALSE;
1026 unsigned long nitems = 0;
1027 unsigned long bytes = 0;
1028 unsigned char* prop =
nullptr;
1029 xfAppWindow* appWindow =
nullptr;
1033 appWindow = xf_AppWindowFromX11Window(xfc, event->window);
1039 if (event->atom == xfc->NET_WM_STATE)
1041 status = xf_GetWindowProperty(xfc, event->window, xfc->NET_WM_STATE, 12, &nitems,
1048 appWindow->maxVert = FALSE;
1049 appWindow->maxHorz = FALSE;
1051 for (
unsigned long i = 0; i < nitems; i++)
1053 if ((Atom)WINPR_PACKED_ALIGN_CAST(UINT16**, prop)[i] ==
1054 xfc->NET_WM_STATE_FULLSCREEN)
1056 if ((Atom)(WINPR_PACKED_ALIGN_CAST(UINT16**, prop))[i] ==
1057 Logging_XInternAtom(xfc->log, xfc->display,
"_NET_WM_STATE_MAXIMIZED_VERT",
1061 appWindow->maxVert = TRUE;
1064 if ((Atom)(WINPR_PACKED_ALIGN_CAST(UINT16**, prop)[i]) ==
1065 Logging_XInternAtom(xfc->log, xfc->display,
"_NET_WM_STATE_MAXIMIZED_HORZ",
1069 appWindow->maxHorz = TRUE;
1075 if (appWindow && appWindow->rail_fullscreen_normalizing)
1077 if (!fullscreen && appWindow->maxVert && appWindow->maxHorz)
1080 appWindow->rail_fullscreen_normalizing = FALSE;
1087 xf_SendClientEvent(xfc, appWindow->handle, xfc->NET_WM_STATE, 4,
1088 NET_WM_STATE_REMOVE, xfc->NET_WM_STATE_FULLSCREEN, 0,
1091 if (!appWindow->maxVert || !appWindow->maxHorz)
1092 xf_SendClientEvent(xfc, appWindow->handle, xfc->NET_WM_STATE, 4,
1093 NET_WM_STATE_ADD, xfc->NET_WM_STATE_MAXIMIZED_VERT,
1094 xfc->NET_WM_STATE_MAXIMIZED_HORZ, 0);
1099 else if (appWindow && fullscreen &&
1100 (appWindow->rail_state == WINDOW_SHOW_MAXIMIZED))
1106 appWindow->rail_fullscreen_normalizing = TRUE;
1108 xf_SendClientEvent(xfc, appWindow->handle, xfc->NET_WM_STATE, 4,
1109 NET_WM_STATE_REMOVE, xfc->NET_WM_STATE_FULLSCREEN, 0, 0);
1111 if (!appWindow->maxVert || !appWindow->maxHorz)
1112 xf_SendClientEvent(xfc, appWindow->handle, xfc->NET_WM_STATE, 4,
1113 NET_WM_STATE_ADD, xfc->NET_WM_STATE_MAXIMIZED_VERT,
1114 xfc->NET_WM_STATE_MAXIMIZED_HORZ, 0);
1121 if (event->atom == xfc->WM_STATE)
1124 xf_GetWindowProperty(xfc, event->window, xfc->WM_STATE, 1, &nitems, &bytes, &prop);
1129 if (((UINT32)*prop == 3) && !IsGnome())
1133 appWindow->minimized = TRUE;
1139 appWindow->minimized = FALSE;
1142 minimizedChanged = TRUE;
1149 WINPR_ASSERT(appWindow);
1150 if (appWindow->maxVert && appWindow->maxHorz && !appWindow->minimized)
1152 if (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED)
1154 appWindow->rail_state = WINDOW_SHOW_MAXIMIZED;
1155 rc = xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MAXIMIZE);
1158 else if (appWindow->minimized)
1160 if (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)
1162 appWindow->rail_state = WINDOW_SHOW_MINIMIZED;
1163 rc = xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MINIMIZE);
1168 if (appWindow->rail_state != WINDOW_SHOW && appWindow->rail_state != WINDOW_HIDE)
1170 appWindow->rail_state = WINDOW_SHOW;
1171 rc = xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE);
1175 else if (minimizedChanged)
1176 rc = gdi_send_suppress_output(xfc->common.context.gdi, minimized);
1179 xf_rail_return_window(appWindow, FALSE);
1185static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow,
const XEvent* event)
1187 if (!xfc->remote_app)
1190 switch (appWindow->local_move.state)
1192 case LMS_NOT_ACTIVE:
1198 if ((event->type == ConfigureNotify) && appWindow->rail_ignore_configure)
1200 appWindow->rail_ignore_configure = FALSE;
1210 switch (event->type)
1212 case ConfigureNotify:
1215 appWindow->local_move.state = LMS_ACTIVE;
1232 case VisibilityNotify:
1233 case PropertyNotify:
1248 switch (event->type)
1250 case ConfigureNotify:
1251 case VisibilityNotify:
1252 case PropertyNotify:
1260 xf_rail_end_local_move(xfc, appWindow);
1266 case LMS_TERMINATING:
1276BOOL xf_event_process(freerdp* instance,
const XEvent* event)
1280 WINPR_ASSERT(instance);
1281 WINPR_ASSERT(event);
1283 xfContext* xfc = (xfContext*)instance->context;
1285 if (!xf_reconnect_event(xfc, event))
1288 rdpSettings* settings = xfc->common.context.settings;
1289 WINPR_ASSERT(settings);
1291 if (xfc->remote_app)
1293 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window);
1298 xfc->appWindow = appWindow;
1300 const BOOL rc = xf_event_suppress_events(xfc, appWindow, event);
1301 xf_rail_return_window(appWindow, FALSE);
1309 xfFloatbar* floatbar = xfc->window->floatbar;
1310 if (xf_floatbar_check_event(floatbar, event))
1312 xf_floatbar_event_process(floatbar, event);
1316 if (xf_floatbar_is_locked(floatbar))
1319 switch (event->type)
1337 xf_event_execute_action_script(xfc, event);
1339 if (event->type != MotionNotify)
1341 WLog_Print(xfc->log, WLOG_TRACE,
"%s Event(%d): wnd=0x%08lX", x11_event_string(event->type),
1342 event->type, (
unsigned long)event->xany.window);
1345 switch (event->type)
1348 status = xf_event_Expose(xfc, &event->xexpose, xfc->remote_app);
1351 case VisibilityNotify:
1352 status = xf_event_VisibilityNotify(xfc, &event->xvisibility, xfc->remote_app);
1356 status = xf_event_MotionNotify(xfc, &event->xmotion, xfc->remote_app);
1360 status = xf_event_ButtonPress(xfc, &event->xbutton, xfc->remote_app);
1364 status = xf_event_ButtonRelease(xfc, &event->xbutton, xfc->remote_app);
1368 status = xf_event_KeyPress(xfc, &event->xkey, xfc->remote_app);
1372 status = xf_event_KeyReleaseOrIgnore(xfc, &event->xkey, xfc->remote_app);
1376 status = xf_event_FocusIn(xfc, &event->xfocus, xfc->remote_app);
1380 status = xf_event_FocusOut(xfc, &event->xfocus, xfc->remote_app);
1384 status = xf_event_EnterNotify(xfc, &event->xcrossing, xfc->remote_app);
1388 status = xf_event_LeaveNotify(xfc, &event->xcrossing, xfc->remote_app);
1394 case GraphicsExpose:
1397 case ConfigureNotify:
1398 status = xf_event_ConfigureNotify(xfc, &event->xconfigure, xfc->remote_app);
1402 status = xf_event_MapNotify(xfc, &event->xmap, xfc->remote_app);
1406 status = xf_event_UnmapNotify(xfc, &event->xunmap, xfc->remote_app);
1409 case ReparentNotify:
1413 status = xf_event_MappingNotify(xfc, &event->xmapping, xfc->remote_app);
1417 status = xf_event_ClientMessage(xfc, &event->xclient, xfc->remote_app);
1420 case PropertyNotify:
1421 status = xf_event_PropertyNotify(xfc, &event->xproperty, xfc->remote_app);
1426 xf_disp_handle_xevent(xfc, event);
1431 xfWindow* window = xfc->window;
1432 xfFloatbar* floatbar =
nullptr;
1434 floatbar = window->floatbar;
1436 xf_cliprdr_handle_xevent(xfc, event);
1437 if (!xf_floatbar_check_event(floatbar, event) && !xf_floatbar_is_locked(floatbar))
1439 if (xf_input_handle_event(xfc, event) < 0)
1443 LogDynAndXSync(xfc->log, xfc->display, FALSE);
1447BOOL xf_generic_RawButtonEvent_(xfContext* xfc,
int button, BOOL app, BOOL down,
const char* file,
1448 const char* fkt,
size_t line)
1452 if (WLog_IsLevelActive(xfc->log, mouseLogLevel))
1453 WLog_PrintTextMessage(xfc->log, mouseLogLevel, line, file, fkt,
1454 "%s: button=%d, app=%d, down=%d", __func__, button, app, down);
1456 if (app || (button < 0))
1459 for (
size_t i = 0; i < ARRAYSIZE(xfc->button_map); i++)
1463 if (cur->button == (UINT32)button)
1472 if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
1476 if (!xf_keyboard_flush_deferred_alt(xfc))
1478 freerdp_client_send_wheel_event(&xfc->common, flags);
1483 BOOL extended = FALSE;
1485 if (flags & (PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2))
1490 flags |= PTR_XFLAGS_DOWN;
1492 else if (flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))
1495 flags |= PTR_FLAGS_DOWN;
1498 if (!xf_keyboard_flush_deferred_alt(xfc))
1501 freerdp_client_send_extended_button_event(&xfc->common, TRUE, flags, 0, 0);
1503 freerdp_client_send_button_event(&xfc->common, TRUE, flags, 0, 0);
1510BOOL xf_event_update_screen(freerdp* instance)
1512 WINPR_ASSERT(instance);
1514 xfContext* xfc = (xfContext*)instance->context;
1517 if (!xfc->exposeRequested)
1519 xfc->exposeRequested =
false;
1521 if (!xfc->remote_app)
1523 if (xfc->common.context.gdi->gfx)
1525 xf_OutputExpose(xfc, WINPR_ASSERTING_INT_CAST(uint32_t, xfc->exposedArea.x),
1526 WINPR_ASSERTING_INT_CAST(uint32_t, xfc->exposedArea.y),
1527 WINPR_ASSERTING_INT_CAST(uint32_t, xfc->exposedArea.w),
1528 WINPR_ASSERTING_INT_CAST(uint32_t, xfc->exposedArea.h));
1531 xf_draw_screen(xfc, xfc->exposedArea.x, xfc->exposedArea.y, xfc->exposedArea.w,
1532 xfc->exposedArea.h);
1536 xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, xfc->exposedWindow);
1538 xf_UpdateWindowArea(xfc, appWindow, xfc->exposedArea.x, xfc->exposedArea.y,
1539 xfc->exposedArea.w, xfc->exposedArea.h);
1540 xf_rail_return_window(appWindow, FALSE);
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew