Compare commits
2 Commits
9a5ecc094b
...
bed99acf27
| Author | SHA1 | Date | |
|---|---|---|---|
| bed99acf27 | |||
| f88d1a7d44 |
@@ -0,0 +1,98 @@
|
|||||||
|
FROM ubuntu:24.04 AS builder
|
||||||
|
|
||||||
|
# Pilot build against the xrdp/xorgxrdp "devel" branches (pre-0.11).
|
||||||
|
# This is NOT the same codebase as Dockerfile (v0.10.x) - devel is ~787
|
||||||
|
# commits / ~300 files ahead of v0.10.6.1, and xorgxrdp's devel branch has
|
||||||
|
# moved together with it (137 commits / 81 files ahead of v0.10.5). Track
|
||||||
|
# them as a pair; don't mix a devel xrdp with a tagged xorgxrdp or vice versa.
|
||||||
|
#
|
||||||
|
# Known deltas from the v0.10.x build baked into this file:
|
||||||
|
# - New hard dep: libxkbfile-dev (unconditional XKB header check)
|
||||||
|
# - --enable-ibus now also needs libibus-1.0-dev + libglib2.0-dev
|
||||||
|
# - NVENC support moved into a new helper binary (xrdp-accel-assist) that
|
||||||
|
# vendors its own NVENC API headers, so the nv-codec-headers clone/symlink
|
||||||
|
# step from the stable Dockerfile is gone - it's dead weight on devel.
|
||||||
|
# - --enable-accel is auto-derived from --enable-nvenc in configure.ac, so
|
||||||
|
# no new configure flag is needed to get xrdp-accel-assist built.
|
||||||
|
#
|
||||||
|
# devel is a floating branch, not a tag: Docker layer caching means a
|
||||||
|
# `docker build` with no cache change will keep reusing an old clone.
|
||||||
|
# Always pass --no-cache (or otherwise bust the git-clone layers) to actually
|
||||||
|
# pick up new commits on each pilot run.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# docker build --no-cache -f Dockerfile.devel -t xrdp-builder:devel .
|
||||||
|
# docker run --rm -v $(pwd)/packages:/output xrdp-builder:devel
|
||||||
|
|
||||||
|
# Get build and target platform info
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG TARGETVARIANT
|
||||||
|
|
||||||
|
# Build arguments for versions - devel branches by default for this pilot
|
||||||
|
ARG XRDP_VERSION=devel
|
||||||
|
ARG XORGXRDP_VERSION=devel
|
||||||
|
ARG PW_MODULE_XRDP_VERSION=devel
|
||||||
|
|
||||||
|
# Prevent interactive prompts during build
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
git \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
libtool \
|
||||||
|
pkg-config \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
make \
|
||||||
|
libssl-dev \
|
||||||
|
libpam0g-dev \
|
||||||
|
libx11-dev \
|
||||||
|
libxfixes-dev \
|
||||||
|
libxrandr-dev \
|
||||||
|
libxkbfile-dev \
|
||||||
|
nasm \
|
||||||
|
xsltproc \
|
||||||
|
flex \
|
||||||
|
bison \
|
||||||
|
libxml2-dev \
|
||||||
|
dpkg-dev \
|
||||||
|
libcap-dev \
|
||||||
|
libfuse3-dev \
|
||||||
|
libpixman-1-dev \
|
||||||
|
intltool \
|
||||||
|
xserver-xorg-dev \
|
||||||
|
xserver-xorg-core \
|
||||||
|
libconfig-dev \
|
||||||
|
libjpeg-dev \
|
||||||
|
wget \
|
||||||
|
libturbojpeg-dev \
|
||||||
|
libx264-dev \
|
||||||
|
libpulse-dev \
|
||||||
|
libopus-dev \
|
||||||
|
libibus-1.0-dev \
|
||||||
|
libglib2.0-dev \
|
||||||
|
ca-certificates \
|
||||||
|
libepoxy-dev \
|
||||||
|
libasound2-dev \
|
||||||
|
libdrm-dev \
|
||||||
|
libglvnd-dev \
|
||||||
|
libgbm-dev \
|
||||||
|
pipewire \
|
||||||
|
libpipewire-0.3-dev \
|
||||||
|
libspa-0.2-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN apt -get update && apt-get install -y \
|
||||||
|
nano \
|
||||||
|
xvfb xdotool \
|
||||||
|
ibus dbus-x11 \
|
||||||
|
openbox \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Match the workspaceFolder set in devcontainer.json
|
||||||
|
WORKDIR /workspace
|
||||||
|
CMD [ "tail", "-f", "/dev/null" ]
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
|
||||||
|
"name": "XRDP",
|
||||||
|
"build": { "dockerfile": "Dockerfile" },
|
||||||
|
"workspaceFolder": "/workspace",
|
||||||
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
|
||||||
|
"remoteUser": "root",
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"source": "${localEnv:HOME}${localEnv:USERPROFILE}/.claude",
|
||||||
|
"target": "/root/.claude",
|
||||||
|
"type": "bind",
|
||||||
|
"consistency": "cached"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "${localEnv:HOME}${localEnv:USERPROFILE}/.gitconfig",
|
||||||
|
"target": "/root/.gitconfig",
|
||||||
|
"type": "bind",
|
||||||
|
"consistency": "cached"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "${localEnv:HOME}${localEnv:USERPROFILE}/.git-credentials",
|
||||||
|
"target": "/root/.git-credentials",
|
||||||
|
"type": "bind",
|
||||||
|
"consistency": "cached"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
+82
-14
@@ -30,7 +30,7 @@
|
|||||||
static IBusBus *bus;
|
static IBusBus *bus;
|
||||||
static IBusEngine *g_engine;
|
static IBusEngine *g_engine;
|
||||||
/* This is the engine name enabled before unicode engine enabled */
|
/* This is the engine name enabled before unicode engine enabled */
|
||||||
static const gchar *last_input_name;
|
static gchar *last_input_name;
|
||||||
static int id = 0;
|
static int id = 0;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -39,27 +39,38 @@ xrdp_input_enable(void)
|
|||||||
IBusEngineDesc *desc;
|
IBusEngineDesc *desc;
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
|
|
||||||
if (last_input_name)
|
|
||||||
{
|
|
||||||
/* already enabled */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bus)
|
if (!bus)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: input method switched failed, ibus not connected");
|
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: input method switched failed, ibus not connected");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Re-check the current global engine on every call rather than
|
||||||
|
* trusting a one-time flag: ibus (particularly with
|
||||||
|
* use_global_engine disabled, which is common) can silently swap
|
||||||
|
* the active engine back to the user's own IME between calls, and
|
||||||
|
* we need to notice that and reassert XrdpIme rather than keep
|
||||||
|
* committing text to an engine that's no longer active. */
|
||||||
desc = ibus_bus_get_global_engine(bus);
|
desc = ibus_bus_get_global_engine(bus);
|
||||||
name = ibus_engine_desc_get_name (desc);
|
name = desc ? ibus_engine_desc_get_name(desc) : NULL;
|
||||||
if (!g_ascii_strcasecmp(name, "XrdpIme"))
|
if (name && !g_ascii_strcasecmp(name, "XrdpIme"))
|
||||||
{
|
{
|
||||||
|
g_object_unref(desc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remember user's input method, will switch back when disconnect */
|
if (!last_input_name && name)
|
||||||
last_input_name = name;
|
{
|
||||||
|
/* remember user's original input method (first time only), will
|
||||||
|
* switch back when disconnected. Copy the name out since it's
|
||||||
|
* owned by desc, which we're about to unref. */
|
||||||
|
last_input_name = g_strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc)
|
||||||
|
{
|
||||||
|
g_object_unref(desc);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ibus_bus_set_global_engine(bus, "XrdpIme"))
|
if (!ibus_bus_set_global_engine(bus, "XrdpIme"))
|
||||||
{
|
{
|
||||||
@@ -105,8 +116,25 @@ static void
|
|||||||
xrdp_input_ibus_disconnect(IBusEngine *engine)
|
xrdp_input_ibus_disconnect(IBusEngine *engine)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled");
|
LOG(LOG_LEVEL_INFO, "xrdp_ibus_engine_disable: IM disabled");
|
||||||
|
if (g_engine)
|
||||||
|
{
|
||||||
g_object_unref(g_engine);
|
g_object_unref(g_engine);
|
||||||
|
g_engine = NULL;
|
||||||
|
}
|
||||||
|
if (bus)
|
||||||
|
{
|
||||||
g_object_unref(bus);
|
g_object_unref(bus);
|
||||||
|
bus = NULL;
|
||||||
|
}
|
||||||
|
g_free(last_input_name);
|
||||||
|
last_input_name = NULL;
|
||||||
|
|
||||||
|
/* ibus_main()/ibus_quit() operate on a single loop shared by the
|
||||||
|
* whole process, not one per IBusBus. Without this, the
|
||||||
|
* xrdp_input_main_loop thread for this (now dead) connection stays
|
||||||
|
* blocked in ibus_main() forever, and a fresh thread + loop gets
|
||||||
|
* started on the next reconnect - leaking a thread per reconnect. */
|
||||||
|
ibus_quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -125,12 +153,13 @@ xrdp_input_ibus_create_engine(IBusFactory *factory,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
IBusEngine *engine;
|
IBusEngine *engine;
|
||||||
gchar *path = g_strdup_printf("/org/freedesktop/IBus/Engine/%i", 1);
|
gchar *path = g_strdup_printf("/org/freedesktop/IBus/Engine/%i", ++id);
|
||||||
engine = ibus_engine_new(engine_name,
|
engine = ibus_engine_new(engine_name,
|
||||||
path,
|
path,
|
||||||
ibus_bus_get_connection(bus));
|
ibus_bus_get_connection(bus));
|
||||||
|
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_input_ibus_create_engine: Creating IM Engine with name:%s and id:%d\n", engine_name, ++id);
|
LOG(LOG_LEVEL_DEBUG, "xrdp_input_ibus_create_engine: Creating IM Engine with name:%s and id:%d\n", engine_name, id);
|
||||||
|
g_free(path);
|
||||||
|
|
||||||
g_signal_connect(engine, "process-key-event", G_CALLBACK(engine_process_key_event_cb), NULL);
|
g_signal_connect(engine, "process-key-event", G_CALLBACK(engine_process_key_event_cb), NULL);
|
||||||
g_signal_connect(engine, "enable", G_CALLBACK(xrdp_input_ibus_engine_enable), NULL);
|
g_signal_connect(engine, "enable", G_CALLBACK(xrdp_input_ibus_engine_enable), NULL);
|
||||||
@@ -192,15 +221,22 @@ int
|
|||||||
xrdp_input_unicode_destroy(void)
|
xrdp_input_unicode_destroy(void)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_input_unicode_destory: ibus input is under destory");
|
LOG(LOG_LEVEL_DEBUG, "xrdp_input_unicode_destory: ibus input is under destory");
|
||||||
if (last_input_name)
|
if (last_input_name && bus)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO, "xrdp_input_unicode_destory: ibus engine rolling back to origin: %s", last_input_name);
|
LOG(LOG_LEVEL_INFO, "xrdp_input_unicode_destory: ibus engine rolling back to origin: %s", last_input_name);
|
||||||
ibus_bus_set_global_engine(bus, last_input_name);
|
ibus_bus_set_global_engine(bus, last_input_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_engine)
|
||||||
|
{
|
||||||
g_object_unref(g_engine);
|
g_object_unref(g_engine);
|
||||||
|
}
|
||||||
|
if (bus)
|
||||||
|
{
|
||||||
g_object_unref(bus);
|
g_object_unref(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(last_input_name);
|
||||||
last_input_name = NULL;
|
last_input_name = NULL;
|
||||||
bus = NULL;
|
bus = NULL;
|
||||||
g_engine = NULL;
|
g_engine = NULL;
|
||||||
@@ -212,12 +248,39 @@ int
|
|||||||
xrdp_input_unicode_init(void)
|
xrdp_input_unicode_init(void)
|
||||||
{
|
{
|
||||||
if (bus)
|
if (bus)
|
||||||
|
{
|
||||||
|
if (ibus_bus_is_connected(bus))
|
||||||
{
|
{
|
||||||
/* Already initialized, just re-enable it */
|
/* Already initialized, just re-enable it */
|
||||||
xrdp_input_enable();
|
xrdp_input_enable();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The bus is stale (e.g. the ibus daemon restarted and left a
|
||||||
|
* dead connection behind). Tear it down so we reconnect below
|
||||||
|
* instead of operating on a dead connection. */
|
||||||
|
LOG(LOG_LEVEL_WARNING,
|
||||||
|
"xrdp_ibus_init: existing iBus connection is stale, reconnecting");
|
||||||
|
if (g_engine)
|
||||||
|
{
|
||||||
|
g_object_unref(g_engine);
|
||||||
|
g_engine = NULL;
|
||||||
|
}
|
||||||
|
g_object_unref(bus);
|
||||||
|
bus = NULL;
|
||||||
|
g_free(last_input_name);
|
||||||
|
last_input_name = NULL;
|
||||||
|
|
||||||
|
/* Belt-and-suspenders: normally the "disconnected" signal handler
|
||||||
|
* (xrdp_input_ibus_disconnect) already called this when the bus
|
||||||
|
* dropped. But a stale connection can be detected here without
|
||||||
|
* that signal ever having fired, and ibus_main()/ibus_quit() are
|
||||||
|
* process-global rather than per-bus, so make sure the old
|
||||||
|
* xrdp_input_main_loop thread isn't left blocked in ibus_main()
|
||||||
|
* before we start a new one below. */
|
||||||
|
ibus_quit();
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait because the ibus daemon may not be ready on first login */
|
/* Wait because the ibus daemon may not be ready on first login */
|
||||||
const char *addr = ibus_get_address();
|
const char *addr = ibus_get_address();
|
||||||
unsigned int cnt = 0;
|
unsigned int cnt = 0;
|
||||||
@@ -242,6 +305,8 @@ xrdp_input_unicode_init(void)
|
|||||||
if (!ibus_bus_is_connected(bus))
|
if (!ibus_bus_is_connected(bus))
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: Connect to iBus failed");
|
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: Connect to iBus failed");
|
||||||
|
g_object_unref(bus);
|
||||||
|
bus = NULL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +316,9 @@ xrdp_input_unicode_init(void)
|
|||||||
|
|
||||||
if (!ibus_bus_get_global_engine(bus))
|
if (!ibus_bus_get_global_engine(bus))
|
||||||
{
|
{
|
||||||
|
/* The bus connection itself is fine (and is now owned by the
|
||||||
|
* ibus main loop thread we just started), so leave it in place
|
||||||
|
* rather than tearing it down here. */
|
||||||
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: failed to get origin global engine");
|
LOG(LOG_LEVEL_ERROR, "xrdp_ibus_init: failed to get origin global engine");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user