From 169d358734509e82663a0d6a0085ae726d439d8e Mon Sep 17 00:00:00 2001
From: Armin Novak <armin.novak@thincast.com>
Date: Mon, 9 Feb 2026 16:58:20 +0100
Subject: [PATCH] [client,x11] destroy XImage on window unmap

When unmapping rails window destroy the cached XImage of appWindow
---
 client/X11/xf_gfx.c    | 24 ++++++++++++++++++++++++
 client/X11/xf_window.c |  2 +-
 client/X11/xf_window.h |  6 +++++-
 3 files changed, 30 insertions(+), 2 deletions(-)

Index: FreeRDP-3.10.3/client/X11/xf_gfx.c
===================================================================
--- FreeRDP-3.10.3.orig/client/X11/xf_gfx.c
+++ FreeRDP-3.10.3/client/X11/xf_gfx.c
@@ -26,6 +26,7 @@
 #include <freerdp/log.h>
 #include "xf_gfx.h"
 #include "xf_rail.h"
+#include "xf_window.h"
 
 #include <X11/Xutil.h>
 
@@ -420,6 +421,27 @@ static UINT xf_DeleteSurface(RdpgfxClien
 	return status;
 }
 
+static UINT xf_UnmapWindowForSurface(RdpgfxClientContext* context, UINT64 windowID)
+{
+	WINPR_ASSERT(context);
+	rdpGdi* gdi = (rdpGdi*)context->custom;
+	WINPR_ASSERT(gdi);
+
+	xfContext* xfc = (xfContext*)gdi->context;
+	WINPR_ASSERT(gdi->context);
+
+	if (freerdp_settings_get_bool(gdi->context->settings, FreeRDP_RemoteApplicationMode))
+	{
+		xfAppWindow* appWindow = xf_rail_get_window(xfc, windowID);
+		if (appWindow)
+			xf_AppWindowDestroyImage(appWindow);
+		xf_rail_return_window(appWindow);
+	}
+
+	WLog_WARN(TAG, "function not implemented");
+	return CHANNEL_RC_OK;
+}
+
 static UINT xf_UpdateWindowFromSurface(RdpgfxClientContext* context, gdiGfxSurface* surface)
 {
 	WINPR_ASSERT(context);
@@ -458,7 +480,9 @@ void xf_graphics_pipeline_init(xfContext
 		gfx->CreateSurface = xf_CreateSurface;
 		gfx->DeleteSurface = xf_DeleteSurface;
 	}
+
 	gfx->UpdateWindowFromSurface = xf_UpdateWindowFromSurface;
+	gfx->UnmapWindowForSurface = xf_UnmapWindowForSurface;
 }
 
 void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
Index: FreeRDP-3.10.3/client/X11/xf_window.c
===================================================================
--- FreeRDP-3.10.3.orig/client/X11/xf_window.c
+++ FreeRDP-3.10.3/client/X11/xf_window.c
@@ -1356,7 +1356,7 @@ void xf_UpdateWindowArea(xfContext* xfc,
 	xf_unlock_x11(xfc);
 }
 
-static void xf_AppWindowDestroyImage(xfAppWindow* appWindow)
+void xf_AppWindowDestroyImage(xfAppWindow* appWindow)
 {
 	WINPR_ASSERT(appWindow);
 	if (appWindow->image)
Index: FreeRDP-3.10.3/client/X11/xf_window.h
===================================================================
--- FreeRDP-3.10.3.orig/client/X11/xf_window.h
+++ FreeRDP-3.10.3/client/X11/xf_window.h
@@ -167,9 +167,12 @@ void xf_SetWindowMinimized(xfContext* xf
 void xf_SetWindowDecorations(xfContext* xfc, Window window, BOOL show);
 void xf_SetWindowUnlisted(xfContext* xfc, Window window);
 
+void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window);
+
+WINPR_ATTR_MALLOC(xf_DestroyDesktopWindow, 2)
 xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height);
+
 void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int height);
-void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window);
 
 Window xf_CreateDummyWindow(xfContext* xfc);
 void xf_DestroyDummyWindow(xfContext* xfc, Window window);
@@ -196,6 +199,7 @@ void xf_UpdateWindowArea(xfContext* xfc,
                          int height);
 UINT xf_AppUpdateWindowFromSurface(xfContext* xfc, gdiGfxSurface* surface);
 
+void xf_AppWindowDestroyImage(xfAppWindow* appWindow);
 void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow);
 void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow, int maxWidth, int maxHeight,
                             int maxPosX, int maxPosY, int minTrackWidth, int minTrackHeight,
