2011-08-07 17:52:40 +04:00
|
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-08-07 17:52:40 +04:00
|
|
|
|
* X11 Event Handling
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
2023-08-10 10:58:19 +03:00
|
|
|
|
* Copyright 2023 HP Development Company, L.P.
|
2011-08-07 17:52:40 +04:00
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
2022-02-16 13:20:38 +03:00
|
|
|
|
#include <freerdp/config.h>
|
2012-08-15 01:20:53 +04:00
|
|
|
|
|
2011-10-27 21:29:16 +04:00
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
2022-01-19 11:27:39 +03:00
|
|
|
|
#include <winpr/assert.h>
|
|
|
|
|
|
2014-09-12 19:13:01 +04:00
|
|
|
|
#include <freerdp/log.h>
|
2014-11-12 06:27:33 +03:00
|
|
|
|
#include <freerdp/locale/keyboard.h>
|
2011-08-07 17:52:40 +04:00
|
|
|
|
|
2011-08-22 07:39:56 +04:00
|
|
|
|
#include "xf_rail.h"
|
2011-12-03 02:51:30 +04:00
|
|
|
|
#include "xf_window.h"
|
2011-09-23 07:37:17 +04:00
|
|
|
|
#include "xf_cliprdr.h"
|
2017-11-29 12:26:04 +03:00
|
|
|
|
#include "xf_disp.h"
|
2013-05-09 05:51:16 +04:00
|
|
|
|
#include "xf_input.h"
|
2014-06-13 00:13:12 +04:00
|
|
|
|
#include "xf_gfx.h"
|
2022-07-04 09:52:17 +03:00
|
|
|
|
#include "xf_graphics.h"
|
2011-08-22 07:39:56 +04:00
|
|
|
|
|
2011-08-07 17:52:40 +04:00
|
|
|
|
#include "xf_event.h"
|
|
|
|
|
|
2014-09-12 19:13:01 +04:00
|
|
|
|
#define TAG CLIENT_TAG("x11")
|
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
#define CLAMP_COORDINATES(x, y) \
|
2024-02-27 12:12:04 +03:00
|
|
|
|
do \
|
|
|
|
|
{ \
|
|
|
|
|
if ((x) < 0) \
|
|
|
|
|
(x) = 0; \
|
|
|
|
|
if ((y) < 0) \
|
|
|
|
|
(y) = 0; \
|
|
|
|
|
} while (0)
|
2014-01-22 18:16:14 +04:00
|
|
|
|
|
2023-02-24 10:57:59 +03:00
|
|
|
|
const char* x11_event_string(int event)
|
2011-08-19 19:12:30 +04:00
|
|
|
|
{
|
2018-01-24 18:26:27 +03:00
|
|
|
|
switch (event)
|
|
|
|
|
{
|
|
|
|
|
case KeyPress:
|
|
|
|
|
return "KeyPress";
|
|
|
|
|
|
|
|
|
|
case KeyRelease:
|
|
|
|
|
return "KeyRelease";
|
|
|
|
|
|
|
|
|
|
case ButtonPress:
|
|
|
|
|
return "ButtonPress";
|
|
|
|
|
|
|
|
|
|
case ButtonRelease:
|
|
|
|
|
return "ButtonRelease";
|
|
|
|
|
|
|
|
|
|
case MotionNotify:
|
|
|
|
|
return "MotionNotify";
|
|
|
|
|
|
|
|
|
|
case EnterNotify:
|
|
|
|
|
return "EnterNotify";
|
|
|
|
|
|
|
|
|
|
case LeaveNotify:
|
|
|
|
|
return "LeaveNotify";
|
|
|
|
|
|
|
|
|
|
case FocusIn:
|
|
|
|
|
return "FocusIn";
|
|
|
|
|
|
|
|
|
|
case FocusOut:
|
|
|
|
|
return "FocusOut";
|
|
|
|
|
|
|
|
|
|
case KeymapNotify:
|
|
|
|
|
return "KeymapNotify";
|
|
|
|
|
|
|
|
|
|
case Expose:
|
|
|
|
|
return "Expose";
|
|
|
|
|
|
|
|
|
|
case GraphicsExpose:
|
|
|
|
|
return "GraphicsExpose";
|
|
|
|
|
|
|
|
|
|
case NoExpose:
|
|
|
|
|
return "NoExpose";
|
|
|
|
|
|
|
|
|
|
case VisibilityNotify:
|
|
|
|
|
return "VisibilityNotify";
|
|
|
|
|
|
|
|
|
|
case CreateNotify:
|
|
|
|
|
return "CreateNotify";
|
|
|
|
|
|
|
|
|
|
case DestroyNotify:
|
|
|
|
|
return "DestroyNotify";
|
|
|
|
|
|
|
|
|
|
case UnmapNotify:
|
|
|
|
|
return "UnmapNotify";
|
|
|
|
|
|
|
|
|
|
case MapNotify:
|
|
|
|
|
return "MapNotify";
|
|
|
|
|
|
|
|
|
|
case MapRequest:
|
|
|
|
|
return "MapRequest";
|
|
|
|
|
|
|
|
|
|
case ReparentNotify:
|
|
|
|
|
return "ReparentNotify";
|
|
|
|
|
|
|
|
|
|
case ConfigureNotify:
|
|
|
|
|
return "ConfigureNotify";
|
|
|
|
|
|
|
|
|
|
case ConfigureRequest:
|
|
|
|
|
return "ConfigureRequest";
|
|
|
|
|
|
|
|
|
|
case GravityNotify:
|
|
|
|
|
return "GravityNotify";
|
|
|
|
|
|
|
|
|
|
case ResizeRequest:
|
|
|
|
|
return "ResizeRequest";
|
|
|
|
|
|
|
|
|
|
case CirculateNotify:
|
|
|
|
|
return "CirculateNotify";
|
|
|
|
|
|
|
|
|
|
case CirculateRequest:
|
|
|
|
|
return "CirculateRequest";
|
|
|
|
|
|
|
|
|
|
case PropertyNotify:
|
|
|
|
|
return "PropertyNotify";
|
|
|
|
|
|
|
|
|
|
case SelectionClear:
|
|
|
|
|
return "SelectionClear";
|
|
|
|
|
|
|
|
|
|
case SelectionRequest:
|
|
|
|
|
return "SelectionRequest";
|
|
|
|
|
|
|
|
|
|
case SelectionNotify:
|
|
|
|
|
return "SelectionNotify";
|
|
|
|
|
|
|
|
|
|
case ColormapNotify:
|
|
|
|
|
return "ColormapNotify";
|
|
|
|
|
|
|
|
|
|
case ClientMessage:
|
|
|
|
|
return "ClientMessage";
|
|
|
|
|
|
|
|
|
|
case MappingNotify:
|
|
|
|
|
return "MappingNotify";
|
|
|
|
|
|
|
|
|
|
case GenericEvent:
|
|
|
|
|
return "GenericEvent";
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return "UNKNOWN";
|
2021-06-18 11:00:21 +03:00
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
}
|
2013-04-02 23:13:10 +04:00
|
|
|
|
|
|
|
|
|
#ifdef WITH_DEBUG_X11
|
2016-10-07 15:04:40 +03:00
|
|
|
|
#define DEBUG_X11(...) WLog_DBG(TAG, __VA_ARGS__)
|
2013-04-02 23:13:10 +04:00
|
|
|
|
#else
|
2019-11-06 17:24:51 +03:00
|
|
|
|
#define DEBUG_X11(...) \
|
|
|
|
|
do \
|
|
|
|
|
{ \
|
|
|
|
|
} while (0)
|
2013-04-02 23:13:10 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2015-05-20 20:19:50 +03:00
|
|
|
|
BOOL xf_event_action_script_init(xfContext* xfc)
|
2014-03-23 01:12:50 +04:00
|
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
|
wObject* obj = NULL;
|
|
|
|
|
FILE* actionScript = NULL;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
char buffer[1024] = { 0 };
|
|
|
|
|
char command[1024] = { 0 };
|
2024-01-23 18:49:54 +03:00
|
|
|
|
const rdpSettings* settings = NULL;
|
|
|
|
|
const char* ActionScript = NULL;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
|
|
|
|
|
settings = xfc->common.context.settings;
|
|
|
|
|
WINPR_ASSERT(settings);
|
|
|
|
|
|
2014-03-23 01:12:50 +04:00
|
|
|
|
xfc->xevents = ArrayList_New(TRUE);
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2015-05-18 12:28:00 +03:00
|
|
|
|
if (!xfc->xevents)
|
2015-05-20 20:19:50 +03:00
|
|
|
|
return FALSE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
|
2020-05-12 18:16:14 +03:00
|
|
|
|
obj = ArrayList_Object(xfc->xevents);
|
2024-01-24 10:21:47 +03:00
|
|
|
|
WINPR_ASSERT(obj);
|
2024-02-12 12:39:37 +03:00
|
|
|
|
obj->fnObjectNew = winpr_ObjectStringClone;
|
|
|
|
|
obj->fnObjectFree = winpr_ObjectStringFree;
|
2022-03-24 13:07:11 +03:00
|
|
|
|
ActionScript = freerdp_settings_get_string(settings, FreeRDP_ActionScript);
|
|
|
|
|
sprintf_s(command, sizeof(command), "%s xevent", ActionScript);
|
2014-03-23 01:12:50 +04:00
|
|
|
|
actionScript = popen(command, "r");
|
|
|
|
|
|
2015-06-22 15:26:11 +03:00
|
|
|
|
if (!actionScript)
|
2015-05-20 20:19:50 +03:00
|
|
|
|
return FALSE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
|
2014-11-12 04:26:47 +03:00
|
|
|
|
while (fgets(buffer, sizeof(buffer), actionScript))
|
2014-03-23 01:12:50 +04:00
|
|
|
|
{
|
2020-05-18 12:18:55 +03:00
|
|
|
|
char* context = NULL;
|
|
|
|
|
strtok_s(buffer, "\n", &context);
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2024-01-24 10:21:47 +03:00
|
|
|
|
if (!buffer || !ArrayList_Append(xfc->xevents, buffer))
|
2015-06-17 23:08:02 +03:00
|
|
|
|
{
|
2018-08-17 15:28:55 +03:00
|
|
|
|
pclose(actionScript);
|
2015-06-17 23:08:02 +03:00
|
|
|
|
ArrayList_Free(xfc->xevents);
|
|
|
|
|
xfc->xevents = NULL;
|
2015-05-20 20:19:50 +03:00
|
|
|
|
return FALSE;
|
2015-06-17 23:08:02 +03:00
|
|
|
|
}
|
2014-03-23 01:12:50 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
|
pclose(actionScript);
|
2015-05-20 20:19:50 +03:00
|
|
|
|
return TRUE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void xf_event_action_script_free(xfContext* xfc)
|
|
|
|
|
{
|
|
|
|
|
if (xfc->xevents)
|
|
|
|
|
{
|
|
|
|
|
ArrayList_Free(xfc->xevents);
|
|
|
|
|
xfc->xevents = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_execute_action_script(xfContext* xfc, const XEvent* event)
|
2014-03-23 01:12:50 +04:00
|
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
|
int count = 0;
|
|
|
|
|
char* name = NULL;
|
|
|
|
|
FILE* actionScript = NULL;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
BOOL match = FALSE;
|
2024-01-23 18:49:54 +03:00
|
|
|
|
const char* xeventName = NULL;
|
|
|
|
|
const char* ActionScript = NULL;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
char buffer[1024] = { 0 };
|
|
|
|
|
char command[1024] = { 0 };
|
|
|
|
|
|
2019-01-28 12:56:48 +03:00
|
|
|
|
if (!xfc->actionScriptExists || !xfc->xevents || !xfc->window)
|
2015-06-17 23:08:02 +03:00
|
|
|
|
return FALSE;
|
2014-03-24 17:40:01 +04:00
|
|
|
|
|
2018-01-24 18:26:27 +03:00
|
|
|
|
if (event->type > LASTEvent)
|
2015-06-17 23:08:02 +03:00
|
|
|
|
return FALSE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
|
2018-01-24 18:26:27 +03:00
|
|
|
|
xeventName = x11_event_string(event->type);
|
2014-03-23 01:12:50 +04:00
|
|
|
|
count = ArrayList_Count(xfc->xevents);
|
|
|
|
|
|
2024-01-30 12:25:38 +03:00
|
|
|
|
for (int index = 0; index < count; index++)
|
2014-03-23 01:12:50 +04:00
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
|
name = (char*)ArrayList_GetItem(xfc->xevents, index);
|
2014-03-23 01:12:50 +04:00
|
|
|
|
|
|
|
|
|
if (_stricmp(name, xeventName) == 0)
|
|
|
|
|
{
|
|
|
|
|
match = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!match)
|
2015-06-17 23:08:02 +03:00
|
|
|
|
return FALSE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
|
2022-03-24 13:07:11 +03:00
|
|
|
|
ActionScript = freerdp_settings_get_string(xfc->common.context.settings, FreeRDP_ActionScript);
|
|
|
|
|
sprintf_s(command, sizeof(command), "%s xevent %s %lu", ActionScript, xeventName,
|
2022-01-19 11:27:39 +03:00
|
|
|
|
(unsigned long)xfc->window->handle);
|
2014-03-23 01:12:50 +04:00
|
|
|
|
actionScript = popen(command, "r");
|
|
|
|
|
|
2015-06-22 15:26:11 +03:00
|
|
|
|
if (!actionScript)
|
2015-06-17 23:08:02 +03:00
|
|
|
|
return FALSE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
|
2014-11-12 04:26:47 +03:00
|
|
|
|
while (fgets(buffer, sizeof(buffer), actionScript))
|
2014-03-23 01:12:50 +04:00
|
|
|
|
{
|
2020-05-18 12:18:55 +03:00
|
|
|
|
char* context = NULL;
|
|
|
|
|
strtok_s(buffer, "\n", &context);
|
2014-03-23 01:12:50 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-17 23:08:02 +03:00
|
|
|
|
pclose(actionScript);
|
|
|
|
|
return TRUE;
|
2014-03-23 01:12:50 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
2021-03-08 15:52:29 +03:00
|
|
|
|
void xf_adjust_coordinates_to_screen(xfContext* xfc, UINT32* x, UINT32* y)
|
|
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
|
rdpSettings* settings = NULL;
|
|
|
|
|
INT64 tx = 0;
|
|
|
|
|
INT64 ty = 0;
|
2021-03-08 15:52:29 +03:00
|
|
|
|
|
2022-01-19 11:27:39 +03:00
|
|
|
|
if (!xfc || !xfc->common.context.settings || !y || !x)
|
2021-03-08 15:52:29 +03:00
|
|
|
|
return;
|
|
|
|
|
|
2022-01-19 11:27:39 +03:00
|
|
|
|
settings = xfc->common.context.settings;
|
2021-03-08 15:52:29 +03:00
|
|
|
|
tx = *x;
|
|
|
|
|
ty = *y;
|
|
|
|
|
if (!xfc->remote_app)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_XRENDER
|
|
|
|
|
|
|
|
|
|
if (xf_picture_transform_required(xfc))
|
|
|
|
|
{
|
2023-10-13 10:48:44 +03:00
|
|
|
|
double xScalingFactor = xfc->scaledWidth / (double)freerdp_settings_get_uint32(
|
|
|
|
|
settings, FreeRDP_DesktopWidth);
|
|
|
|
|
double yScalingFactor = xfc->scaledHeight / (double)freerdp_settings_get_uint32(
|
|
|
|
|
settings, FreeRDP_DesktopHeight);
|
2021-03-08 15:52:29 +03:00
|
|
|
|
tx = ((tx + xfc->offset_x) * xScalingFactor);
|
|
|
|
|
ty = ((ty + xfc->offset_y) * yScalingFactor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CLAMP_COORDINATES(tx, ty);
|
|
|
|
|
*x = tx;
|
|
|
|
|
*y = ty;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-19 17:15:38 +03:00
|
|
|
|
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int* y)
|
2014-12-01 13:56:44 +03:00
|
|
|
|
{
|
2022-01-19 11:27:39 +03:00
|
|
|
|
if (!xfc || !xfc->common.context.settings || !y || !x)
|
2016-07-19 17:15:38 +03:00
|
|
|
|
return;
|
|
|
|
|
|
2014-12-01 13:56:44 +03:00
|
|
|
|
if (!xfc->remote_app)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_XRENDER
|
2022-04-28 11:49:42 +03:00
|
|
|
|
rdpSettings* settings = xfc->common.context.settings;
|
2014-12-01 13:56:44 +03:00
|
|
|
|
if (xf_picture_transform_required(xfc))
|
|
|
|
|
{
|
2023-10-13 10:48:44 +03:00
|
|
|
|
double xScalingFactor = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) /
|
|
|
|
|
(double)xfc->scaledWidth;
|
|
|
|
|
double yScalingFactor = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) /
|
|
|
|
|
(double)xfc->scaledHeight;
|
2014-12-01 13:56:44 +03:00
|
|
|
|
*x = (int)((*x - xfc->offset_x) * xScalingFactor);
|
|
|
|
|
*y = (int)((*y - xfc->offset_y) * yScalingFactor);
|
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2014-12-01 13:56:44 +03:00
|
|
|
|
#endif
|
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2014-12-01 13:56:44 +03:00
|
|
|
|
CLAMP_COORDINATES(*x, *y);
|
|
|
|
|
}
|
2022-04-28 11:49:42 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
static BOOL xf_event_Expose(xfContext* xfc, const XExposeEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
|
int x = 0;
|
|
|
|
|
int y = 0;
|
|
|
|
|
int w = 0;
|
|
|
|
|
int h = 0;
|
|
|
|
|
rdpSettings* settings = NULL;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
WINPR_ASSERT(event);
|
|
|
|
|
|
|
|
|
|
settings = xfc->common.context.settings;
|
|
|
|
|
WINPR_ASSERT(settings);
|
2014-12-01 13:56:44 +03:00
|
|
|
|
|
2023-10-13 10:48:44 +03:00
|
|
|
|
if (!app && (freerdp_settings_get_bool(settings, FreeRDP_SmartSizing) ||
|
|
|
|
|
freerdp_settings_get_bool(settings, FreeRDP_MultiTouchGestures)))
|
2014-12-01 13:56:44 +03:00
|
|
|
|
{
|
|
|
|
|
x = 0;
|
|
|
|
|
y = 0;
|
2023-10-13 10:48:44 +03:00
|
|
|
|
w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
|
|
|
|
|
h = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
|
2014-12-01 13:56:44 +03:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
x = event->x;
|
|
|
|
|
y = event->y;
|
|
|
|
|
w = event->width;
|
|
|
|
|
h = event->height;
|
2014-12-01 13:56:44 +03:00
|
|
|
|
}
|
2014-06-05 20:36:01 +04:00
|
|
|
|
|
2013-02-10 22:17:08 +04:00
|
|
|
|
if (!app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2022-01-19 11:27:39 +03:00
|
|
|
|
if (xfc->common.context.gdi->gfx)
|
2019-05-08 16:36:20 +03:00
|
|
|
|
{
|
|
|
|
|
xf_OutputExpose(xfc, x, y, w, h);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2014-12-01 13:56:44 +03:00
|
|
|
|
xf_draw_screen(xfc, x, y, w, h);
|
2013-08-04 00:13:39 +04:00
|
|
|
|
}
|
|
|
|
|
else
|
2011-08-18 09:16:49 +04:00
|
|
|
|
{
|
2022-05-19 12:08:04 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (appWindow)
|
2011-08-18 09:16:49 +04:00
|
|
|
|
{
|
2014-11-12 06:27:33 +03:00
|
|
|
|
xf_UpdateWindowArea(xfc, appWindow, x, y, w, h);
|
2011-08-18 09:16:49 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2014-12-01 13:56:44 +03:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_VisibilityNotify(xfContext* xfc, const XVisibilityEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2019-02-07 19:53:21 +03:00
|
|
|
|
WINPR_UNUSED(app);
|
2020-02-27 11:02:41 +03:00
|
|
|
|
xfc->unobscured = event->state == VisibilityUnobscured;
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2023-06-05 13:16:57 +03:00
|
|
|
|
Window childWindow = None;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
WINPR_ASSERT(xfc->common.context.settings);
|
|
|
|
|
|
2023-06-05 13:16:57 +03:00
|
|
|
|
rdpInput* input = xfc->common.context.input;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(input);
|
|
|
|
|
|
2023-10-13 10:48:44 +03:00
|
|
|
|
if (!freerdp_settings_get_bool(xfc->common.context.settings, FreeRDP_MouseMotion))
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2013-06-18 05:54:38 +04:00
|
|
|
|
if ((state & (Button1Mask | Button2Mask | Button3Mask)) == 0)
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2013-06-18 05:54:38 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2012-05-07 23:50:47 +04:00
|
|
|
|
if (app)
|
2011-08-25 01:41:45 +04:00
|
|
|
|
{
|
2012-09-19 02:57:19 +04:00
|
|
|
|
/* make sure window exists */
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (!xf_AppWindowFromX11Window(xfc, window))
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2013-03-29 07:09:28 +04:00
|
|
|
|
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Translate to desktop coordinates */
|
2019-11-06 17:24:51 +03:00
|
|
|
|
XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y, &x, &y,
|
|
|
|
|
&childWindow);
|
2012-05-07 23:50:47 +04:00
|
|
|
|
}
|
2014-12-01 13:56:44 +03:00
|
|
|
|
|
|
|
|
|
xf_event_adjust_coordinates(xfc, &x, &y);
|
2022-01-19 15:11:34 +03:00
|
|
|
|
freerdp_client_send_button_event(&xfc->common, FALSE, PTR_FLAGS_MOVE, x, y);
|
2011-08-25 01:41:45 +04:00
|
|
|
|
|
2014-11-12 06:27:33 +03:00
|
|
|
|
if (xfc->fullscreen && !app)
|
2012-05-07 23:50:47 +04:00
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
|
XSetInputFocus(xfc->display, xfc->window->handle, RevertToPointerRoot, CurrentTime);
|
2011-08-25 01:41:45 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 17:52:40 +04:00
|
|
|
|
}
|
2022-01-19 15:29:26 +03:00
|
|
|
|
|
|
|
|
|
BOOL xf_generic_RawMotionNotify(xfContext* xfc, int x, int y, Window window, BOOL app)
|
|
|
|
|
{
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
|
|
|
|
|
if (app)
|
|
|
|
|
{
|
|
|
|
|
WLog_ERR(TAG, "Relative mouse input is not supported with remoate app mode!");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-19 17:01:34 +03:00
|
|
|
|
return freerdp_client_send_button_event(&xfc->common, TRUE, PTR_FLAGS_MOVE, x, y);
|
2022-01-19 15:29:26 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
static BOOL xf_event_MotionNotify(xfContext* xfc, const XMotionEvent* event, BOOL app)
|
2013-06-18 05:54:38 +04:00
|
|
|
|
{
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
2018-12-10 17:41:20 +03:00
|
|
|
|
|
2024-03-23 04:39:45 +03:00
|
|
|
|
if (xfc->xi_event ||
|
|
|
|
|
(xfc->common.mouse_grabbed && freerdp_client_use_relative_mouse_events(&xfc->common)))
|
2020-05-22 12:24:25 +03:00
|
|
|
|
return TRUE;
|
|
|
|
|
|
2022-01-22 15:29:28 +03:00
|
|
|
|
if (xfc->window)
|
|
|
|
|
xf_floatbar_set_root_y(xfc->window->floatbar, event->y);
|
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
return xf_generic_MotionNotify(xfc, event->x, event->y, event->state, event->window, app);
|
2013-06-18 05:54:38 +04:00
|
|
|
|
}
|
2018-12-10 16:25:07 +03:00
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
BOOL xf_generic_ButtonEvent(xfContext* xfc, int x, int y, int button, Window window, BOOL app,
|
|
|
|
|
BOOL down)
|
2011-08-07 17:52:40 +04:00
|
|
|
|
{
|
2018-12-10 16:25:07 +03:00
|
|
|
|
UINT16 flags = 0;
|
2023-06-05 13:16:57 +03:00
|
|
|
|
Window childWindow = None;
|
2011-08-18 00:00:09 +04:00
|
|
|
|
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
|
2023-06-05 13:16:57 +03:00
|
|
|
|
for (size_t i = 0; i < ARRAYSIZE(xfc->button_map); i++)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2018-12-10 16:25:07 +03:00
|
|
|
|
const button_map* cur = &xfc->button_map[i];
|
2015-12-14 20:29:23 +03:00
|
|
|
|
|
2018-12-10 16:25:07 +03:00
|
|
|
|
if (cur->button == button)
|
|
|
|
|
{
|
|
|
|
|
flags = cur->flags;
|
2011-08-18 00:00:09 +04:00
|
|
|
|
break;
|
2018-12-10 16:25:07 +03:00
|
|
|
|
}
|
2011-08-18 00:00:09 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags != 0)
|
|
|
|
|
{
|
2018-12-10 16:25:07 +03:00
|
|
|
|
if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2018-12-10 16:25:07 +03:00
|
|
|
|
if (down)
|
2022-01-19 15:11:34 +03:00
|
|
|
|
freerdp_client_send_wheel_event(&xfc->common, flags);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2011-08-18 00:00:09 +04:00
|
|
|
|
else
|
|
|
|
|
{
|
2018-12-11 11:32:11 +03:00
|
|
|
|
BOOL extended = FALSE;
|
|
|
|
|
|
|
|
|
|
if (flags & (PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2))
|
|
|
|
|
{
|
|
|
|
|
extended = TRUE;
|
|
|
|
|
|
|
|
|
|
if (down)
|
|
|
|
|
flags |= PTR_XFLAGS_DOWN;
|
|
|
|
|
}
|
|
|
|
|
else if (flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))
|
|
|
|
|
{
|
|
|
|
|
if (down)
|
|
|
|
|
flags |= PTR_FLAGS_DOWN;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-18 00:00:09 +04:00
|
|
|
|
if (app)
|
|
|
|
|
{
|
2012-09-19 02:57:19 +04:00
|
|
|
|
/* make sure window exists */
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (!xf_AppWindowFromX11Window(xfc, window))
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2014-11-12 04:26:47 +03:00
|
|
|
|
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Translate to desktop coordinates */
|
2019-11-06 17:24:51 +03:00
|
|
|
|
XTranslateCoordinates(xfc->display, window, RootWindowOfScreen(xfc->screen), x, y,
|
|
|
|
|
&x, &y, &childWindow);
|
2011-08-18 00:00:09 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2014-12-01 13:56:44 +03:00
|
|
|
|
xf_event_adjust_coordinates(xfc, &x, &y);
|
2013-05-05 00:29:22 +04:00
|
|
|
|
|
2012-04-01 17:35:11 +04:00
|
|
|
|
if (extended)
|
2022-01-19 15:11:34 +03:00
|
|
|
|
freerdp_client_send_extended_button_event(&xfc->common, FALSE, flags, x, y);
|
2012-04-01 17:35:11 +04:00
|
|
|
|
else
|
2022-01-19 15:11:34 +03:00
|
|
|
|
freerdp_client_send_button_event(&xfc->common, FALSE, flags, x, y);
|
2011-08-18 00:00:09 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 17:52:40 +04:00
|
|
|
|
}
|
2022-01-19 15:27:36 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_grab_mouse(xfContext* xfc)
|
|
|
|
|
{
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
|
|
|
|
|
if (!xfc->window)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (freerdp_settings_get_bool(xfc->common.context.settings, FreeRDP_GrabMouse))
|
|
|
|
|
{
|
|
|
|
|
XGrabPointer(xfc->display, xfc->window->handle, False,
|
|
|
|
|
ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask |
|
|
|
|
|
EnterWindowMask | LeaveWindowMask,
|
|
|
|
|
GrabModeAsync, GrabModeAsync, xfc->window->handle, None, CurrentTime);
|
2022-01-26 16:21:53 +03:00
|
|
|
|
xfc->common.mouse_grabbed = TRUE;
|
2022-01-19 15:27:36 +03:00
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL xf_grab_kbd(xfContext* xfc)
|
|
|
|
|
{
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
|
|
|
|
|
if (!xfc->window)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
XGrabKeyboard(xfc->display, xfc->window->handle, TRUE, GrabModeAsync, GrabModeAsync,
|
|
|
|
|
CurrentTime);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2023-12-06 22:47:25 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
static BOOL xf_event_ButtonPress(xfContext* xfc, const XButtonEvent* event, BOOL app)
|
2013-06-18 05:54:38 +04:00
|
|
|
|
{
|
2022-01-19 15:27:36 +03:00
|
|
|
|
xf_grab_mouse(xfc);
|
2013-06-28 21:46:58 +04:00
|
|
|
|
|
2024-03-23 04:39:45 +03:00
|
|
|
|
if (xfc->xi_event ||
|
|
|
|
|
(xfc->common.mouse_grabbed && freerdp_client_use_relative_mouse_events(&xfc->common)))
|
2022-01-22 15:29:28 +03:00
|
|
|
|
return TRUE;
|
2020-02-27 11:02:41 +03:00
|
|
|
|
return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app, TRUE);
|
2013-06-18 05:54:38 +04:00
|
|
|
|
}
|
2014-01-22 18:16:14 +04:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
static BOOL xf_event_ButtonRelease(xfContext* xfc, const XButtonEvent* event, BOOL app)
|
2013-06-18 05:54:38 +04:00
|
|
|
|
{
|
2022-01-19 15:27:36 +03:00
|
|
|
|
xf_grab_mouse(xfc);
|
2013-06-28 21:46:58 +04:00
|
|
|
|
|
2024-03-23 04:39:45 +03:00
|
|
|
|
if (xfc->xi_event ||
|
|
|
|
|
(xfc->common.mouse_grabbed && freerdp_client_use_relative_mouse_events(&xfc->common)))
|
2022-01-22 15:29:28 +03:00
|
|
|
|
return TRUE;
|
2020-02-27 11:02:41 +03:00
|
|
|
|
return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app,
|
|
|
|
|
FALSE);
|
2013-06-18 05:54:38 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_KeyPress(xfContext* xfc, const XKeyEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2023-06-05 13:16:57 +03:00
|
|
|
|
KeySym keysym = 0;
|
2022-04-27 22:02:18 +03:00
|
|
|
|
char str[256] = { 0 };
|
|
|
|
|
union
|
|
|
|
|
{
|
|
|
|
|
const XKeyEvent* cev;
|
|
|
|
|
XKeyEvent* ev;
|
|
|
|
|
} cnv;
|
|
|
|
|
cnv.cev = event;
|
2019-02-07 19:53:21 +03:00
|
|
|
|
WINPR_UNUSED(app);
|
2022-04-27 22:02:18 +03:00
|
|
|
|
XLookupString(cnv.ev, str, sizeof(str), &keysym, NULL);
|
2021-09-07 09:31:07 +03:00
|
|
|
|
xf_keyboard_key_press(xfc, event, keysym);
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_KeyRelease(xfContext* xfc, const XKeyEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2023-06-05 13:16:57 +03:00
|
|
|
|
KeySym keysym = 0;
|
2022-04-27 22:02:18 +03:00
|
|
|
|
char str[256] = { 0 };
|
|
|
|
|
union
|
|
|
|
|
{
|
|
|
|
|
const XKeyEvent* cev;
|
|
|
|
|
XKeyEvent* ev;
|
|
|
|
|
} cnv;
|
|
|
|
|
cnv.cev = event;
|
|
|
|
|
|
2019-02-07 19:53:21 +03:00
|
|
|
|
WINPR_UNUSED(app);
|
2022-04-27 22:02:18 +03:00
|
|
|
|
XLookupString(cnv.ev, str, sizeof(str), &keysym, NULL);
|
2021-09-07 09:31:07 +03:00
|
|
|
|
xf_keyboard_key_release(xfc, event, keysym);
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
2022-12-12 12:14:21 +03:00
|
|
|
|
/* Release a key, but ignore the event in case of autorepeat.
|
|
|
|
|
*/
|
|
|
|
|
static BOOL xf_event_KeyReleaseOrIgnore(xfContext* xfc, const XKeyEvent* event, BOOL app)
|
|
|
|
|
{
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
WINPR_ASSERT(event);
|
|
|
|
|
|
|
|
|
|
if ((event->type == KeyRelease) && XEventsQueued(xfc->display, QueuedAfterReading))
|
|
|
|
|
{
|
|
|
|
|
XEvent nev = { 0 };
|
|
|
|
|
XPeekEvent(xfc->display, &nev);
|
|
|
|
|
|
|
|
|
|
if ((nev.type == KeyPress) && (nev.xkey.time == event->time) &&
|
|
|
|
|
(nev.xkey.keycode == event->keycode))
|
|
|
|
|
{
|
|
|
|
|
/* Key wasn’t actually released */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return xf_event_KeyRelease(xfc, event, app);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
static BOOL xf_event_FocusIn(xfContext* xfc, const XFocusInEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (event->mode == NotifyGrab)
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
xfc->focused = TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2014-11-12 06:27:33 +03:00
|
|
|
|
if (xfc->mouse_active && !app)
|
2019-02-08 12:46:26 +03:00
|
|
|
|
{
|
2022-01-19 15:27:36 +03:00
|
|
|
|
xf_grab_mouse(xfc);
|
|
|
|
|
if (!xf_grab_kbd(xfc))
|
2019-02-08 12:46:26 +03:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2020-06-29 09:39:09 +03:00
|
|
|
|
/* Release all keys, should already be done at FocusOut but might be missed
|
|
|
|
|
* if the WM decided to use an alternate event order */
|
2023-01-09 10:33:05 +03:00
|
|
|
|
if (!app)
|
2022-09-30 10:08:24 +03:00
|
|
|
|
xf_keyboard_release_all_keypress(xfc);
|
2024-03-13 17:16:39 +03:00
|
|
|
|
else
|
|
|
|
|
xf_rail_send_activate(xfc, event->window, TRUE);
|
2022-09-30 10:08:24 +03:00
|
|
|
|
|
2022-07-04 09:52:17 +03:00
|
|
|
|
xf_pointer_update_scale(xfc);
|
2020-06-29 09:39:09 +03:00
|
|
|
|
|
2011-12-20 23:51:44 +04:00
|
|
|
|
if (app)
|
2012-08-04 02:35:17 +04:00
|
|
|
|
{
|
2022-05-19 12:08:04 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2014-11-12 06:27:33 +03:00
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
/* Update the server with any window changes that occurred while the window was not focused.
|
|
|
|
|
*/
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (appWindow)
|
2014-11-12 06:27:33 +03:00
|
|
|
|
xf_rail_adjust_position(xfc, appWindow);
|
2012-08-04 02:35:17 +04:00
|
|
|
|
}
|
2013-02-12 05:38:19 +04:00
|
|
|
|
|
2014-03-14 05:10:22 +04:00
|
|
|
|
xf_keyboard_focus_in(xfc);
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_FocusOut(xfContext* xfc, const XFocusOutEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (event->mode == NotifyUngrab)
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
xfc->focused = FALSE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (event->mode == NotifyWhileGrabbed)
|
2013-06-13 02:57:25 +04:00
|
|
|
|
XUngrabKeyboard(xfc->display, CurrentTime);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2015-02-27 18:02:40 +03:00
|
|
|
|
xf_keyboard_release_all_keypress(xfc);
|
2024-03-13 17:16:39 +03:00
|
|
|
|
if (app)
|
|
|
|
|
xf_rail_send_activate(xfc, event->window, FALSE);
|
2012-08-03 00:45:03 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_MappingNotify(xfContext* xfc, const XMappingEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2019-02-07 19:53:21 +03:00
|
|
|
|
WINPR_UNUSED(app);
|
2019-05-08 16:36:20 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (event->request == MappingModifier)
|
2022-11-28 08:22:32 +03:00
|
|
|
|
return xf_keyboard_update_modifier_map(xfc);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_ClientMessage(xfContext* xfc, const XClientMessageEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if ((event->message_type == xfc->WM_PROTOCOLS) &&
|
|
|
|
|
((Atom)event->data.l[0] == xfc->WM_DELETE_WINDOW))
|
2011-09-21 16:36:49 +04:00
|
|
|
|
{
|
|
|
|
|
if (app)
|
|
|
|
|
{
|
2022-05-19 12:08:04 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (appWindow)
|
|
|
|
|
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_CLOSE);
|
2011-09-21 16:36:49 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-09-21 16:36:49 +04:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-03-23 00:30:15 +04:00
|
|
|
|
DEBUG_X11("Main window closed");
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return FALSE;
|
2011-09-21 16:36:49 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 17:52:40 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_EnterNotify(xfContext* xfc, const XEnterWindowEvent* event, BOOL app)
|
2011-08-07 17:52:40 +04:00
|
|
|
|
{
|
2013-02-10 22:17:08 +04:00
|
|
|
|
if (!app)
|
2011-08-18 09:16:49 +04:00
|
|
|
|
{
|
2019-02-08 12:46:26 +03:00
|
|
|
|
if (!xfc->window)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
xfc->mouse_active = TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
if (xfc->fullscreen)
|
2019-11-06 17:24:51 +03:00
|
|
|
|
XSetInputFocus(xfc->display, xfc->window->handle, RevertToPointerRoot, CurrentTime);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
if (xfc->focused)
|
2022-01-19 15:27:36 +03:00
|
|
|
|
xf_grab_kbd(xfc);
|
2011-12-20 23:42:22 +04:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-12-09 18:07:49 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2014-11-13 00:42:32 +03:00
|
|
|
|
|
|
|
|
|
/* keep track of which window has focus so that we can apply pointer updates */
|
2020-12-09 18:07:49 +03:00
|
|
|
|
xfc->appWindow = appWindow;
|
2011-08-18 09:16:49 +04:00
|
|
|
|
}
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 17:52:40 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_LeaveNotify(xfContext* xfc, const XLeaveWindowEvent* event, BOOL app)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2021-02-08 01:57:05 +03:00
|
|
|
|
if (event->mode == NotifyGrab || event->mode == NotifyUngrab)
|
|
|
|
|
return TRUE;
|
2013-02-10 22:17:08 +04:00
|
|
|
|
if (!app)
|
2011-08-19 19:12:30 +04:00
|
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
|
xfc->mouse_active = FALSE;
|
|
|
|
|
XUngrabKeyboard(xfc->display, CurrentTime);
|
2011-08-19 19:12:30 +04:00
|
|
|
|
}
|
2020-12-09 18:07:49 +03:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2020-12-09 18:07:49 +03:00
|
|
|
|
/* keep track of which window has focus so that we can apply pointer updates */
|
|
|
|
|
if (xfc->appWindow == appWindow)
|
|
|
|
|
xfc->appWindow = NULL;
|
|
|
|
|
}
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_ConfigureNotify(xfContext* xfc, const XConfigureEvent* event, BOOL app)
|
2011-08-18 09:16:49 +04:00
|
|
|
|
{
|
2023-06-05 13:16:57 +03:00
|
|
|
|
Window childWindow = None;
|
|
|
|
|
xfAppWindow* appWindow = NULL;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
|
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
WINPR_ASSERT(event);
|
|
|
|
|
|
2023-06-05 13:16:57 +03:00
|
|
|
|
const rdpSettings* settings = xfc->common.context.settings;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(settings);
|
2011-11-19 03:46:22 +04:00
|
|
|
|
|
2023-01-23 14:03:18 +03:00
|
|
|
|
WLog_DBG(TAG, "x=%" PRId32 ", y=%" PRId32 ", w=%" PRId32 ", h=%" PRId32, event->x, event->y,
|
|
|
|
|
event->width, event->height);
|
2022-07-04 13:13:20 +03:00
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (!app)
|
2014-12-01 13:56:44 +03:00
|
|
|
|
{
|
2019-02-08 12:46:26 +03:00
|
|
|
|
if (!xfc->window)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (xfc->window->left != event->x)
|
|
|
|
|
xfc->window->left = event->x;
|
2015-04-16 18:29:52 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (xfc->window->top != event->y)
|
|
|
|
|
xfc->window->top = event->y;
|
2015-04-16 18:29:52 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if (xfc->window->width != event->width || xfc->window->height != event->height)
|
2014-12-01 13:56:44 +03:00
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
xfc->window->width = event->width;
|
|
|
|
|
xfc->window->height = event->height;
|
2014-12-03 17:41:10 +03:00
|
|
|
|
#ifdef WITH_XRENDER
|
|
|
|
|
xfc->offset_x = 0;
|
|
|
|
|
xfc->offset_y = 0;
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2023-10-13 10:48:44 +03:00
|
|
|
|
if (freerdp_settings_get_bool(settings, FreeRDP_SmartSizing) ||
|
|
|
|
|
freerdp_settings_get_bool(settings, FreeRDP_MultiTouchGestures))
|
2014-12-01 13:56:44 +03:00
|
|
|
|
{
|
2015-04-16 18:29:52 +03:00
|
|
|
|
xfc->scaledWidth = xfc->window->width;
|
|
|
|
|
xfc->scaledHeight = xfc->window->height;
|
2023-10-13 10:48:44 +03:00
|
|
|
|
xf_draw_screen(xfc, 0, 0,
|
|
|
|
|
freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
|
|
|
|
|
freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight));
|
2014-12-01 13:56:44 +03:00
|
|
|
|
}
|
2014-12-03 17:41:10 +03:00
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-13 10:48:44 +03:00
|
|
|
|
xfc->scaledWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
|
|
|
|
|
xfc->scaledHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
|
2014-12-03 17:41:10 +03:00
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2014-12-01 13:56:44 +03:00
|
|
|
|
#endif
|
2014-12-03 17:41:10 +03:00
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2023-10-13 10:48:44 +03:00
|
|
|
|
if (freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate))
|
2017-11-29 12:26:04 +03:00
|
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
|
int alignedWidth = 0;
|
|
|
|
|
int alignedHeight = 0;
|
2017-11-29 12:26:04 +03:00
|
|
|
|
alignedWidth = (xfc->window->width / 2) * 2;
|
|
|
|
|
alignedHeight = (xfc->window->height / 2) * 2;
|
|
|
|
|
/* ask the server to resize using the display channel */
|
2017-12-19 17:16:14 +03:00
|
|
|
|
xf_disp_handle_configureNotify(xfc, alignedWidth, alignedHeight);
|
2017-11-29 12:26:04 +03:00
|
|
|
|
}
|
2014-12-01 13:56:44 +03:00
|
|
|
|
}
|
2022-07-04 09:52:17 +03:00
|
|
|
|
else
|
2014-11-12 06:27:33 +03:00
|
|
|
|
{
|
2022-07-04 09:52:17 +03:00
|
|
|
|
appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
|
|
|
|
|
|
|
|
|
if (appWindow)
|
2012-09-19 02:57:19 +04:00
|
|
|
|
{
|
2022-07-04 09:52:17 +03:00
|
|
|
|
/*
|
|
|
|
|
* ConfigureNotify coordinates are expressed relative to the window parent.
|
|
|
|
|
* Translate these to root window coordinates.
|
|
|
|
|
*/
|
|
|
|
|
XTranslateCoordinates(xfc->display, appWindow->handle, RootWindowOfScreen(xfc->screen),
|
|
|
|
|
0, 0, &appWindow->x, &appWindow->y, &childWindow);
|
|
|
|
|
appWindow->width = event->width;
|
|
|
|
|
appWindow->height = event->height;
|
|
|
|
|
|
2022-11-08 11:33:02 +03:00
|
|
|
|
xf_AppWindowResize(xfc, appWindow);
|
|
|
|
|
|
2022-07-04 09:52:17 +03:00
|
|
|
|
/*
|
|
|
|
|
* Additional checks for not in a local move and not ignoring configure to send
|
|
|
|
|
* position update to server, also should the window not be focused then do not
|
|
|
|
|
* send to server yet (i.e. resizing using window decoration).
|
|
|
|
|
* The server will be updated when the window gets refocused.
|
|
|
|
|
*/
|
|
|
|
|
if (appWindow->decorations)
|
|
|
|
|
{
|
|
|
|
|
/* moving resizing using window decoration */
|
2014-11-12 06:27:33 +03:00
|
|
|
|
xf_rail_adjust_position(xfc, appWindow);
|
2022-07-04 09:52:17 +03:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((!event->send_event || appWindow->local_move.state == LMS_NOT_ACTIVE) &&
|
|
|
|
|
!appWindow->rail_ignore_configure && xfc->focused)
|
|
|
|
|
xf_rail_adjust_position(xfc, appWindow);
|
|
|
|
|
}
|
2012-09-19 02:57:19 +04:00
|
|
|
|
}
|
2014-11-12 06:27:33 +03:00
|
|
|
|
}
|
2022-07-04 09:52:17 +03:00
|
|
|
|
return xf_pointer_update_scale(xfc);
|
2011-08-18 09:16:49 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_MapNotify(xfContext* xfc, const XMapEvent* event, BOOL app)
|
2011-08-22 07:15:19 +04:00
|
|
|
|
{
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
2013-02-10 22:17:08 +04:00
|
|
|
|
if (!app)
|
2022-01-19 11:27:39 +03:00
|
|
|
|
gdi_send_suppress_output(xfc->common.context.gdi, FALSE);
|
2012-05-28 16:21:56 +04:00
|
|
|
|
else
|
|
|
|
|
{
|
2022-05-19 12:08:04 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2012-05-28 16:21:56 +04:00
|
|
|
|
|
2023-08-10 10:58:19 +03:00
|
|
|
|
if (appWindow)
|
2012-05-28 16:21:56 +04:00
|
|
|
|
{
|
|
|
|
|
/* local restore event */
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* This is now handled as part of the PropertyNotify
|
|
|
|
|
* Doing this here would inhibit the ability to restore a maximized window
|
|
|
|
|
* that is minimized back to the maximized state
|
|
|
|
|
*/
|
2022-04-27 12:37:57 +03:00
|
|
|
|
// xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE);
|
2014-11-12 06:27:33 +03:00
|
|
|
|
appWindow->is_mapped = TRUE;
|
2012-05-28 16:21:56 +04:00
|
|
|
|
}
|
2011-11-29 01:50:08 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-11-29 01:50:08 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_UnmapNotify(xfContext* xfc, const XUnmapEvent* event, BOOL app)
|
2011-11-29 01:50:08 +04:00
|
|
|
|
{
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
WINPR_ASSERT(event);
|
|
|
|
|
|
2023-01-09 10:33:05 +03:00
|
|
|
|
if (!app)
|
2022-09-30 10:08:24 +03:00
|
|
|
|
xf_keyboard_release_all_keypress(xfc);
|
2012-04-11 08:37:47 +04:00
|
|
|
|
|
2013-02-10 22:17:08 +04:00
|
|
|
|
if (!app)
|
2022-01-19 11:27:39 +03:00
|
|
|
|
gdi_send_suppress_output(xfc->common.context.gdi, TRUE);
|
2012-05-28 16:21:56 +04:00
|
|
|
|
else
|
|
|
|
|
{
|
2022-05-19 12:08:04 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2012-05-28 16:21:56 +04:00
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (appWindow)
|
2014-11-12 06:27:33 +03:00
|
|
|
|
appWindow->is_mapped = FALSE;
|
2011-08-22 07:15:19 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-08-22 07:15:19 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_PropertyNotify(xfContext* xfc, const XPropertyEvent* event, BOOL app)
|
2011-09-23 07:37:17 +04:00
|
|
|
|
{
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
WINPR_ASSERT(event);
|
|
|
|
|
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/*
|
|
|
|
|
* This section handles sending the appropriate commands to the rail server
|
|
|
|
|
* when the window has been minimized, maximized, restored locally
|
|
|
|
|
* ie. not using the buttons on the rail window itself
|
|
|
|
|
*/
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if ((((Atom)event->atom == xfc->_NET_WM_STATE) && (event->state != PropertyDelete)) ||
|
|
|
|
|
(((Atom)event->atom == xfc->WM_STATE) && (event->state != PropertyDelete)))
|
2012-08-04 02:35:17 +04:00
|
|
|
|
{
|
2023-06-05 13:16:57 +03:00
|
|
|
|
BOOL status = FALSE;
|
2018-01-24 18:26:27 +03:00
|
|
|
|
BOOL minimized = FALSE;
|
|
|
|
|
BOOL minimizedChanged = FALSE;
|
2023-06-05 13:16:57 +03:00
|
|
|
|
unsigned long nitems = 0;
|
|
|
|
|
unsigned long bytes = 0;
|
|
|
|
|
unsigned char* prop = NULL;
|
2018-04-12 15:39:37 +03:00
|
|
|
|
xfAppWindow* appWindow = NULL;
|
|
|
|
|
|
|
|
|
|
if (app)
|
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
appWindow = xf_AppWindowFromX11Window(xfc, event->window);
|
2018-04-12 15:39:37 +03:00
|
|
|
|
|
|
|
|
|
if (!appWindow)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if ((Atom)event->atom == xfc->_NET_WM_STATE)
|
2016-07-19 17:15:38 +03:00
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_GetWindowProperty(xfc, event->window, xfc->_NET_WM_STATE, 12, &nitems,
|
|
|
|
|
&bytes, &prop);
|
2012-08-04 02:35:17 +04:00
|
|
|
|
|
2018-01-24 18:26:27 +03:00
|
|
|
|
if (status)
|
|
|
|
|
{
|
2022-04-27 22:44:40 +03:00
|
|
|
|
if (appWindow)
|
|
|
|
|
{
|
|
|
|
|
appWindow->maxVert = FALSE;
|
|
|
|
|
appWindow->maxHorz = FALSE;
|
|
|
|
|
}
|
2024-01-30 12:25:38 +03:00
|
|
|
|
for (unsigned long i = 0; i < nitems; i++)
|
2013-03-29 07:09:28 +04:00
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
|
if ((Atom)((UINT16**)prop)[i] ==
|
|
|
|
|
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_VERT", False))
|
2013-03-29 07:09:28 +04:00
|
|
|
|
{
|
2022-04-27 22:44:40 +03:00
|
|
|
|
if (appWindow)
|
|
|
|
|
appWindow->maxVert = TRUE;
|
2013-03-29 07:09:28 +04:00
|
|
|
|
}
|
2014-11-12 04:26:47 +03:00
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
if ((Atom)((UINT16**)prop)[i] ==
|
|
|
|
|
XInternAtom(xfc->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False))
|
2018-01-24 18:26:27 +03:00
|
|
|
|
{
|
2022-04-27 22:44:40 +03:00
|
|
|
|
if (appWindow)
|
|
|
|
|
appWindow->maxHorz = TRUE;
|
2018-01-24 18:26:27 +03:00
|
|
|
|
}
|
2013-03-29 07:09:28 +04:00
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
|
|
|
|
|
XFree(prop);
|
2016-07-19 17:15:38 +03:00
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
}
|
2014-12-01 13:56:44 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
if ((Atom)event->atom == xfc->WM_STATE)
|
2018-01-24 18:26:27 +03:00
|
|
|
|
{
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status =
|
|
|
|
|
xf_GetWindowProperty(xfc, event->window, xfc->WM_STATE, 1, &nitems, &bytes, &prop);
|
2018-01-24 18:26:27 +03:00
|
|
|
|
|
|
|
|
|
if (status)
|
2016-07-19 17:15:38 +03:00
|
|
|
|
{
|
2018-01-24 18:26:27 +03:00
|
|
|
|
/* If the window is in the iconic state */
|
2019-11-06 17:24:51 +03:00
|
|
|
|
if (((UINT32)*prop == 3))
|
2022-04-27 12:37:57 +03:00
|
|
|
|
{
|
2018-01-24 18:26:27 +03:00
|
|
|
|
minimized = TRUE;
|
2022-04-27 22:44:40 +03:00
|
|
|
|
if (appWindow)
|
|
|
|
|
appWindow->minimized = TRUE;
|
2022-04-27 12:37:57 +03:00
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
else
|
2022-04-27 12:37:57 +03:00
|
|
|
|
{
|
2018-01-24 18:26:27 +03:00
|
|
|
|
minimized = FALSE;
|
2022-04-27 22:44:40 +03:00
|
|
|
|
if (appWindow)
|
|
|
|
|
appWindow->minimized = FALSE;
|
2022-04-27 12:37:57 +03:00
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
|
|
|
|
|
minimizedChanged = TRUE;
|
|
|
|
|
XFree(prop);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-03-29 07:09:28 +04:00
|
|
|
|
|
2018-01-24 18:26:27 +03:00
|
|
|
|
if (app)
|
|
|
|
|
{
|
2022-04-27 22:44:40 +03:00
|
|
|
|
WINPR_ASSERT(appWindow);
|
2022-04-27 12:37:57 +03:00
|
|
|
|
if (appWindow->maxVert && appWindow->maxHorz && !appWindow->minimized)
|
2016-07-19 17:15:38 +03:00
|
|
|
|
{
|
2022-06-23 08:57:38 +03:00
|
|
|
|
if (appWindow->rail_state != WINDOW_SHOW_MAXIMIZED)
|
2022-04-27 12:37:57 +03:00
|
|
|
|
{
|
2022-06-23 08:57:38 +03:00
|
|
|
|
appWindow->rail_state = WINDOW_SHOW_MAXIMIZED;
|
|
|
|
|
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MAXIMIZE);
|
2022-04-27 12:37:57 +03:00
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
}
|
2022-04-27 12:37:57 +03:00
|
|
|
|
else if (appWindow->minimized)
|
2016-07-19 17:15:38 +03:00
|
|
|
|
{
|
2022-06-23 08:57:38 +03:00
|
|
|
|
if (appWindow->rail_state != WINDOW_SHOW_MINIMIZED)
|
2022-04-27 12:37:57 +03:00
|
|
|
|
{
|
|
|
|
|
appWindow->rail_state = WINDOW_SHOW_MINIMIZED;
|
|
|
|
|
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MINIMIZE);
|
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
}
|
2022-04-27 12:37:57 +03:00
|
|
|
|
else
|
2016-07-19 17:15:38 +03:00
|
|
|
|
{
|
2022-06-23 08:57:38 +03:00
|
|
|
|
if (appWindow->rail_state != WINDOW_SHOW && appWindow->rail_state != WINDOW_HIDE)
|
2022-04-27 12:37:57 +03:00
|
|
|
|
{
|
|
|
|
|
appWindow->rail_state = WINDOW_SHOW;
|
|
|
|
|
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE);
|
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-24 18:26:27 +03:00
|
|
|
|
else if (minimizedChanged)
|
2022-01-19 11:27:39 +03:00
|
|
|
|
gdi_send_suppress_output(xfc->common.context.gdi, minimized);
|
2016-07-19 17:15:38 +03:00
|
|
|
|
}
|
2011-09-23 07:37:17 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-09-23 07:37:17 +04:00
|
|
|
|
}
|
2020-02-27 11:02:41 +03:00
|
|
|
|
|
|
|
|
|
static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, const XEvent* event)
|
2011-08-07 21:41:54 +04:00
|
|
|
|
{
|
2013-06-13 02:57:25 +04:00
|
|
|
|
if (!xfc->remote_app)
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return FALSE;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
|
2014-11-12 06:27:33 +03:00
|
|
|
|
switch (appWindow->local_move.state)
|
2011-08-18 09:16:49 +04:00
|
|
|
|
{
|
2011-12-07 03:42:58 +04:00
|
|
|
|
case LMS_NOT_ACTIVE:
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* No local move in progress, nothing to do */
|
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
/* Prevent Configure from happening during indeterminant state of Horz or Vert Max only
|
|
|
|
|
*/
|
2016-07-19 17:15:38 +03:00
|
|
|
|
if ((event->type == ConfigureNotify) && appWindow->rail_ignore_configure)
|
|
|
|
|
{
|
|
|
|
|
appWindow->rail_ignore_configure = FALSE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2012-08-04 02:35:17 +04:00
|
|
|
|
|
2011-12-07 03:42:58 +04:00
|
|
|
|
break;
|
2012-11-21 04:34:52 +04:00
|
|
|
|
|
2011-12-07 03:42:58 +04:00
|
|
|
|
case LMS_STARTING:
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
|
/* Local move initiated by RDP server, but we have not yet seen any updates from the X
|
|
|
|
|
* server */
|
2014-11-12 06:27:33 +03:00
|
|
|
|
switch (event->type)
|
2011-12-03 02:51:30 +04:00
|
|
|
|
{
|
2011-12-07 03:42:58 +04:00
|
|
|
|
case ConfigureNotify:
|
2019-11-06 17:24:51 +03:00
|
|
|
|
/* Starting to see move events from the X server. Local move is now in progress.
|
|
|
|
|
*/
|
2014-11-12 06:27:33 +03:00
|
|
|
|
appWindow->local_move.state = LMS_ACTIVE;
|
2019-11-06 17:24:51 +03:00
|
|
|
|
/* Allow these events to be processed during move to keep our state up to date.
|
|
|
|
|
*/
|
2011-12-07 03:42:58 +04:00
|
|
|
|
break;
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2011-12-03 02:51:30 +04:00
|
|
|
|
case ButtonPress:
|
|
|
|
|
case ButtonRelease:
|
|
|
|
|
case KeyPress:
|
|
|
|
|
case KeyRelease:
|
|
|
|
|
case UnmapNotify:
|
2016-07-19 17:15:38 +03:00
|
|
|
|
/*
|
|
|
|
|
* A button release event means the X window server did not grab the
|
|
|
|
|
* mouse before the user released it. In this case we must cancel the
|
|
|
|
|
* local move. The event will be processed below as normal, below.
|
|
|
|
|
*/
|
|
|
|
|
break;
|
|
|
|
|
|
2011-12-03 02:51:30 +04:00
|
|
|
|
case VisibilityNotify:
|
2011-12-07 03:42:58 +04:00
|
|
|
|
case PropertyNotify:
|
2011-12-10 00:25:56 +04:00
|
|
|
|
case Expose:
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Allow these events to pass */
|
2011-12-10 00:25:56 +04:00
|
|
|
|
break;
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2011-12-07 03:42:58 +04:00
|
|
|
|
default:
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Eat any other events */
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-12-07 03:42:58 +04:00
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2011-12-07 03:42:58 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LMS_ACTIVE:
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Local move is in progress */
|
2014-11-12 06:27:33 +03:00
|
|
|
|
switch (event->type)
|
2011-12-07 03:42:58 +04:00
|
|
|
|
{
|
2011-12-03 02:51:30 +04:00
|
|
|
|
case ConfigureNotify:
|
2011-12-07 03:42:58 +04:00
|
|
|
|
case VisibilityNotify:
|
2011-12-03 02:51:30 +04:00
|
|
|
|
case PropertyNotify:
|
2011-12-10 00:25:56 +04:00
|
|
|
|
case Expose:
|
2012-08-04 02:35:17 +04:00
|
|
|
|
case GravityNotify:
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Keep us up to date on position */
|
2011-12-03 02:51:30 +04:00
|
|
|
|
break;
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2011-12-03 02:51:30 +04:00
|
|
|
|
default:
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Any other event terminates move */
|
2014-11-12 06:27:33 +03:00
|
|
|
|
xf_rail_end_local_move(xfc, appWindow);
|
2011-12-07 03:42:58 +04:00
|
|
|
|
break;
|
2011-12-03 02:51:30 +04:00
|
|
|
|
}
|
2016-07-19 17:15:38 +03:00
|
|
|
|
|
2011-12-07 03:42:58 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LMS_TERMINATING:
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Already sent RDP end move to server. Allow events to pass. */
|
2011-12-07 03:42:58 +04:00
|
|
|
|
break;
|
2014-12-01 13:56:44 +03:00
|
|
|
|
}
|
2011-12-07 03:42:58 +04:00
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return FALSE;
|
2011-12-07 03:42:58 +04:00
|
|
|
|
}
|
2019-05-08 16:36:20 +03:00
|
|
|
|
|
2020-02-27 11:02:41 +03:00
|
|
|
|
BOOL xf_event_process(freerdp* instance, const XEvent* event)
|
2011-12-07 03:42:58 +04:00
|
|
|
|
{
|
2012-10-09 10:38:39 +04:00
|
|
|
|
BOOL status = TRUE;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
|
|
|
|
|
WINPR_ASSERT(instance);
|
|
|
|
|
WINPR_ASSERT(event);
|
|
|
|
|
|
2023-06-05 13:16:57 +03:00
|
|
|
|
xfContext* xfc = (xfContext*)instance->context;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(xfc);
|
|
|
|
|
|
2023-06-05 13:16:57 +03:00
|
|
|
|
rdpSettings* settings = xfc->common.context.settings;
|
2022-01-19 11:27:39 +03:00
|
|
|
|
WINPR_ASSERT(settings);
|
2011-12-07 03:42:58 +04:00
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
if (xfc->remote_app)
|
2011-12-07 03:42:58 +04:00
|
|
|
|
{
|
2022-05-19 12:08:04 +03:00
|
|
|
|
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window);
|
2012-11-21 04:34:52 +04:00
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (appWindow)
|
2011-12-07 03:42:58 +04:00
|
|
|
|
{
|
2012-11-21 04:34:52 +04:00
|
|
|
|
/* Update "current" window for cursor change orders */
|
2014-11-13 00:42:32 +03:00
|
|
|
|
xfc->appWindow = appWindow;
|
2011-12-07 03:42:58 +04:00
|
|
|
|
|
2014-11-13 00:42:32 +03:00
|
|
|
|
if (xf_event_suppress_events(xfc, appWindow, event))
|
2012-10-09 10:31:28 +04:00
|
|
|
|
return TRUE;
|
2011-12-03 02:51:30 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-09-03 20:50:26 +04:00
|
|
|
|
|
2018-12-10 17:41:20 +03:00
|
|
|
|
if (xfc->window)
|
2018-09-18 22:25:51 +03:00
|
|
|
|
{
|
2022-10-03 14:34:59 +03:00
|
|
|
|
xfFloatbar* floatbar = xfc->window->floatbar;
|
|
|
|
|
if (xf_floatbar_check_event(floatbar, event))
|
2018-12-10 17:41:20 +03:00
|
|
|
|
{
|
2022-10-03 14:34:59 +03:00
|
|
|
|
xf_floatbar_event_process(floatbar, event);
|
2018-12-10 17:41:20 +03:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2022-10-03 14:34:59 +03:00
|
|
|
|
|
|
|
|
|
if (xf_floatbar_is_locked(floatbar))
|
|
|
|
|
return TRUE;
|
2018-09-18 22:25:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-23 01:12:50 +04:00
|
|
|
|
xf_event_execute_action_script(xfc, event);
|
|
|
|
|
|
2011-08-19 19:12:30 +04:00
|
|
|
|
if (event->type != MotionNotify)
|
2018-01-24 18:26:27 +03:00
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
|
DEBUG_X11("%s Event(%d): wnd=0x%08lX", x11_event_string(event->type), event->type,
|
|
|
|
|
(unsigned long)event->xany.window);
|
2018-01-24 18:26:27 +03:00
|
|
|
|
}
|
2011-08-19 19:12:30 +04:00
|
|
|
|
|
2011-08-07 21:41:54 +04:00
|
|
|
|
switch (event->type)
|
|
|
|
|
{
|
|
|
|
|
case Expose:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_Expose(xfc, &event->xexpose, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case VisibilityNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_VisibilityNotify(xfc, &event->xvisibility, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MotionNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_MotionNotify(xfc, &event->xmotion, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
2014-11-12 06:27:33 +03:00
|
|
|
|
|
2011-08-07 21:41:54 +04:00
|
|
|
|
case ButtonPress:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_ButtonPress(xfc, &event->xbutton, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ButtonRelease:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_ButtonRelease(xfc, &event->xbutton, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case KeyPress:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_KeyPress(xfc, &event->xkey, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case KeyRelease:
|
2022-12-12 12:14:21 +03:00
|
|
|
|
status = xf_event_KeyReleaseOrIgnore(xfc, &event->xkey, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FocusIn:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_FocusIn(xfc, &event->xfocus, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case FocusOut:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_FocusOut(xfc, &event->xfocus, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case EnterNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_EnterNotify(xfc, &event->xcrossing, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LeaveNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_LeaveNotify(xfc, &event->xcrossing, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NoExpose:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case GraphicsExpose:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ConfigureNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_ConfigureNotify(xfc, &event->xconfigure, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MapNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_MapNotify(xfc, &event->xmap, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
2011-11-29 01:50:08 +04:00
|
|
|
|
case UnmapNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_UnmapNotify(xfc, &event->xunmap, xfc->remote_app);
|
2011-11-29 01:50:08 +04:00
|
|
|
|
break;
|
|
|
|
|
|
2011-08-07 21:41:54 +04:00
|
|
|
|
case ReparentNotify:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MappingNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_MappingNotify(xfc, &event->xmapping, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ClientMessage:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_ClientMessage(xfc, &event->xclient, xfc->remote_app);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
break;
|
|
|
|
|
|
2011-09-23 07:37:17 +04:00
|
|
|
|
case PropertyNotify:
|
2020-02-27 11:02:41 +03:00
|
|
|
|
status = xf_event_PropertyNotify(xfc, &event->xproperty, xfc->remote_app);
|
2011-09-23 07:37:17 +04:00
|
|
|
|
break;
|
2017-11-29 12:26:04 +03:00
|
|
|
|
|
|
|
|
|
default:
|
2023-10-13 10:48:44 +03:00
|
|
|
|
if (freerdp_settings_get_bool(settings, FreeRDP_SupportDisplayControl))
|
2017-11-29 12:26:04 +03:00
|
|
|
|
xf_disp_handle_xevent(xfc, event);
|
2017-12-21 13:04:50 +03:00
|
|
|
|
|
2017-11-29 12:26:04 +03:00
|
|
|
|
break;
|
2011-08-07 21:41:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 14:34:59 +03:00
|
|
|
|
xfWindow* window = xfc->window;
|
|
|
|
|
xfFloatbar* floatbar = NULL;
|
|
|
|
|
if (window)
|
|
|
|
|
floatbar = window->floatbar;
|
|
|
|
|
|
2016-08-18 21:14:52 +03:00
|
|
|
|
xf_cliprdr_handle_xevent(xfc, event);
|
2022-10-03 14:34:59 +03:00
|
|
|
|
if (!xf_floatbar_check_event(floatbar, event) && !xf_floatbar_is_locked(floatbar))
|
|
|
|
|
xf_input_handle_event(xfc, event);
|
|
|
|
|
|
2013-06-13 02:57:25 +04:00
|
|
|
|
XSync(xfc->display, FALSE);
|
2011-08-07 21:41:54 +04:00
|
|
|
|
return status;
|
|
|
|
|
}
|
2022-01-19 15:29:26 +03:00
|
|
|
|
|
|
|
|
|
BOOL xf_generic_RawButtonEvent(xfContext* xfc, int button, BOOL app, BOOL down)
|
|
|
|
|
{
|
|
|
|
|
UINT16 flags = 0;
|
|
|
|
|
|
|
|
|
|
if (app)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2024-01-30 12:25:38 +03:00
|
|
|
|
for (size_t i = 0; i < ARRAYSIZE(xfc->button_map); i++)
|
2022-01-19 15:29:26 +03:00
|
|
|
|
{
|
|
|
|
|
const button_map* cur = &xfc->button_map[i];
|
|
|
|
|
|
|
|
|
|
if (cur->button == button)
|
|
|
|
|
{
|
|
|
|
|
flags = cur->flags;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags != 0)
|
|
|
|
|
{
|
|
|
|
|
if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
|
|
|
|
|
{
|
|
|
|
|
if (down)
|
|
|
|
|
freerdp_client_send_wheel_event(&xfc->common, flags);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
BOOL extended = FALSE;
|
|
|
|
|
|
|
|
|
|
if (flags & (PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2))
|
|
|
|
|
{
|
|
|
|
|
extended = TRUE;
|
|
|
|
|
|
|
|
|
|
if (down)
|
|
|
|
|
flags |= PTR_XFLAGS_DOWN;
|
|
|
|
|
}
|
|
|
|
|
else if (flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))
|
|
|
|
|
{
|
|
|
|
|
if (down)
|
|
|
|
|
flags |= PTR_FLAGS_DOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (extended)
|
|
|
|
|
freerdp_client_send_extended_button_event(&xfc->common, TRUE, flags, 0, 0);
|
|
|
|
|
else
|
|
|
|
|
freerdp_client_send_button_event(&xfc->common, TRUE, flags, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|