1
0
mirror of https://github.com/KDE/krfb synced 2026-07-02 00:01:18 -07:00

Compare commits

...

56 Commits

Author SHA1 Message Date
l10n daemon script
367ad54921 GIT_SILENT Sync po/docbooks with svn 2023-07-05 04:41:42 +00:00
l10n daemon script
cca39f6f87 GIT_SILENT Sync po/docbooks with svn 2023-07-04 05:08:17 +00:00
Heiko Becker
bd90236e94 GIT_SILENT Update Appstream for new release 2023-06-30 00:53:40 +02:00
Heiko Becker
f8d5f90c4d GIT_SILENT Upgrade release service version to 23.04.3. 2023-06-30 00:01:37 +02:00
l10n daemon script
4c25bfdf69 GIT_SILENT Sync po/docbooks with svn 2023-06-20 04:49:59 +00:00
l10n daemon script
e9ef26a7b0 GIT_SILENT Sync po/docbooks with svn 2023-06-18 05:17:20 +00:00
Heiko Becker
474644d6cb GIT_SILENT Update Appstream for new release 2023-06-02 21:28:53 +02:00
Heiko Becker
27ad545370 GIT_SILENT Upgrade release service version to 23.04.2. 2023-06-02 20:33:29 +02:00
l10n daemon script
e8a0fe0ba4 GIT_SILENT Sync po/docbooks with svn 2023-05-30 04:28:16 +00:00
l10n daemon script
606c9d6c35 GIT_SILENT Sync po/docbooks with svn 2023-05-24 03:27:05 +00:00
l10n daemon script
3cc822702c GIT_SILENT Sync po/docbooks with svn 2023-05-23 05:02:05 +00:00
Heiko Becker
8b16492e33 GIT_SILENT Update Appstream for new release 2023-05-06 10:53:20 +02:00
Heiko Becker
e7ba0ec8e7 GIT_SILENT Upgrade release service version to 23.04.1. 2023-05-06 09:53:20 +02:00
l10n daemon script
7609f2433b GIT_SILENT made messages (after extraction) 2023-05-02 02:51:06 +00:00
l10n daemon script
6e3e24ac36 GIT_SILENT Sync po/docbooks with svn 2023-05-01 04:03:13 +00:00
l10n daemon script
ae2e2f2b24 SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-05-01 03:51:56 +00:00
l10n daemon script
6ba47bb41b GIT_SILENT Sync po/docbooks with svn 2023-04-30 05:22:02 +00:00
l10n daemon script
fcd75a0fec GIT_SILENT Sync po/docbooks with svn 2023-04-23 05:17:45 +00:00
l10n daemon script
0292e57409 GIT_SILENT Sync po/docbooks with svn 2023-04-17 05:04:51 +00:00
Heiko Becker
41b502ac64 GIT_SILENT Update Appstream for new release 2023-04-12 18:47:19 +02:00
Heiko Becker
2ab6976823 GIT_SILENT Upgrade release service version to 23.04.0. 2023-04-12 17:53:15 +02:00
l10n daemon script
929b1be202 GIT_SILENT Sync po/docbooks with svn 2023-04-11 04:30:14 +00:00
Albert Astals Cid
458f8aeabd GIT_SILENT Upgrade release service version to 23.03.90. 2023-03-30 22:03:08 +02:00
l10n daemon script
9afb064b8a GIT_SILENT Sync po/docbooks with svn 2023-03-28 04:34:32 +00:00
l10n daemon script
68d7b7ddfa GIT_SILENT Sync po/docbooks with svn 2023-03-27 05:38:05 +00:00
l10n daemon script
7da2b98bc5 GIT_SILENT Sync po/docbooks with svn 2023-03-12 06:15:44 +00:00
Albert Astals Cid
8613cd080f GIT_SILENT Upgrade release service version to 23.03.80. 2023-03-10 20:46:39 +01:00
l10n daemon script
c92c4108b0 GIT_SILENT Sync po/docbooks with svn 2023-03-05 02:35:04 +00:00
l10n daemon script
854bc782a0 GIT_SILENT Sync po/docbooks with svn 2023-02-25 03:04:09 +00:00
Heiko Becker
20c787931c GIT_SILENT Update Appstream for new release
(cherry picked from commit 5a6381537c)
2023-02-24 21:44:10 +01:00
l10n daemon script
b740b6518e GIT_SILENT Sync po/docbooks with svn 2023-02-16 03:06:54 +00:00
l10n daemon script
acc304fb94 GIT_SILENT Sync po/docbooks with svn 2023-02-13 02:13:33 +00:00
David Redondo
01c775f2e8 Hook up keyevents on Wayland 2023-02-09 13:50:35 +00:00
David Redondo
953cc4218b Encode supported platforms in the plugin metdata
This way we don't load pipewire on X, or xcb on Wayland regardless
if they are configured as preferred or not.
2023-02-09 07:54:39 +00:00
David Redondo
e865b187a2 Fallback to another plugin if preferred one doesn't work
I assume this is what the code wants to do instead of looping
through all the plugins just to find a specific one and just
giving up it it fails.
2023-02-09 07:54:39 +00:00
l10n daemon script
86fe436fd0 GIT_SILENT Sync po/docbooks with svn 2023-02-08 03:04:49 +00:00
Heiko Becker
21b2361c9f GIT_SILENT Update Appstream for new release
(cherry picked from commit f21499f023)
2023-01-30 00:26:22 +01:00
l10n daemon script
09e6984b58 GIT_SILENT Sync po/docbooks with svn 2023-01-22 02:19:18 +00:00
l10n daemon script
df52969067 GIT_SILENT Sync po/docbooks with svn 2023-01-19 02:25:46 +00:00
l10n daemon script
e0ec84ef65 GIT_SILENT Sync po/docbooks with svn 2023-01-13 02:54:17 +00:00
l10n daemon script
336af069cf SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2023-01-13 02:01:54 +00:00
l10n daemon script
83654bd33d GIT_SILENT made messages (after extraction) 2023-01-13 00:56:14 +00:00
Aleix Pol i Gonzalez
4db9c65083 pipewire: Port to use KPipeWire
Rather than using pipewire directly, we can use this framework which
allows us to share a bunch of code with Plasma.
2023-01-12 13:48:46 +00:00
l10n daemon script
4f924c2306 GIT_SILENT Sync po/docbooks with svn 2023-01-12 02:15:49 +00:00
l10n daemon script
d7cafa3dfc GIT_SILENT Sync po/docbooks with svn 2023-01-07 02:50:15 +00:00
l10n daemon script
2e06f4f370 GIT_SILENT Sync po/docbooks with svn 2023-01-06 02:39:19 +00:00
l10n daemon script
0ec2f9f01b GIT_SILENT Sync po/docbooks with svn 2023-01-04 02:45:35 +00:00
l10n daemon script
43b91cc93a GIT_SILENT Sync po/docbooks with svn 2023-01-03 02:59:42 +00:00
Albert Astals Cid
e805ce0e55 GIT_SILENT Update Appstream for new release
(cherry picked from commit ebbd8b982c)
2023-01-03 00:55:19 +01:00
l10n daemon script
462c7295d2 GIT_SILENT Sync po/docbooks with svn 2022-12-25 02:44:30 +00:00
l10n daemon script
f97f9a79fd GIT_SILENT Sync po/docbooks with svn 2022-12-14 02:43:13 +00:00
l10n daemon script
ab13b9a16f GIT_SILENT Sync po/docbooks with svn 2022-12-02 02:54:13 +00:00
Heiko Becker
fba34da8da GIT_SILENT Update Appstream for new release
(cherry picked from commit 97ba8f617e)
2022-11-30 01:35:56 +01:00
l10n daemon script
21763fe544 GIT_SILENT Sync po/docbooks with svn 2022-11-20 02:33:54 +00:00
l10n daemon script
9699e7ad2a GIT_SILENT Sync po/docbooks with svn 2022-11-07 02:34:26 +00:00
Albert Astals Cid
62da564888 GIT_SILENT Upgrade release service version to 23.03.70. 2022-11-05 21:47:53 +01:00
27 changed files with 311 additions and 734 deletions

View File

@@ -19,3 +19,4 @@ Dependencies:
'frameworks/kxmlgui': '@stable'
'frameworks/kwayland': '@stable'
'libraries/plasma-wayland-protocols': '@latest' # can be switched to @stable when 1.5.0 is released
'plasma/kpipewire': '@latest'

View File

@@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 3.16)
# KDE Application Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "22")
set (RELEASE_SERVICE_VERSION_MINOR "11")
set (RELEASE_SERVICE_VERSION_MICRO "70")
set (RELEASE_SERVICE_VERSION_MAJOR "23")
set (RELEASE_SERVICE_VERSION_MINOR "04")
set (RELEASE_SERVICE_VERSION_MICRO "3")
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(krfb VERSION ${RELEASE_SERVICE_VERSION})
@@ -73,6 +73,7 @@ find_package(LibVNCServer REQUIRED)
option(DISABLE_PIPEWIRE "Disable PipeWire support." OFF)
if(NOT DISABLE_PIPEWIRE)
find_package(KPipeWire REQUIRED)
pkg_check_modules(PipeWire IMPORTED_TARGET libpipewire-0.3)
endif()
add_feature_info(PipeWire PipeWire_FOUND "Required for pipewire screencast plugin")

View File

@@ -61,10 +61,8 @@ void EventData::init()
void XdpEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
{
// TODO: implement button handling
// both in FakeInput interface and here
Q_UNUSED(down)
Q_UNUSED(keySym)
const QDBusObjectPath sessionHandle = frameBuffer()->customProperty(QStringLiteral("session_handle")).value<QDBusObjectPath>();
data->dbusXdpRemoteDesktopService->NotifyKeyboardKeysym(sessionHandle, {}, keySym, down);
}
void XdpEventHandler::handlePointer(int buttonMask, int x, int y)

View File

@@ -49,6 +49,8 @@ target_link_libraries(krfb_framebuffer_pw
Wayland::Client
krfbprivate
PkgConfig::PipeWire
K::KPipeWire
K::KPipeWireDmaBuf
)
if (HAVE_DMA_BUF)

View File

@@ -0,0 +1,5 @@
{
"X-KDE-OnlyShowOnQtPlatforms": [
"wayland"
]
}

View File

@@ -42,9 +42,10 @@
#include "xdp_dbus_remotedesktop_interface.h"
#include "krfb_fb_pipewire_debug.h"
#include "screencasting.h"
#include <KPipeWire/PipeWireSourceStream>
#include <KPipeWire/DmaBufHandler>
#if HAVE_DMA_BUF
#include <fcntl.h>
#include <unistd.h>
#include <gbm.h>
@@ -114,47 +115,21 @@ public:
private:
friend class PWFrameBuffer;
static void onCoreError(void *data, uint32_t id, int seq, int res, const char *message);
static void onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format);
static void onStreamStateChanged(void *data, pw_stream_state old, pw_stream_state state, const char *error_message);
static void onStreamProcess(void *data);
void initDbus();
void initPw();
// dbus handling
void handleSessionCreated(quint32 &code, QVariantMap &results);
void handleDevicesSelected(quint32 &code, QVariantMap &results);
void handleSourcesSelected(quint32 &code, QVariantMap &results);
void handleRemoteDesktopStarted(quint32 &code, QVariantMap &results);
void handleSessionCreated(quint32 code, const QVariantMap &results);
void handleDevicesSelected(quint32 code, const QVariantMap &results);
void handleSourcesSelected(quint32 code, const QVariantMap &results);
void handleRemoteDesktopStarted(quint32 code, const QVariantMap &results);
void setVideoSize(const QSize &size);
// pw handling
pw_stream *createReceivingStream();
void handleFrame(pw_buffer *pwBuffer);
void handleFrame(const PipeWireFrame &frame);
// link to public interface
PWFrameBuffer *q;
// pipewire stuff
struct pw_context *pwContext = nullptr;
struct pw_core *pwCore = nullptr;
struct pw_stream *pwStream = nullptr;
struct pw_thread_loop *pwMainLoop = nullptr;
// wayland-like listeners
// ...of events that happen in pipewire server
spa_hook coreListener = {};
spa_hook streamListener = {};
// event handlers
pw_core_events pwCoreEvents = {};
pw_stream_events pwStreamEvents = {};
uint pwStreamNodeId = 0;
// negotiated video format
spa_video_info_raw *videoFormat = nullptr;
// requests a session from XDG Desktop Portal
// auto-generated and compiled from xdp_dbus_interface.xml file
QScopedPointer<OrgFreedesktopPortalScreenCastInterface> dbusXdpScreenCastService;
@@ -162,113 +137,24 @@ private:
// XDP screencast session handle
QDBusObjectPath sessionPath;
// Pipewire file descriptor
QDBusUnixFileDescriptor pipewireFd;
// screen geometry holder
QSize streamSize;
QSize videoSize;
// Allowed devices
uint devices = 0;
// sanity indicator
bool isValid = true;
QImage cursorTexture;
QPoint cursorPosition;
QPoint cursorHotspot;
#if HAVE_DMA_BUF
struct EGLStruct {
QList<QByteArray> extensions;
EGLDisplay display = EGL_NO_DISPLAY;
EGLContext context = EGL_NO_CONTEXT;
};
bool m_eglInitialized = false;
qint32 m_drmFd = 0; // for GBM buffer mmap
gbm_device *m_gbmDevice = nullptr; // for passed GBM buffer retrieval
EGLStruct m_egl;
#endif /* HAVE_DMA_BUF */
std::unique_ptr<PipeWireSourceStream> stream;
std::optional<PipeWireCursor> cursor;
DmaBufHandler m_dmabufHandler;
};
PWFrameBuffer::Private::Private(PWFrameBuffer *q) : q(q)
PWFrameBuffer::Private::Private(PWFrameBuffer *q)
: q(q)
, stream(new PipeWireSourceStream(q))
{
pwCoreEvents.version = PW_VERSION_CORE_EVENTS;
pwCoreEvents.error = &onCoreError;
pwStreamEvents.version = PW_VERSION_STREAM_EVENTS;
pwStreamEvents.state_changed = &onStreamStateChanged;
pwStreamEvents.param_changed = &onStreamParamChanged;
pwStreamEvents.process = &onStreamProcess;
#if HAVE_DMA_BUF
m_drmFd = open("/dev/dri/renderD128", O_RDWR);
if (m_drmFd < 0) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to open drm render node: " << strerror(errno);
return;
}
m_gbmDevice = gbm_create_device(m_drmFd);
if (!m_gbmDevice) {
qCWarning(KRFB_FB_PIPEWIRE) << "Cannot create GBM device: " << strerror(errno);
return;
}
// Get the list of client extensions
const char* clientExtensionsCString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
const QByteArray clientExtensionsString = QByteArray::fromRawData(clientExtensionsCString, qstrlen(clientExtensionsCString));
if (clientExtensionsString.isEmpty()) {
// If eglQueryString() returned NULL, the implementation doesn't support
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
qCWarning(KRFB_FB_PIPEWIRE) << "No client extensions defined! " << formatGLError(eglGetError());
return;
}
m_egl.extensions = clientExtensionsString.split(' ');
// Use eglGetPlatformDisplayEXT() to get the display pointer
// if the implementation supports it.
if (!m_egl.extensions.contains(QByteArrayLiteral("EGL_EXT_platform_base")) ||
!m_egl.extensions.contains(QByteArrayLiteral("EGL_MESA_platform_gbm"))) {
qCWarning(KRFB_FB_PIPEWIRE) << "One of required EGL extensions is missing";
return;
}
m_egl.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, m_gbmDevice, nullptr);
if (m_egl.display == EGL_NO_DISPLAY) {
qCWarning(KRFB_FB_PIPEWIRE) << "Error during obtaining EGL display: " << formatGLError(eglGetError());
return;
}
EGLint major, minor;
if (eglInitialize(m_egl.display, &major, &minor) == EGL_FALSE) {
qCWarning(KRFB_FB_PIPEWIRE) << "Error during eglInitialize: " << formatGLError(eglGetError());
return;
}
if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
qCWarning(KRFB_FB_PIPEWIRE) << "bind OpenGL API failed";
return;
}
m_egl.context = eglCreateContext(m_egl.display, nullptr, EGL_NO_CONTEXT, nullptr);
if (m_egl.context == EGL_NO_CONTEXT) {
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't create EGL context: " << formatGLError(eglGetError());
return;
}
qCDebug(KRFB_FB_PIPEWIRE) << "Egl initialization succeeded";
qCDebug(KRFB_FB_PIPEWIRE) << QStringLiteral("EGL version: %1.%2").arg(major).arg(minor);
m_eglInitialized = true;
#endif /* HAVE_DMA_BUF */
QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q, [this] (const PipeWireFrame &frame) {
handleFrame(frame);
});
}
/**
@@ -314,7 +200,7 @@ void PWFrameBuffer::Private::initDbus()
SLOT(handleXdpSessionCreated(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpSessionCreated(quint32 code, QVariantMap results)
void PWFrameBuffer::handleXdpSessionCreated(quint32 code, const QVariantMap &results)
{
d->handleSessionCreated(code, results);
}
@@ -326,7 +212,7 @@ void PWFrameBuffer::handleXdpSessionCreated(quint32 code, QVariantMap results)
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleSessionCreated(quint32 &code, QVariantMap &results)
void PWFrameBuffer::Private::handleSessionCreated(quint32 code, const QVariantMap &results)
{
if (code != 0) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to create session: " << code;
@@ -357,7 +243,7 @@ void PWFrameBuffer::Private::handleSessionCreated(quint32 &code, QVariantMap &re
SLOT(handleXdpDevicesSelected(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpDevicesSelected(quint32 code, QVariantMap results)
void PWFrameBuffer::handleXdpDevicesSelected(quint32 code, const QVariantMap &results)
{
d->handleDevicesSelected(code, results);
}
@@ -368,7 +254,7 @@ void PWFrameBuffer::handleXdpDevicesSelected(quint32 code, QVariantMap results)
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleDevicesSelected(quint32 &code, QVariantMap &results)
void PWFrameBuffer::Private::handleDevicesSelected(quint32 code, const QVariantMap &results)
{
Q_UNUSED(results)
if (code != 0) {
@@ -398,7 +284,7 @@ void PWFrameBuffer::Private::handleDevicesSelected(quint32 &code, QVariantMap &r
SLOT(handleXdpSourcesSelected(uint, QVariantMap)));
}
void PWFrameBuffer::handleXdpSourcesSelected(quint32 code, QVariantMap results)
void PWFrameBuffer::handleXdpSourcesSelected(quint32 code, const QVariantMap &results)
{
d->handleSourcesSelected(code, results);
}
@@ -411,7 +297,7 @@ void PWFrameBuffer::handleXdpSourcesSelected(quint32 code, QVariantMap results)
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleSourcesSelected(quint32 &code, QVariantMap &)
void PWFrameBuffer::Private::handleSourcesSelected(quint32 code, const QVariantMap &)
{
if (code != 0) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to select sources: " << code;
@@ -434,7 +320,7 @@ void PWFrameBuffer::Private::handleSourcesSelected(quint32 &code, QVariantMap &)
}
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, QVariantMap results)
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results)
{
d->handleRemoteDesktopStarted(code, results);
}
@@ -446,7 +332,7 @@ void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, QVariantMap resu
* @param code return code for dbus call. Zero is success, non-zero means error
* @param results map with results of call.
*/
void PWFrameBuffer::Private::handleRemoteDesktopStarted(quint32 &code, QVariantMap &results)
void PWFrameBuffer::Private::handleRemoteDesktopStarted(quint32 code, const QVariantMap &results)
{
if (code != 0) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to start screencast: " << code;
@@ -454,8 +340,14 @@ void PWFrameBuffer::Private::handleRemoteDesktopStarted(quint32 &code, QVariantM
return;
}
if (results.value(QStringLiteral("devices")).toUInt() == 0) {
qCWarning(KRFB_FB_PIPEWIRE) << "No devices were granted" << results;
isValid = false;
return;
}
// there should be only one stream
Streams streams = qdbus_cast<Streams>(results.value(QStringLiteral("streams")));
const Streams streams = qdbus_cast<Streams>(results.value(QStringLiteral("streams")));
if (streams.isEmpty()) {
// maybe we should check deeper with qdbus_cast but this suffices for now
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to get screencast streams";
@@ -471,501 +363,85 @@ void PWFrameBuffer::Private::handleRemoteDesktopStarted(quint32 &code, QVariantM
return;
}
pipewireFd = streamReply.value();
QDBusUnixFileDescriptor pipewireFd = streamReply.value();
if (!pipewireFd.isValid()) {
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't get pipewire connection file descriptor";
isValid = false;
return;
}
devices = results.value(QStringLiteral("types")).toUInt();
pwStreamNodeId = streams.first().nodeId;
initPw();
}
/**
* @brief PWFrameBuffer::Private::initPw - initialize Pipewire socket connectivity.
* pipewireFd should be pointing to existing file descriptor that was passed by D-Bus at this point.
*/
void PWFrameBuffer::Private::initPw() {
qInfo() << "Initializing Pipewire connectivity";
// init pipewire (required)
pw_init(nullptr, nullptr); // args are not used anyways
pwMainLoop = pw_thread_loop_new("pipewire-main-loop", nullptr);
pw_thread_loop_lock(pwMainLoop);
pwContext = pw_context_new(pw_thread_loop_get_loop(pwMainLoop), nullptr, 0);
if (!pwContext) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to create PipeWire context";
return;
}
pwCore = pw_context_connect(pwContext, nullptr, 0);
if (!pwCore) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to connect PipeWire context";
return;
}
pw_core_add_listener(pwCore, &coreListener, &pwCoreEvents, this);
pwStream = createReceivingStream();
if (!pwStream) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to create PipeWire stream";
return;
}
if (pw_thread_loop_start(pwMainLoop) < 0) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to start main PipeWire loop";
if (!stream->createStream(streams.first().nodeId, pipewireFd.takeFileDescriptor())) {
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't create the pipewire stream";
isValid = false;
}
pw_thread_loop_unlock(pwMainLoop);
}
void PWFrameBuffer::Private::onCoreError(void *data, uint32_t id, int seq, int res, const char *message)
{
Q_UNUSED(data);
Q_UNUSED(id);
Q_UNUSED(seq);
Q_UNUSED(res);
qInfo() << "core error: " << message;
}
/**
* @brief PWFrameBuffer::Private::onStreamStateChanged - called whenever stream state changes on pipewire server
* @param data pointer that you have set in pw_stream_add_listener call's last argument
* @param state new state that stream has changed to
* @param error_message optional error message, is set to non-null if state is error
*/
void PWFrameBuffer::Private::onStreamStateChanged(void *data, pw_stream_state /*old*/, pw_stream_state state, const char *error_message)
{
Q_UNUSED(data);
qInfo() << "Stream state changed: " << pw_stream_state_as_string(state);
switch (state) {
case PW_STREAM_STATE_ERROR:
qCWarning(KRFB_FB_PIPEWIRE) << "pipewire stream error: " << error_message;
break;
case PW_STREAM_STATE_PAUSED:
case PW_STREAM_STATE_STREAMING:
case PW_STREAM_STATE_UNCONNECTED:
case PW_STREAM_STATE_CONNECTING:
break;
}
}
#define CURSOR_BPP 4
#define CURSOR_META_SIZE(w,h) (sizeof(struct spa_meta_cursor) + \
sizeof(struct spa_meta_bitmap) + w * h * CURSOR_BPP)
/**
* @brief PWFrameBuffer::Private::onStreamFormatChanged - being executed after stream is set to active
* and after setup has been requested to connect to it. The actual video format is being negotiated here.
* @param data pointer that you have set in pw_stream_add_listener call's last argument
* @param format format that's being proposed
*/
void PWFrameBuffer::Private::onStreamParamChanged(void *data, uint32_t id, const struct spa_pod *format)
{
qInfo() << "Stream format changed";
auto d = static_cast<PWFrameBuffer::Private *>(data);
if (!format || id != SPA_PARAM_Format) {
return;
}
d->videoFormat = new spa_video_info_raw();
spa_format_video_raw_parse(format, d->videoFormat);
auto width = d->videoFormat->size.width;
auto height = d->videoFormat->size.height;
auto stride = SPA_ROUND_UP_N(width * BYTES_PER_PIXEL, 4);
auto size = height * stride;
d->streamSize = QSize(width, height);
uint8_t buffer[1024];
auto builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
// setup buffers and meta header for new format
#if HAVE_DMA_BUF
const auto bufferTypes = d->m_eglInitialized ? (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr) :
(1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr);
#else
const auto bufferTypes = (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr);
#endif /* HAVE_DMA_BUF */
QVector<const struct spa_pod *> params = {
reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32),
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1),
SPA_PARAM_BUFFERS_align, SPA_POD_Int(16),
SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(bufferTypes))),
reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)))),
reinterpret_cast<spa_pod*>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type,
SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size,
SPA_POD_Int(sizeof(struct spa_meta_region)))),
reinterpret_cast<spa_pod*>(spa_pod_builder_add_object ( &builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor),
SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int (CURSOR_META_SIZE (64, 64),
CURSOR_META_SIZE (1, 1),
CURSOR_META_SIZE (1024, 1024)))),
reinterpret_cast<spa_pod*>(spa_pod_builder_add_object ( &builder,
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoDamage),
SPA_PARAM_META_size, SPA_POD_CHOICE_RANGE_Int(
sizeof(struct spa_meta_region) * 16,
sizeof(struct spa_meta_region) * 1,
sizeof(struct spa_meta_region) * 16))),
};
pw_stream_update_params(d->pwStream, params.data(), params.size());
setVideoSize(qdbus_cast<QSize>(streams.first().map[QStringLiteral("size")].value<QDBusArgument>()));
}
/**
* @brief PWFrameBuffer::Private::onNewBuffer - called when new buffer is available in pipewire stream
* @param data pointer that you have set in pw_stream_add_listener call's last argument
* @param id
*/
void PWFrameBuffer::Private::onStreamProcess(void *data)
void PWFrameBuffer::Private::handleFrame(const PipeWireFrame &frame)
{
auto d = static_cast<PWFrameBuffer::Private *>(data);
cursor = frame.cursor;
pw_buffer* next_buffer;
pw_buffer* buffer = nullptr;
next_buffer = pw_stream_dequeue_buffer(d->pwStream);
while (next_buffer) {
buffer = next_buffer;
next_buffer = pw_stream_dequeue_buffer(d->pwStream);
if (next_buffer) {
pw_stream_queue_buffer(d->pwStream, buffer);
}
}
if (!buffer) {
return;
}
d->handleFrame(buffer);
pw_stream_queue_buffer(d->pwStream, buffer);
}
static QImage::Format spaToQImageFormat(quint32 format)
{
return format == SPA_VIDEO_FORMAT_BGR ? QImage::Format_BGR888
: format == SPA_VIDEO_FORMAT_RGBx ? QImage::Format_RGBX8888
: QImage::Format_RGB32;
}
void PWFrameBuffer::Private::handleFrame(pw_buffer *pwBuffer)
{
auto spaBuffer = pwBuffer->buffer;
uint8_t *src = nullptr;
// process cursor
{
struct spa_meta_cursor *cursor = static_cast<struct spa_meta_cursor*>(spa_buffer_find_meta_data (spaBuffer, SPA_META_Cursor, sizeof (*cursor)));
if (spa_meta_cursor_is_valid (cursor)) {
struct spa_meta_bitmap *bitmap = nullptr;
if (cursor->bitmap_offset)
bitmap = SPA_MEMBER (cursor, cursor->bitmap_offset, struct spa_meta_bitmap);
if (bitmap && bitmap->size.width > 0 && bitmap->size.height > 0) {
const uint8_t *bitmap_data;
bitmap_data = SPA_MEMBER (bitmap, bitmap->offset, uint8_t);
cursorHotspot = { cursor->hotspot.x, cursor->hotspot.y };
cursorTexture = QImage(bitmap_data, bitmap->size.width, bitmap->size.height, bitmap->stride, spaToQImageFormat(bitmap->format));
}
cursorPosition = QPoint{ cursor->position.x, cursor->position.y };
}
}
if (spaBuffer->datas[0].chunk->size == 0) {
if (!frame.dmabuf && !frame.image) {
qCDebug(KRFB_FB_PIPEWIRE) << "Got empty buffer. The buffer possibly carried only "
"information about the mouse cursor.";
return;
}
std::function<void()> cleanup;
const qint64 srcStride = spaBuffer->datas[0].chunk->stride;
if (spaBuffer->datas->type == SPA_DATA_MemFd) {
uint8_t *map = static_cast<uint8_t*>(mmap(
nullptr, spaBuffer->datas->maxsize + spaBuffer->datas->mapoffset,
PROT_READ, MAP_PRIVATE, spaBuffer->datas->fd, 0));
if (map == MAP_FAILED) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to mmap the memory: " << strerror(errno);
return;
}
src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t);
cleanup = [map, spaBuffer] {
munmap(map, spaBuffer->datas->maxsize + spaBuffer->datas->mapoffset);
};
} else if (spaBuffer->datas[0].type == SPA_DATA_MemPtr) {
src = static_cast<uint8_t*>(spaBuffer->datas[0].data);
if (frame.image) {
memcpy(q->fb, frame.image->constBits(), frame.image->sizeInBytes());
setVideoSize(frame.image->size());
}
#if HAVE_DMA_BUF
else if (spaBuffer->datas->type == SPA_DATA_DmaBuf) {
if (!m_eglInitialized) {
// Shouldn't reach this
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to process DMA buffer.";
else if (frame.dmabuf) {
QImage src((uchar*) q->fb, videoSize.width(), videoSize.height(), QImage::Format_RGB32);
if (!m_dmabufHandler.downloadFrame(src, frame)) {
stream->renegotiateModifierFailed(frame.format, frame.dmabuf->modifier);
qCDebug(KRFB_FB_PIPEWIRE) << "Failed to download frame.";
return;
}
gbm_import_fd_data importInfo = {static_cast<int>(spaBuffer->datas->fd), static_cast<uint32_t>(streamSize.width()),
static_cast<uint32_t>(streamSize.height()), static_cast<uint32_t>(spaBuffer->datas[0].chunk->stride), GBM_BO_FORMAT_ARGB8888};
gbm_bo *imported = gbm_bo_import(m_gbmDevice, GBM_BO_IMPORT_FD, &importInfo, GBM_BO_USE_SCANOUT);
if (!imported) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to process buffer: Cannot import passed GBM fd - " << strerror(errno);
return;
}
// bind context to render thread
eglMakeCurrent(m_egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, m_egl.context);
// create EGL image from imported BO
EGLImageKHR image = eglCreateImageKHR(m_egl.display, nullptr, EGL_NATIVE_PIXMAP_KHR, imported, nullptr);
if (image == EGL_NO_IMAGE_KHR) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to record frame: Error creating EGLImageKHR - " << formatGLError(glGetError());
gbm_bo_destroy(imported);
return;
}
// create GL 2D texture for framebuffer
GLuint texture;
glGenTextures(1, &texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, texture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
src = static_cast<uint8_t*>(malloc(srcStride * streamSize.height()));
GLenum glFormat = GL_BGRA;
switch (videoFormat->format) {
case SPA_VIDEO_FORMAT_RGBx:
glFormat = GL_RGBA;
break;
case SPA_VIDEO_FORMAT_RGBA:
glFormat = GL_RGBA;
break;
case SPA_VIDEO_FORMAT_BGRx:
glFormat = GL_BGRA;
break;
case SPA_VIDEO_FORMAT_RGB:
glFormat = GL_RGB;
break;
case SPA_VIDEO_FORMAT_BGR:
glFormat = GL_BGR;
break;
default:
glFormat = GL_BGRA;
break;
}
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, GL_UNSIGNED_BYTE, src);
if (!src) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to get image from DMA buffer.";
gbm_bo_destroy(imported);
return;
}
cleanup = [src] {
free(src);
};
glDeleteTextures(1, &texture);
eglDestroyImageKHR(m_egl.display, image);
gbm_bo_destroy(imported);
setVideoSize(src.size());
}
#endif /* HAVE_DMA_BUF */
struct spa_meta_region* videoMetadata =
static_cast<struct spa_meta_region*>(spa_buffer_find_meta_data(
spaBuffer, SPA_META_VideoCrop, sizeof(*videoMetadata)));
if (videoMetadata && (videoMetadata->region.size.width > static_cast<uint32_t>(streamSize.width()) ||
videoMetadata->region.size.height > static_cast<uint32_t>(streamSize.height()))) {
qCWarning(KRFB_FB_PIPEWIRE) << "Stream metadata sizes are wrong!";
return;
else {
qCDebug(KRFB_FB_PIPEWIRE) << "Unknown kind of frame";
}
// Use video metadata when video size from metadata is set and smaller than
// video stream size, so we need to adjust it.
bool videoFullWidth = true;
bool videoFullHeight = true;
if (videoMetadata && videoMetadata->region.size.width != 0 &&
videoMetadata->region.size.height != 0) {
if (videoMetadata->region.size.width < static_cast<uint32_t>(streamSize.width())) {
videoFullWidth = false;
} else if (videoMetadata->region.size.height < static_cast<uint32_t>(streamSize.height())) {
videoFullHeight = false;
}
}
QSize prevVideoSize = videoSize;
if (!videoFullHeight || !videoFullWidth) {
videoSize = QSize(videoMetadata->region.size.width, videoMetadata->region.size.height);
} else {
videoSize = streamSize;
}
if (!q->fb || videoSize != prevVideoSize) {
if (q->fb) {
free(q->fb);
}
q->fb = static_cast<char*>(malloc(videoSize.width() * videoSize.height() * BYTES_PER_PIXEL));
if (!q->fb) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to allocate buffer";
isValid = false;
return;
}
Q_EMIT q->frameBufferChanged();
}
const qint32 dstStride = videoSize.width() * BYTES_PER_PIXEL;
Q_ASSERT(dstStride <= srcStride);
if (!videoFullHeight && (videoMetadata->region.position.y + videoSize.height() <= streamSize.height())) {
src += srcStride * videoMetadata->region.position.y;
}
const int xOffset = !videoFullWidth && (videoMetadata->region.position.x + videoSize.width() <= streamSize.width())
? videoMetadata->region.position.x * BYTES_PER_PIXEL : 0;
char *dst = q->fb;
for (int i = 0; i < videoSize.height(); ++i) {
// Adjust source content based on crop video position if needed
src += xOffset;
std::memcpy(dst, src, dstStride);
if (videoFormat->format == SPA_VIDEO_FORMAT_BGRA || videoFormat->format == SPA_VIDEO_FORMAT_BGRx) {
for (int j = 0; j < dstStride; j += 4) {
std::swap(dst[j], dst[j + 2]);
}
}
src += srcStride - xOffset;
dst += dstStride;
}
if (spaBuffer->datas->type == SPA_DATA_MemFd ||
spaBuffer->datas->type == SPA_DATA_DmaBuf) {
cleanup();
}
if (videoFormat->format != SPA_VIDEO_FORMAT_RGB) {
QImage img((uchar*) q->fb, videoSize.width(), videoSize.height(), dstStride, spaToQImageFormat(videoFormat->format));
img.convertTo(QImage::Format_RGB888);
}
if (spa_meta* vdMeta = spa_buffer_find_meta(spaBuffer, SPA_META_VideoDamage)) {
struct spa_meta_region *r;
spa_meta_for_each(r, vdMeta) {
if (!spa_meta_region_is_valid(r))
break;
q->tiles.append(QRect(r->region.position.x, r->region.position.y, r->region.size.width, r->region.size.height));
if (auto damage = frame.damage) {
for (const auto &rect : *damage) {
q->tiles.append(rect);
}
} else {
q->tiles.append(QRect(0, 0, videoSize.width(), videoSize.height()));
}
}
/**
* @brief PWFrameBuffer::Private::createReceivingStream - create a stream that will consume Pipewire buffers
* and copy the framebuffer to the existing image that we track. The state of the stream and configuration
* are later handled by the corresponding listener.
*/
pw_stream *PWFrameBuffer::Private::createReceivingStream()
void PWFrameBuffer::Private::setVideoSize(const QSize &size)
{
spa_rectangle pwMinScreenBounds = SPA_RECTANGLE(1, 1);
spa_rectangle pwMaxScreenBounds = SPA_RECTANGLE(UINT32_MAX, UINT32_MAX);
spa_fraction pwFramerateMin = SPA_FRACTION(0, 1);
spa_fraction pwFramerateMax = SPA_FRACTION(60, 1);
pw_properties* reuseProps = pw_properties_new_string("pipewire.client.reuse=1");
auto stream = pw_stream_new(pwCore, "krfb-fb-consume-stream", reuseProps);
uint8_t buffer[1024] = {};
const spa_pod *params[1];
auto builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(6,
SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA,
SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_BGRA,
SPA_VIDEO_FORMAT_RGB, SPA_VIDEO_FORMAT_BGR),
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMaxScreenBounds, &pwMinScreenBounds, &pwMaxScreenBounds),
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&pwFramerateMin),
SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction(&pwFramerateMax, &pwFramerateMin, &pwFramerateMax)));
pw_stream_add_listener(stream, &streamListener, &pwStreamEvents, this);
if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pwStreamNodeId, PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) {
isValid = false;
if (q->fb && videoSize == size) {
return;
}
return stream;
free(q->fb);
q->fb = static_cast<char*>(malloc(size.width() * size.height() * BYTES_PER_PIXEL));
if (!q->fb) {
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to allocate buffer";
isValid = false;
return;
}
videoSize = size;
Q_EMIT q->frameBufferChanged();
}
PWFrameBuffer::Private::~Private()
{
if (pwMainLoop) {
pw_thread_loop_stop(pwMainLoop);
}
if (pwStream) {
pw_stream_destroy(pwStream);
}
if (pwCore) {
pw_core_disconnect(pwCore);
}
if (pwContext) {
pw_context_destroy(pwContext);
}
if (pwMainLoop) {
pw_thread_loop_destroy(pwMainLoop);
}
}
PWFrameBuffer::PWFrameBuffer(QObject *parent)
: FrameBuffer (parent),
d(new Private(this))
{
fb = nullptr;
}
PWFrameBuffer::~PWFrameBuffer()
@@ -998,8 +474,7 @@ void PWFrameBuffer::startVirtualMonitor(const QString& name, const QSize& resolu
auto screencasting = new Screencasting(registry, wlname, version, this);
auto r = screencasting->createVirtualMonitorStream(name, resolution, dpr, Screencasting::Metadata);
connect(r, &ScreencastingStream::created, this, [this] (quint32 nodeId) {
d->pwStreamNodeId = nodeId;
d->initPw();
d->stream->createStream(nodeId, 0);
});
});
registry->create(connection);
@@ -1013,11 +488,17 @@ int PWFrameBuffer::depth()
int PWFrameBuffer::height()
{
if (!d->videoSize.isValid()) {
return 0;
}
return d->videoSize.height();
}
int PWFrameBuffer::width()
{
if (!d->videoSize.isValid()) {
return 0;
}
return d->videoSize.width();
}
@@ -1047,7 +528,7 @@ void PWFrameBuffer::stopMonitor()
QVariant PWFrameBuffer::customProperty(const QString &property) const
{
if (property == QLatin1String("stream_node_id")) {
return QVariant::fromValue<uint>(d->pwStreamNodeId);
return QVariant::fromValue<uint>(d->stream->nodeId());
} if (property == QLatin1String("session_handle")) {
return QVariant::fromValue<QDBusObjectPath>(d->sessionPath);
}
@@ -1062,5 +543,5 @@ bool PWFrameBuffer::isValid() const
QPoint PWFrameBuffer::cursorPosition()
{
return d->cursorPosition;
return d->cursor->position;
}

View File

@@ -50,10 +50,10 @@ public:
bool isValid() const;
private Q_SLOTS:
void handleXdpSessionCreated(quint32 code, QVariantMap results);
void handleXdpDevicesSelected(quint32 code, QVariantMap results);
void handleXdpSourcesSelected(quint32 code, QVariantMap results);
void handleXdpRemoteDesktopStarted(quint32 code, QVariantMap results);
void handleXdpSessionCreated(quint32 code, const QVariantMap &results);
void handleXdpDevicesSelected(quint32 code, const QVariantMap &results);
void handleXdpSourcesSelected(quint32 code, const QVariantMap &results);
void handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results);
private:
class Private;

View File

@@ -22,7 +22,7 @@
#include "pw_framebuffer.h"
#include <KPluginFactory>
K_PLUGIN_CLASS(PWFrameBufferPlugin)
K_PLUGIN_CLASS_WITH_JSON(PWFrameBufferPlugin, "pipewire.json")
PWFrameBufferPlugin::PWFrameBufferPlugin(QObject *parent, const QVariantList &args)
: FrameBufferPlugin(parent, args)

6
framebuffers/qt/qt.json Normal file
View File

@@ -0,0 +1,6 @@
{
"X-KDE-OnlyShowOnQtPlatforms": [
"xcb"
]
}

View File

@@ -24,7 +24,7 @@
#include <KPluginFactory>
K_PLUGIN_CLASS(QtFrameBufferPlugin)
K_PLUGIN_CLASS_WITH_JSON(QtFrameBufferPlugin, "qt.json")
QtFrameBufferPlugin::QtFrameBufferPlugin(QObject *parent, const QVariantList &args)
: FrameBufferPlugin(parent, args)

View File

@@ -0,0 +1,6 @@
{
"X-KDE-OnlyShowOnQtPlatforms": [
"xcb"
]
}

View File

@@ -22,7 +22,7 @@
#include "xcb_framebuffer.h"
#include <KPluginFactory>
K_PLUGIN_CLASS(XCBFrameBufferPlugin)
K_PLUGIN_CLASS_WITH_JSON(XCBFrameBufferPlugin, "xcb.json")
XCBFrameBufferPlugin::XCBFrameBufferPlugin(QObject *parent, const QVariantList &args)
: FrameBufferPlugin(parent, args)

View File

@@ -24,6 +24,7 @@
#include "krfbconfig.h"
#include "krfbdebug.h"
#include <QGuiApplication>
#include <QGlobalStatic>
#include <KPluginFactory>
@@ -40,7 +41,10 @@ Q_GLOBAL_STATIC(FrameBufferManagerStatic, frameBufferManagerStatic)
FrameBufferManager::FrameBufferManager()
{
const QVector<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), {}, KPluginMetaData::AllowEmptyMetaData);
const auto platformFilter = [] (const KPluginMetaData &pluginData) {
return pluginData.value(QStringLiteral("X-KDE-OnlyShowOnQtPlatforms"), QStringList()).contains(QGuiApplication::platformName());
};
const QVector<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), platformFilter, KPluginMetaData::AllowEmptyMetaData);
for (const KPluginMetaData &data : plugins) {
const KPluginFactory::Result<FrameBufferPlugin> result = KPluginFactory::instantiatePlugin<FrameBufferPlugin>(data);
if (result.plugin) {
@@ -76,17 +80,21 @@ QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id, const QVaria
}
}
if (auto preferredPlugin = m_plugins.value(KrfbConfig::preferredFrameBufferPlugin())) {
if (auto frameBuffer = QSharedPointer<FrameBuffer>(preferredPlugin->frameBuffer(args))) {
qCDebug(KRFB) << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();
m_frameBuffers.insert(id, frameBuffer.toWeakRef());
return frameBuffer;
}
}
// We don't already have that frame buffer.
for (auto it = m_plugins.cbegin(); it != m_plugins.constEnd(); it++) {
if (it.key() == KrfbConfig::preferredFrameBufferPlugin()) {
qCDebug(KRFB) << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();
QSharedPointer<FrameBuffer> frameBuffer(it.value()->frameBuffer(args));
if (frameBuffer) {
m_frameBuffers.insert(id, frameBuffer.toWeakRef());
return frameBuffer;
}
QSharedPointer<FrameBuffer> frameBuffer(it.value()->frameBuffer(args));
if (frameBuffer) {
qCDebug(KRFB) << "Using FrameBuffer:" << it.key();
m_frameBuffers.insert(id, frameBuffer.toWeakRef());
return frameBuffer;
}
}

View File

@@ -722,6 +722,7 @@ Comment[id]=Undangan mengirimkan sebuah sandi tidak absah. Koneksi ditampik.
Comment[is]=Boðinn aðili sendi ógilt lykilorð. Tengingu hafnað
Comment[it]=La parte invitata ha inviato una password non valida. Connessione rifiutata.
Comment[ja]=招待された人が無効なパスワードを送ってきました。接続を拒否しました。
Comment[ka]=მოწვეული მხრის გამოგზავნილი პაროლი არასწორია. კავშირი უარყოფილია.
Comment[kk]=Шқырылған жақ дұрыс емес парольді жіберді. Қосылымдан бас тартылды..
Comment[km]=ភាគី​ដែល​បាន​អញ្ជើញ បាន​ផ្ញើ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ ។ ការ​តភ្ជាប់​ត្រូវ​បាន​បដិសេធ ។
Comment[ko]=초대한 사람이 잘못된 암호를 보냈습니다. 연결이 잘못되었습니다.
@@ -789,6 +790,7 @@ Name[id]=Koneksi Baru sedang Tertahan
Name[is]=Ný tenging á bið
Name[it]=Nuova connessione in attesa
Name[ja]=保留中の新しい接続
Name[ka]=ახალი შეერთება შეჩერებულია
Name[kk]=Жаңа қосылым күтілуде
Name[km]=ការ​តភ្ជាប់​ថ្មី កំពុង​ស្ថិត​នៅ​ក្នុង​ការ​រង់ចាំ
Name[ko]=새 연결 대기 중
@@ -852,6 +854,7 @@ Comment[id]=Koneksi diminta, pengguna harus menyetujui
Comment[is]=Beiðni um tengingu, notandi verður að samþykkja
Comment[it]=Connessione richiesta, l'utente deve accettare
Comment[ja]=接続が要求されています。ユーザが許可しなければなりません。
Comment[ka]=მიერთება მოთხოვნილია. მომხმარებელი მას უნდა დაეთანხმოს
Comment[kk]=Қосылым сұралды, пайдаланушы жауап беруге тиіс
Comment[km]=បាន​ស្នើ​ការ​ត​ភ្ជាប់​​ អ្នក​ប្រើ​ត្រូវ​តែ​ទទួល​យក
Comment[ko]=연결 요청됨, 사용자가 수락해야 함
@@ -920,6 +923,7 @@ Name[id]=Koneksi Baru Tersetujui Otomatis
Name[is]=Ný tenging sjálfvirkt samþykkt
Name[it]=Nuova connessione accettata automaticamente
Name[ja]=新しい接続の自動受け入れ
Name[ka]=ახალი მიერთება ავტომატურად მიღებულია
Name[kk]=Жаңа қосылым автоқабылданды
Name[km]=បាន​ទទួល​យក​ការ​តភ្ជាប់​ថ្មី​ដោយ​ស្វ័យ​ប្រវត្តិ
Name[ko]=새 연결 자동 수락
@@ -983,6 +987,7 @@ Comment[id]=Koneksi baru secara otomatis terpancang
Comment[is]=Nýjar tengingar sjálfkrafa samþykktar
Comment[it]=Nuova connessione stabilita automaticamente
Comment[ja]=新しい接続を自動的に確立しました
Comment[ka]=ახალი მიერთება ავტომატურად დამყარებულია
Comment[kk]=Жаңа қосылым автоматты түрде орнатылды
Comment[km]=បាន​បង្កើត​ការ​ត​ភ្ជាប់​ថ្មី​ដោយ​ស្វ័យ​ប្រវត្តិ
Comment[ko]=새 연결이 자동으로 성립됨
@@ -1252,6 +1257,7 @@ Comment[id]=Diperoleh koneksi tak terduga, gugurkan
Comment[is]=Tók á móti óvæntri tengingu, hætti
Comment[it]=Ricevuta connessione inattesa, terminata
Comment[ja]=予期しない接続を受信しました。廃棄します。
Comment[ka]=მიღებულია მოულოდნელი მიერთება. გაუქმდება
Comment[kk]=Күтпеген қосылым ұсынысы, доғарылды
Comment[km]=បាន​ទទួល​យក​ការ​តភ្ជាប់​ដែល​មិន​បាន​រំពឹង​ទុក ​បោះបង់
Comment[ko]=예상하지 않은 연결을 받았습니다, 중지합니다

View File

@@ -54,6 +54,7 @@
<summary xml:lang="eu">Partekatu zure mahaigaina beste ordenagailu batekin VNC erabiliz</summary>
<summary xml:lang="fi">Jaa työpöytä toiselle koneelle VNC:n kautta</summary>
<summary xml:lang="fr">Partager votre bureau avec un autre ordinateur grâce à « VNC »</summary>
<summary xml:lang="gl">Comparte o teu escritorio con outro computador por VNC</summary>
<summary xml:lang="ia">Compartir tu scriptorio a un altere computator via VNC</summary>
<summary xml:lang="id">Bagikan desktopmu ke komputer lainnya via VNC</summary>
<summary xml:lang="it">Condividi il desktop con un altro computer tramite VNC</summary>
@@ -90,6 +91,7 @@
<p xml:lang="ia">Krfb Desktop Sharing es un application de servitor que te permitte compartir tu session currente con un usator sur un altere machina,le qual pote usar un cliente VNC per vider o anque controlar le scriptorio.</p>
<p xml:lang="id">Krfb Desktop Sharing adalah aplikasi server yang memungkinkan kamu untuk berbagi sesimu saat ini dengan pengguna di mesin lain, yang bisa menggunakan klien VNC untuk menampilkan atau bahkan mengendalikan desktop.</p>
<p xml:lang="it">Condivisione del desktop Krfb è un'applicazione server che permette di condividere la sessione attuale con un utente su un'altra macchina, che potrà usare un client VNC per visualizzare ed anche controllare il desktop.</p>
<p xml:lang="ka">Krfb სამუშაო მაგიდის გაზიარება აპლიკაციის სერვერია, რომელიც თქვენი მიმდინარე სესიის სხვა მომხმარებლისთვის, რომელსაც VNC კლიენტი აქვს, გაზიარების და კონტროლის გადაცემის საშუალებას გაძლევთ.</p>
<p xml:lang="ko">Krfb 데스크톱 공유는 현재 세션을 다른 머신의 사용자와 VNC를 통해서 공유하거나 원격 제어를 요청할 수 있는 서버 프로그램입니다.</p>
<p xml:lang="nl">Bureaublad delen is een server-applicatie die u in staat stelt uw huidige sessie te delen met een gebruiker op een andere machine, die een VNC-client kan gebruiken om uw bureaublad te bekijken of zelfs te besturen.</p>
<p xml:lang="nn">Krfb skrivebordsdeling er eit tenar­program som lèt deg dela skrivebords­økta di med ein brukar på ei anna maskin. Vedkommande kan så bruka ein VNC-klient for å sjå og eventuelt òg styra økta.</p>
@@ -159,9 +161,9 @@
</provides>
<project_group>KDE</project_group>
<releases>
<release version="22.08.3" date="2022-11-03"/>
<release version="22.08.2" date="2022-10-13"/>
<release version="22.08.1" date="2022-09-08"/>
<release version="22.08.0" date="2022-08-18"/>
<release version="23.04.3" date="2023-07-06"/>
<release version="23.04.2" date="2023-06-08"/>
<release version="23.04.1" date="2023-05-11"/>
<release version="23.04.0" date="2023-04-20"/>
</releases>
</component>

View File

@@ -88,6 +88,7 @@ GenericName[et]=Töölaua jagamine (VNC)
GenericName[eu]=Mahaigaina partekatzea (VNC)
GenericName[fi]=Työpöydän jakaminen (VNC)
GenericName[fr]=Partage de bureaux (VNC)
GenericName[gl]=Compartir o escritorio (VNC)
GenericName[ia]=Compartir de scriptorio (VNC)
GenericName[it]=Condivisione del desktop (VNC)
GenericName[ka]=სამუშაო მაგიდის გაზიარება(VNC).

View File

@@ -14,6 +14,7 @@ Name[es]=Monitor virtual de KRFB
Name[eu]=KRFBren alegiazko monitorea
Name[fi]=KRFB:n virtuaalinäyttö
Name[fr]=Moniteur virtuel « Krfb »
Name[gl]=Monitor virtual de KRFB
Name[ia]=Virtual Monitor de KRFB
Name[it]=Monitor virtuale di KRFB
Name[ka]=KRFB-
@@ -41,6 +42,7 @@ Comment[es]=Monitor virtual remoto
Comment[eu]=Urruneko alegiazko monitorea
Comment[fi]=Virtuaalinen etänäyttö
Comment[fr]=Moniteur virtuel distant
Comment[gl]=Monitor virtual remoto
Comment[ia]=Monitor Virtual Remote
Comment[it]=Monitor virtuale remoto
Comment[ka]=

View File

@@ -174,7 +174,7 @@ msgstr "Alessandro Praduroux"
#: main-virtualmonitor.cpp:93 main.cpp:111
#, kde-format
msgid "KDE4 porting"
msgstr "النقل إلى كيدي4"
msgstr "النقل إلى كِيدِي4"
#: main-virtualmonitor.cpp:94 main.cpp:112
#, kde-format
@@ -544,7 +544,7 @@ msgid ""
"KDE Desktop Sharing allows you to grant permission to someone at a remote "
"location for viewing and possibly controlling your desktop."
msgstr ""
"تشارك سطح المكتب للكيدي يسمح لك بدعوة شخص بعيد لمشاهدةأو التحكم بسطح مكتبك . "
"تشارك سطح المكتب للكِيدِي يسمح لك بدعوة شخص بعيد لمشاهدةأو التحكم بسطح مكتبك . "
"<a href=\"whatsthis\">المزيد عند الدعوات...</a>"
#. i18n: ectx: property (whatsThis), widget (QCheckBox, enableSharingCheckBox)
@@ -699,7 +699,7 @@ msgstr ""
#~ "watch and possibly control your desktop. <a href=\"whatsthis\">More about "
#~ "invitations...</a>"
#~ msgstr ""
#~ "تشارك سطح المكتب للكيدي يسمح لك بدعوة شخص بعيد لمشاهدةأو التحكم بسطح "
#~ "تشارك سطح المكتب للكِيدِي يسمح لك بدعوة شخص بعيد لمشاهدةأو التحكم بسطح "
#~ "مكتبك . <a href=\"whatsthis\">المزيد عند الدعوات...</a>"
#~ msgid ""
@@ -836,8 +836,8 @@ msgstr ""
#~ "\n"
#~ "For security reasons this invitation will expire at %5 (%6)."
#~ msgstr ""
#~ "لقد دعيت إلى جلسة VNC ، إذا كان لديك برنامج كدي للأسطح البعيدةما عليك إلا "
#~ "أن تنقر على الرابط الذي بالأسفل.\n"
#~ "لقد دعيت إلى جلسة VNC ، إذا كان لديك برنامج كِيدِي للأسطح البعيدةما عليك "
#~ "إلا أن تنقر على الرابط الذي بالأسفل.\n"
#~ "\n"
#~ "%1\n"
#~ "\n"
@@ -869,7 +869,7 @@ msgstr ""
#~ msgstr ""
#~ "مشاركة سطح المكتب باستخدام برتوكول VNC . يمكنك استعمال أي عميل VNC "
#~ "للاتصال.\n"
#~ "في الكيدي يسمى العميل بـ 'اتصال بسطح مكتب بعيد' . ادخل معلومات المضيف\n"
#~ "في الكِيدِي يسمى العميل بـ 'اتصال بسطح مكتب بعيد' . ادخل معلومات المضيف\n"
#~ "في العميل و هو سيقوم بالاتصال.."
#, fuzzy
@@ -901,7 +901,7 @@ msgstr ""
#~ "font-weight:400; font-style:normal; text-decoration:none;\">\n"
#~ "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-"
#~ "right:0px; -qt-block-indent:0; text-indent:0px;\">يسمح عميل مشاركة سطح "
#~ "المكتب للكيديبدعوة شخص في مكان بعيد لمشاهدة سطح مكتب و بالإمكان التحكم "
#~ "المكتب للكِيدِيبدعوة شخص في مكان بعيد لمشاهدة سطح مكتب و بالإمكان التحكم "
#~ "به . <a href=\"whatsthis\">المزيد عن الدعوات...</a></p></body></html>"
#~ msgid "Creation Time"

View File

@@ -2,7 +2,7 @@
# This file is distributed under the same license as the PACKAGE package.
# Vít Pelčák <vit@pelcak.org>, 2011, 2013, 2014, 2017, 2019.
# Tomáš Chvátal <tomas.chvatal@gmail.com>, 2012, 2013.
# Vit Pelcak <vpelcak@suse.cz>, 2022.
# Vit Pelcak <vit@pelcak.org>, 2022.
#
msgid ""
msgstr ""

View File

@@ -17,7 +17,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 21.12.3\n"
#, kde-format

View File

@@ -15,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#, kde-format
msgctxt "NAME OF TRANSLATORS"

View File

@@ -15,6 +15,7 @@
# xavier <xavier.besnard@neuf.fr>, 2013, 2021.
# Vincent Pinon <vpinon@kde.org>, 2017.
# Simon Depiets <sdepiets@gmail.com>, 2019.
# Xavier BESNARD <xavier.besnard@neuf.fr>, 2023.
#
# invite, 2008.
# amine say, 2011.
@@ -23,9 +24,9 @@ msgstr ""
"Project-Id-Version: krfb\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2022-07-18 00:45+0000\n"
"PO-Revision-Date: 2021-11-01 08:30+0100\n"
"Last-Translator: Xavier Besnard <xavier.besnard@neuf.fr>\n"
"Language-Team: French <kde-francophone@kde.org>\n"
"PO-Revision-Date: 2023-01-09 16:44+0100\n"
"Last-Translator: Xavier BESNARD <xavier.besnard]neuf.fr>\n"
"Language-Team: fr\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -34,7 +35,7 @@ msgstr ""
"X-Environment: kde\n"
"X-Accelerator-Marker: &\n"
"X-Text-Markup: kde4\n"
"X-Generator: Lokalize 21.08.1\n"
"X-Generator: Lokalize 22.12.1\n"
#, kde-format
msgctxt "NAME OF TRANSLATORS"
@@ -166,7 +167,7 @@ msgstr ""
"(c) 2001, Johannes E. Schindelin\n"
"(c) 2000-2001, Const Kaplinsky\n"
"(c) 2000, Tridia Corporation\n"
"(c) 1999, AT&T Laboratories Boston\n"
"(c) 1999, Laboratoires AT&T Boston\n"
#: main-virtualmonitor.cpp:91
#, kde-format
@@ -231,7 +232,7 @@ msgstr "Encodeur « ZLib »"
#: main-virtualmonitor.cpp:101 main.cpp:119
#, kde-format
msgid "AT&T Laboratories Boston"
msgstr "AT&T Laboratories Boston"
msgstr "Laboratoires AT&T Boston"
#: main-virtualmonitor.cpp:102 main.cpp:120
#, kde-format

View File

@@ -8,20 +8,21 @@
# Xosé <xosecalvo@gmail.com>, 2009.
# Marce Villarino <mvillarino@kde-espana.es>, 2012, 2013, 2014.
# Adrian Chaves Fernandez <adriyetichaves@gmail.com>, 2012, 2015, 2017.
# Adrián Chaves (Gallaecio) <adrian@chaves.io>, 2017, 2018, 2019.
# Adrián Chaves (Gallaecio) <adrian@chaves.io>, 2017, 2018, 2019, 2023.
msgid ""
msgstr ""
"Project-Id-Version: krfb\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2022-07-18 00:45+0000\n"
"PO-Revision-Date: 2019-07-13 12:48+0200\n"
"PO-Revision-Date: 2023-04-30 15:46+0200\n"
"Last-Translator: Adrián Chaves (Gallaecio) <adrian@chaves.io>\n"
"Language-Team: Galician <kde-i18n-doc@kde.org>\n"
"Language-Team: Galician <proxecto@trasno.gal>\n"
"Language: gl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Lokalize 23.04.0\n"
#, kde-format
msgctxt "NAME OF TRANSLATORS"
@@ -73,7 +74,7 @@ msgstr "Iniciar minimizado."
#: krfb.kcfg:15
#, kde-format
msgid "Use the default port for VNC (5900)"
msgstr "Empregar o porto predeterminado para VNC (5900)"
msgstr "Usar o porto predeterminado para VNC (5900)"
#. i18n: ectx: label, entry (port), group (TCP)
#: krfb.kcfg:19
@@ -122,17 +123,17 @@ msgstr "Complemento de búfer de fotograma preferido"
#: main-virtualmonitor.cpp:49
#, kde-format
msgid "Creating a Virtual Monitor from %1"
msgstr ""
msgstr "Creando un monitor virtual desde %1"
#: main-virtualmonitor.cpp:80
#, kde-format
msgid "Remote Virtual Monitor"
msgstr ""
msgstr "Monitor virtual remoto"
#: main-virtualmonitor.cpp:82
#, kde-format
msgid "Offer a Virtual Monitor that can be accessed remotely"
msgstr ""
msgstr "Ofrecer un monitor virtual ao que se pode acceder en remoto"
#: main-virtualmonitor.cpp:84 main.cpp:98
#, kde-format
@@ -156,7 +157,7 @@ msgstr ""
#: main-virtualmonitor.cpp:91
#, kde-format
msgid "Virtual Monitor implementation"
msgstr ""
msgstr "Implementación do monitor virtual"
#: main-virtualmonitor.cpp:92 main.cpp:108
#, kde-format
@@ -226,54 +227,52 @@ msgstr "codificadores orixinais de VNC e deseño do protocolo"
#: main-virtualmonitor.cpp:108
#, kde-format
msgid "Logical resolution of the new monitor"
msgstr ""
msgstr "Resolución lóxica do novo monitor"
#: main-virtualmonitor.cpp:108
#, kde-format
msgid "resolution"
msgstr ""
msgstr "resolución"
#: main-virtualmonitor.cpp:110
#, kde-format
msgid "Name of the monitor"
msgstr ""
msgstr "Nome do monitor"
#: main-virtualmonitor.cpp:110
#, kde-format
msgid "name"
msgstr ""
msgstr "nome"
#: main-virtualmonitor.cpp:112
#, fuzzy, kde-format
#| msgid "Password for uninvited connections."
#, kde-format
msgid "Password for the client to connect to it"
msgstr "Contrasinal das conexións sen convite."
msgstr "Contrasinal para que o cliente se conecte a el"
#: main-virtualmonitor.cpp:112
#, fuzzy, kde-format
#| msgid "&Password"
#, kde-format
msgid "password"
msgstr "&Contrasinal:"
msgstr "contrasinal"
#: main-virtualmonitor.cpp:114
#, kde-format
msgid "The device-pixel-ratio of the device, the scaling factor"
msgstr ""
msgstr "A taxa de píxel de dispositivo do dispositivo, o factor de escala"
#: main-virtualmonitor.cpp:114
#, kde-format
msgid "dpr"
msgstr ""
msgstr "dpr"
#: main-virtualmonitor.cpp:116
#, kde-format
msgid "The port we will be listening to"
msgstr ""
msgstr "O porto de entrada"
#: main-virtualmonitor.cpp:116
#, kde-format
msgid "number"
msgstr ""
msgstr "número"
#: main.cpp:49
#, kde-format
@@ -312,7 +311,7 @@ msgstr "Compatibilidade cos tubos de Telepathy."
#: main.cpp:126
#, kde-format
msgid "Do not show the invitations management dialog at startup"
msgstr "Non mostrar o diálogo de xestión dos convites ao comezo"
msgstr "Non amosar o diálogo de xestión dos convites ao comezo"
#: main.cpp:148
#, kde-format
@@ -404,7 +403,7 @@ msgstr "Rede"
#: mainwindow.cpp:250
#, kde-format
msgid "Security"
msgstr "Seguranza"
msgstr "Seguridade"
#: mainwindow.cpp:251
#, kde-format
@@ -477,7 +476,7 @@ msgstr ""
"<html><head/><body> <p>Ao usar x11 debería preferirse o complemento <span "
"style=\" font-weight:600;\">xcb</span>, porque ten un mellor rendemento.<br/"
"> O complemento <span style=\" font-weight:600;\">qt</span> é unha "
"alternativa de seguranza, se por algún motivo non funcionan outros "
"alternativa de seguridade, se por algún motivo non funcionan outros "
"complementos. Pero é moi lento.</p> </body></html>"
#. i18n: ectx: property (text), widget (QCheckBox, kcfg_allowDesktopControl)
@@ -496,7 +495,7 @@ msgstr "Non almacenar os contrasinais usando a carteira de KDE"
#: ui/configtcp.ui:26
#, kde-format
msgid "Use default port"
msgstr "Empregar o porto predeterminado"
msgstr "Usar o porto predeterminado"
#. i18n: ectx: property (text), widget (QLabel, label)
#: ui/configtcp.ui:50
@@ -542,7 +541,7 @@ msgid ""
"screen."
msgstr ""
"Se sinala esta opción, o usuario remoto pode inserir polo teclado e usar o "
"rato. Isto dalle control completo sobre o computador, así que teña coidado. "
"rato. Isto dálle control completo sobre o computador, así que teña coidado. "
"Cando a opción está desactivada, o usuario remoto só poderá ver a pantalla."
#. i18n: ectx: property (text), widget (QCheckBox, cbAllowRemoteControl)
@@ -643,6 +642,7 @@ msgstr ""
"Contrasinal que os usuario remotos necesitan para conectar ao seu "
"escritorio. Prema o botón «Editar» da dereita para cambiar o contrasinal."
# well-spelled: ContrasinalTemporal
#. i18n: ectx: property (text), widget (QLabel, passwordDisplayLabel)
#: ui/mainwidget.ui:314
#, kde-format

View File

@@ -20,7 +20,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 19.08.1\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Accelerator-Marker: &\n"
"X-Text-Markup: kde4\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: krfb\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2022-07-18 00:45+0000\n"
"PO-Revision-Date: 2022-09-29 08:37+0200\n"
"PO-Revision-Date: 2023-02-12 06:06+0100\n"
"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
"Language-Team: Georgian <kde-i18n-doc@kde.org>\n"
"Language: ka\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.1.1\n"
"X-Generator: Poedit 3.2.2\n"
#, kde-format
msgctxt "NAME OF TRANSLATORS"
@@ -36,22 +36,22 @@ msgstr "ახალი შეერთება"
#: connectiondialog.cpp:61
#, kde-format
msgid "Accept Connection"
msgstr ""
msgstr "შეერთების მიღება"
#: connectiondialog.cpp:65
#, kde-format
msgid "Refuse Connection"
msgstr ""
msgstr "შეერთების უარყოფა"
#: invitationsrfbclient.cpp:69
#, kde-format
msgid "Accepted connection from %1"
msgstr ""
msgstr "%1-დან კავშირი მიღებულია"
#: invitationsrfbclient.cpp:75
#, kde-format
msgid "Received connection from %1, on hold (waiting for confirmation)"
msgstr ""
msgstr "%1-დან მიერთება დაყოვნების რეჟიმშია (ველოდები დასტურს)"
#: invitationsrfbserver.cpp:55
#, kde-format
@@ -68,56 +68,56 @@ msgstr "ჩაკეცილად გაშვება"
#: krfb.kcfg:15
#, kde-format
msgid "Use the default port for VNC (5900)"
msgstr ""
msgstr "VNC-ის ნაგულისხმები პორტის გამოყენება (5900)"
#. i18n: ectx: label, entry (port), group (TCP)
#: krfb.kcfg:19
#, kde-format
msgid "This is the port on which krfb will listen."
msgstr ""
msgstr "პორტი, რომელზეც krfb მოუსმენს."
#. i18n: ectx: property (text), widget (QCheckBox, kcfg_publishService)
#. i18n: ectx: label, entry (publishService), group (TCP)
#: krfb.kcfg:23 ui/configtcp.ui:16
#, kde-format
msgid "Announce the service on the local network"
msgstr ""
msgstr "სერვისის გამოცხადება ლოკალურ ქსელში"
#. i18n: ectx: label, entry (noWallet), group (Security)
#: krfb.kcfg:29
#, kde-format
msgid "Do not store passwords in KWallet"
msgstr ""
msgstr "პაროლები KWallet-ში შენახული არ იქნება"
#. i18n: ectx: label, entry (allowDesktopControl), group (Security)
#: krfb.kcfg:33
#, kde-format
msgid "Allow remote connections to manage the desktop."
msgstr ""
msgstr "ამ სამუშაო მაგიდაზე დაშორებული მიერთებების დაშვება."
#. i18n: ectx: label, entry (allowUnattendedAccess), group (Security)
#: krfb.kcfg:37
#, kde-format
msgid "Allow connections without an invitation."
msgstr ""
msgstr "მიერთებების მოწვევის გარეშე დადასტურება."
#. i18n: ectx: label, entry (unattendedAccessPassword), group (Security)
#. i18n: ectx: label, entry (desktopSharingPassword), group (Security)
#: krfb.kcfg:41 krfb.kcfg:44
#, kde-format
msgid "Password for uninvited connections."
msgstr ""
msgstr "პაროლი მოუწვეველი მიერთებებისთვის."
#. i18n: ectx: label, entry (preferredFrameBufferPlugin), group (FrameBuffer)
#: krfb.kcfg:49
#, kde-format
msgid "Preferred Frame Buffer Plugin"
msgstr ""
msgstr "კადრების ბაფერის რჩეული დამატება"
#: main-virtualmonitor.cpp:49
#, kde-format
msgid "Creating a Virtual Monitor from %1"
msgstr ""
msgstr "ვირტუალური მონიტორის შექმნა %1-დან"
#: main-virtualmonitor.cpp:80
#, kde-format
@@ -127,7 +127,7 @@ msgstr "დაშორებული ვირტუალური ეკრ
#: main-virtualmonitor.cpp:82
#, kde-format
msgid "Offer a Virtual Monitor that can be accessed remotely"
msgstr ""
msgstr "ვირტუალური მონიტორი, რომელიც დაშორებულად შეიძლება, გამოჩნდეს"
#: main-virtualmonitor.cpp:84 main.cpp:98
#, kde-format
@@ -140,6 +140,13 @@ msgid ""
"(c) 2000, Tridia Corporation\n"
"(c) 1999, AT&T Laboratories Boston\n"
msgstr ""
"(c) 2009-2010, Collabora Ltd.\n"
"(c) 2007, Alessandro Praduroux\n"
"(c) 2001-2003, Tim Jansen\n"
"(c) 2001, Johannes E. Schindelin\n"
"(c) 2000-2001, Const Kaplinsky\n"
"(c) 2000, Tridia Corporation\n"
"(c) 1999, AT&T Laboratories Boston\n"
#: main-virtualmonitor.cpp:91
#, kde-format
@@ -204,17 +211,17 @@ msgstr "ZLib ენკოდერი"
#: main-virtualmonitor.cpp:101 main.cpp:119
#, kde-format
msgid "AT&T Laboratories Boston"
msgstr ""
msgstr "AT&T ლაბორატორიები, ბოსტონი"
#: main-virtualmonitor.cpp:102 main.cpp:120
#, kde-format
msgid "original VNC encoders and protocol design"
msgstr ""
msgstr "ორიგინალური VNC ენკონდერები და პროტოკოლის დიზაინი"
#: main-virtualmonitor.cpp:108
#, kde-format
msgid "Logical resolution of the new monitor"
msgstr ""
msgstr "ახალი მონიტორის ლოგიკური გაფართოება"
#: main-virtualmonitor.cpp:108
#, kde-format
@@ -234,7 +241,7 @@ msgstr "სახელი"
#: main-virtualmonitor.cpp:112
#, kde-format
msgid "Password for the client to connect to it"
msgstr ""
msgstr "პაროლი კლიენტისთვის, რომ შემოუერთდეს"
#: main-virtualmonitor.cpp:112
#, kde-format
@@ -244,7 +251,7 @@ msgstr "პაროლი"
#: main-virtualmonitor.cpp:114
#, kde-format
msgid "The device-pixel-ratio of the device, the scaling factor"
msgstr ""
msgstr "მოწყობილობის device-pixel-ratio. მასშტაბის კოეფიციენტი"
#: main-virtualmonitor.cpp:114
#, kde-format
@@ -254,7 +261,7 @@ msgstr "dpr"
#: main-virtualmonitor.cpp:116
#, kde-format
msgid "The port we will be listening to"
msgstr ""
msgstr "მოსასმენი პორტი"
#: main-virtualmonitor.cpp:116
#, kde-format
@@ -267,6 +274,8 @@ msgid ""
"Your X11 Server does not support the required XTest extension version 2.2. "
"Sharing your desktop is not possible."
msgstr ""
"თქვენს X11 სერვერს აუცილებელი XTest (ვერსია 2.2) გაფართოების მხარდაჭერა არ "
"გააჩნია. სამუშაო მაგიდის გაზიარება შეუძლებელია."
#: main.cpp:51 main.cpp:150
#, kde-format
@@ -281,7 +290,7 @@ msgstr "სამუშაო მაგიდის გაზიარება"
#: main.cpp:96
#, kde-format
msgid "VNC-compatible server to share desktops"
msgstr ""
msgstr "VNC-სთან თავსებადი სერვერი სამუშაო მაგიდის გასაზიარებლად"
#: main.cpp:105
#, kde-format
@@ -291,12 +300,12 @@ msgstr "George Goldberg"
#: main.cpp:106
#, kde-format
msgid "Telepathy tubes support"
msgstr ""
msgstr "Telepathy tubes -ის მხარდაჭერა"
#: main.cpp:126
#, kde-format
msgid "Do not show the invitations management dialog at startup"
msgstr ""
msgstr "მოსაწვევების მართვის ფანჯარა გაშვებისას ნაჩვენები არ იქნება"
#: main.cpp:148
#, kde-format
@@ -304,16 +313,18 @@ msgid ""
"Desktop Sharing is not running under an X11 Server or Wayland.\n"
"Other display servers are currently not supported."
msgstr ""
"სამუშაო მაგიდის გაზიარება X11 სერვერის ან Wayland-ის ქვეშ არაა გაშვებული.\n"
"სხვა ეკრანის სერვერები ამჟამად მხარდაჭერილი არაა."
#: mainwindow.cpp:52
#, kde-format
msgid "Storing passwords in config file is insecure!"
msgstr ""
msgstr "პაროლებს კონფიგურაციის ფაილში შენახვა დაცული არაა!"
#: mainwindow.cpp:189
#, kde-format
msgid "Enter a new password for Unattended Access"
msgstr ""
msgstr "შეიყვანეთ ახალი პაროლი დაუსწრებელი წვდომისთვის"
#: mainwindow.cpp:200
#, kde-format
@@ -321,6 +332,8 @@ msgid ""
"Failed to start the krfb server. Desktop sharing will not work. Try setting "
"another port in the settings and restart krfb."
msgstr ""
"Krfb სერვერის გაშვების შეცდომა. სამუშაო მაგიდის გაზიარება არ იმუშავებს. "
"სცადეთ, სხვა პორტი დააყენოთ და გადატვირთეთ krfb."
#. i18n: ectx: property (whatsThis), widget (QLabel, titleLabel)
#. i18n: ectx: property (text), widget (QLabel, titleLabel)
@@ -329,7 +342,7 @@ msgstr ""
#: ui/mainwidget.ui:86 ui/mainwidget.ui:114
#, kde-format
msgid "KDE Desktop Sharing"
msgstr ""
msgstr "KDE სამუშაო მაგიდის გაზიარება"
#: mainwindow.cpp:224
#, kde-format
@@ -346,6 +359,17 @@ msgid ""
"If your computer is behind a firewall it may have a different address or be "
"unreachable for other computers."
msgstr ""
"ეს ფაილი ერთმანეთისგან ორი წერტილით გამოყოფილ თქვენი კომპიუტერის მისამართს "
"და პორტს შეიცავს.\n"
"\n"
"მისამართი უბრალოდ მინიშნებაა - შეგიძლიათ გამოიყენოთ ნებისმიერი მისამართი, "
"რომელიც თქვენს კომპიუტერამდე მიდის.\n"
"\n"
"სამუშაო მაგიდის გაზიარება ეცდება აღმოაჩინოს თქვენი მისამართი ქსელის "
"კონფიგურაციიდან, მაგრამ ეს ყოველთვის არ გამოსდის.\n"
"\n"
"თუ თქვენი კომპიუტერი ბრანდმაუერის უკან იმალება, მისამართი შეიძლება "
"განსხვავდებოდეს ან მიუწვდომელი იყოს სხვა კომპიუტერებისთვის."
#: mainwindow.cpp:231
#, kde-format
@@ -357,6 +381,11 @@ msgid ""
"password, desktop sharing access will be granted without explicit "
"confirmation."
msgstr ""
"ყველა დაშორებულ მომხმარებელს, რომელსაც ნორმალური სამუშაო მაგიდა გააჩნია, "
"ვალდებულია, ავთენტიკაცია გაიაროს.\n"
"\n"
"თუ ჩართულია დაუსწრებელი წვდომა, დაშორებულ მომხმარებელს უპაროლო წვდომა "
"გააჩნია, წვდომა დადასტურების გარეშე ექნება."
#: mainwindow.cpp:249
#, kde-format
@@ -371,22 +400,24 @@ msgstr "უსაფრთხოება"
#: mainwindow.cpp:251
#, kde-format
msgid "Screen capture"
msgstr ""
msgstr "ეკრანის გადაღება"
#: mainwindow.cpp:256
#, kde-format
msgid "To apply framebuffer plugin setting, you need to restart the program."
msgstr ""
"კადრების ბაფერის დამატების პარამეტრის გადასატარებლად საჭიროა გადატვირთოთ "
"პროგრამა."
#: rfbservermanager.cpp:229
#, kde-format
msgid "The remote user %1 is now connected."
msgstr ""
msgstr "დაშორებული მომხმარებელი %1 ახლა მოერთებულია."
#: rfbservermanager.cpp:243
#, kde-format
msgid "The remote user %1 disconnected."
msgstr ""
msgstr "დაშორებული მომხმარებელი %1 გაითიშა."
#: trayicon.cpp:56
#, kde-format
@@ -396,34 +427,34 @@ msgstr "გათიშვა"
#: trayicon.cpp:62
#, kde-format
msgid "Enable Remote Control"
msgstr ""
msgstr "დაშორებული კონტროლის ჩართვა"
#: trayicon.cpp:101 trayicon.cpp:133
#, kde-format
msgid "Desktop Sharing - disconnected"
msgstr ""
msgstr "სამუშაო მაგიდის გაზიარება - გათიშულია"
#: trayicon.cpp:117 trayicon.cpp:137
#, kde-format
msgid "Desktop Sharing - connected with %1"
msgstr ""
msgstr "სამუშაო მაგიდის გაზიარება - მიერთებულია %1-სთან"
#: trayicon.cpp:120
#, kde-format
msgid "Desktop Sharing - connected"
msgstr ""
msgstr "სამუშაო მაგიდის გაზიარება - მიერთებულია"
#. i18n: ectx: property (windowTitle), widget (QWidget, Framebuffer)
#: ui/configframebuffer.ui:14
#, kde-format
msgid "Framebuffer"
msgstr ""
msgstr "კადრების ბაფერი"
#. i18n: ectx: property (text), widget (QLabel, label)
#: ui/configframebuffer.ui:22
#, kde-format
msgid "Preferred frameb&uffer plugin:"
msgstr ""
msgstr "კადრების &ბუფერის რჩეული დამატება:"
#. i18n: ectx: property (text), widget (QLabel, helpText)
#: ui/configframebuffer.ui:47
@@ -434,30 +465,35 @@ msgid ""
"style=\" font-weight:600;\">qt</span> plugin is a safe fallback, if for some "
"reason others don't work. But also it is very slow.</p></body></html>"
msgstr ""
"<html><head/><body><p>თუ x11-ს იყენებთ, სჯობს გამოიყენოთ <span style=\" font-"
"weight:600;\">xcb</span> დამატება, რადგან ის საუკეთესო წარმადობას გთავაზობთ."
"<br/><span style=\" font-weight:600;\">qt</span>-ის დამატება უსაფრთხოა "
"გამოსაყენებლად, თუ სხვა არაფერი იმუშავებს, მაგრამ ის ასევე ძალიან ნელიცაა</"
"p></body></html>"
#. i18n: ectx: property (text), widget (QCheckBox, kcfg_allowDesktopControl)
#: ui/configsecurity.ui:17
#, kde-format
msgid "Allow remote connections to control your desktop"
msgstr ""
msgstr "ამ მანქანის დაშორებული მომხმარებლის მიერ კონტროლის უფლების მიცემა"
#. i18n: ectx: property (text), widget (QCheckBox, kcfg_noWallet)
#: ui/configsecurity.ui:27
#, kde-format
msgid "Do not store passwords using KDE wallet"
msgstr ""
msgstr "პაროლები KDE-ის საფულეში არ შეინახება"
#. i18n: ectx: property (text), widget (QCheckBox, kcfg_useDefaultPort)
#: ui/configtcp.ui:26
#, kde-format
msgid "Use default port"
msgstr ""
msgstr "ნაგულისხმები პორტის გამოყენება"
#. i18n: ectx: property (text), widget (QLabel, label)
#: ui/configtcp.ui:50
#, kde-format
msgid "Listening port:"
msgstr ""
msgstr "ვუსმენ პორტს:"
#. i18n: ectx: property (text), widget (QLabel, TextLabel5)
#: ui/connectionwidget.ui:47
@@ -472,18 +508,20 @@ msgid ""
"Somebody is requesting a connection to your computer. Granting this will "
"allow the remote user to watch your desktop. "
msgstr ""
"ვიღაც თქვენს კომპიუტერთან მიერთებას მოითხოვს. ამ უფლების მიცემა დაშორებულ "
"მომხმარებელს თქვენი სამუშაო მაგიდის ყურების საშუალებას მისცემს. "
#. i18n: ectx: property (text), widget (QLabel, TextLabel1)
#: ui/connectionwidget.ui:102
#, kde-format
msgid "Remote system:"
msgstr ""
msgstr "დაშორებული სისტემა:"
#. i18n: ectx: property (text), widget (QLabel, remoteHost)
#: ui/connectionwidget.ui:118
#, kde-format
msgid "123.234.123.234"
msgstr ""
msgstr "123.234.123.234"
#. i18n: ectx: property (whatsThis), widget (QCheckBox, cbAllowRemoteControl)
#: ui/connectionwidget.ui:136
@@ -494,12 +532,17 @@ msgid ""
"careful. When the option is disabled the remote user can only watch your "
"screen."
msgstr ""
"თუ ამ პარამეტრს ჩართავთ, დაშორებულ მომხმარებლებს შეუძლია თქვენი თაგუნა "
"გაამოძრაოს და თქვენი კლავიატურით ისარგებლოს. ეს მათ თქვენს კომპიუტერზე სრულ "
"უფლებებს აძლევთ, ასე რომ, ფრთხილად იყავით. როცა ეს პარამეტრი გამორთულია, "
"დაშორებულ მომხმარებელს თქვენი ეკრანის უბრალოდ ყურება შეუძლია."
#. i18n: ectx: property (text), widget (QCheckBox, cbAllowRemoteControl)
#: ui/connectionwidget.ui:139
#, kde-format
msgid "Allow remote user to &control keyboard and mouse"
msgstr ""
"დაშორებული მომხმარებლისთვის &კლავიატურისა და თაგუნას კონტროლის უფლების მიცემა"
#. i18n: ectx: property (text), widget (QLabel, aboutLabel)
#: ui/mainwidget.ui:117
@@ -508,36 +551,39 @@ msgid ""
"KDE Desktop Sharing allows you to grant permission to someone at a remote "
"location for viewing and possibly controlling your desktop."
msgstr ""
"KDE-ის სამუშაო მაგიდის გაზიარება საშუალებას გაძლევთ ვინმეს, ვინც ამას "
"დაშორებული მდებარეობიდან ცდილობს, თქვენი სამუშაო მაგიდის დათვალიერების და "
"საჭიროების შემთხვევაში კონტროლის საშუალება მისცეთ."
#. i18n: ectx: property (whatsThis), widget (QCheckBox, enableSharingCheckBox)
#: ui/mainwidget.ui:145
#, kde-format
msgid "Starts/Stops Remote Desktop Sharing"
msgstr ""
msgstr "დაშორებული სამუშაო მაგიდის გაზიარების გაშვება/გაჩერება"
#. i18n: ectx: property (text), widget (QCheckBox, enableSharingCheckBox)
#: ui/mainwidget.ui:148
#, kde-format
msgid "&Enable Desktop Sharing"
msgstr ""
msgstr "სამუშაო მაგიდის გაზიარების &ჩართვა"
#. i18n: ectx: property (title), widget (QGroupBox, detailsGroupBox)
#: ui/mainwidget.ui:170
#, kde-format
msgid "Connection Details"
msgstr ""
msgstr "კავშირის დეტალები"
#. i18n: ectx: property (text), widget (QLabel, addressLabel)
#: ui/mainwidget.ui:193
#, kde-format
msgid "&Address"
msgstr ""
msgstr "&მისამართი"
#. i18n: ectx: property (whatsThis), widget (QToolButton, addressAboutButton)
#: ui/mainwidget.ui:214
#, kde-format
msgid "More about this address"
msgstr ""
msgstr "მეტი ამ მისამართის შესახებ"
#. i18n: ectx: property (text), widget (QToolButton, addressAboutButton)
#. i18n: ectx: property (text), widget (QToolButton, unattendedAboutButton)
@@ -553,30 +599,32 @@ msgid ""
"Address required by remote users to connect to your desktop. Click about "
"button on the right for more info."
msgstr ""
"დაშორებულ მომხმარებლებს თქვენს სამუშაო მაგიდასთან მისაერთებლად მისამართი "
"ესაჭიროებათ. მეტი ინფორმაციის მისაღებად \"შესახებ\" ღილაკს დააჭირეთ."
#. i18n: ectx: property (text), widget (QLabel, addressDisplayLabel)
#: ui/mainwidget.ui:238
#, kde-format
msgid "127.0.0.1 : 5900"
msgstr ""
msgstr "127.0.0.1 : 5900"
#. i18n: ectx: property (text), widget (QLabel, passwordLabel)
#: ui/mainwidget.ui:269
#, kde-format
msgid "&Password"
msgstr ""
msgstr "&პაროლი"
#. i18n: ectx: property (whatsThis), widget (QToolButton, passwordEditButton)
#: ui/mainwidget.ui:290
#, kde-format
msgid "Edit/Save Desktop Sharing Password"
msgstr ""
msgstr "სამუშაო მაგიდის გაზიარების პაროლის ჩასწორება/შენახვა"
#. i18n: ectx: property (text), widget (QToolButton, passwordEditButton)
#: ui/mainwidget.ui:293
#, kde-format
msgid "Edit"
msgstr ""
msgstr "ჩასწორება"
#. i18n: ectx: property (whatsThis), widget (QLabel, passwordDisplayLabel)
#: ui/mainwidget.ui:311
@@ -585,12 +633,14 @@ msgid ""
"Password required by remote users to connect to your desktop. Click the edit "
"button on the right to change password."
msgstr ""
"დაშორებულ მომხმარებლებს თქვენს სამუშაო მაგიდასთან მისაერთებლად პაროლი "
"ესაჭიროება.პაროლის შესაცვლელად მარჯვენა მხარეს ჩასწორების ღილაკს დააჭირეთ."
#. i18n: ectx: property (text), widget (QLabel, passwordDisplayLabel)
#: ui/mainwidget.ui:314
#, kde-format
msgid "TemporaryPassword"
msgstr ""
msgstr "დროებითიპაროლი"
#. i18n: ectx: property (whatsThis), widget (QGroupBox, unattendedGroupBox)
#. i18n: ectx: property (text), widget (QLabel, unattendedAboutLabel)
@@ -600,12 +650,14 @@ msgid ""
"Unattended Access allows a remote user with the password to gain control to "
"your desktop without your explicit confirmation."
msgstr ""
"მოუწვეველი წვდომა საშუალებას აძლევს დაშორებულ მომხმარებელს, რომელსაც პაროლი "
"გააჩნია, თქვენს კომპიუტერთან წვდომა თქვენი დადასტურების გარეშე მიიღოს."
#. i18n: ectx: property (title), widget (QGroupBox, unattendedGroupBox)
#: ui/mainwidget.ui:343
#, kde-format
msgid "Unattended Access"
msgstr ""
msgstr "დაუსწრებელი წვდომა"
#. i18n: ectx: property (whatsThis), widget (QLabel, unattendedAboutLabel)
#: ui/mainwidget.ui:375
@@ -615,12 +667,15 @@ msgid ""
"your desktop without your explicit confirmation. Click \"About\" button on "
"right to know more."
msgstr ""
"მოუწვეველი წვდომა საშუალებას აძლევს დაშორებულ მომხმარებელს, რომელსაც პაროლი "
"გააჩნია, თქვენს სამუშაო მაგიდასთან წვდომა თქვენი დადასტურების გარეშე აიღოს. "
"მეტის გასაგებად მარჯვენა მხარეს მდებარე ღილაკ \"შესახებ\"-ს დააწექით."
#. i18n: ectx: property (whatsThis), widget (QToolButton, unattendedAboutButton)
#: ui/mainwidget.ui:394
#, kde-format
msgid "Know more about Unattended Access"
msgstr ""
msgstr "გაიგეთ მეტი დაუსწრებელი წვდომის შესახებ"
#. i18n: ectx: property (whatsThis), widget (QCheckBox, enableUnattendedCheckBox)
#: ui/mainwidget.ui:437
@@ -629,21 +684,23 @@ msgid ""
"Starts/Stops unattended access to your desktop. Click on button on right to "
"change password, and \"About\" button to know more."
msgstr ""
"თქვენს სამუშაო მაგიდასთან მოუწვეველი წვდომის შეჩერება/გაშვება. პაროლის "
"შესაცვლელად დააწექით ღილაკს მარჯვნივ, მეტის გასაგებად კი ღილაკს \"შესახებ\"."
#. i18n: ectx: property (text), widget (QCheckBox, enableUnattendedCheckBox)
#: ui/mainwidget.ui:440
#, kde-format
msgid "Enable &Unattended Access"
msgstr ""
msgstr "&დაუსწრებელი წვდომის ჩართვა"
#. i18n: ectx: property (whatsThis), widget (QPushButton, unattendedPasswordButton)
#: ui/mainwidget.ui:465
#, kde-format
msgid "Change password for Unattended Access"
msgstr ""
msgstr "დაუსწრებელი წვდომის პაროლის შეცვლა"
#. i18n: ectx: property (text), widget (QPushButton, unattendedPasswordButton)
#: ui/mainwidget.ui:468
#, kde-format
msgid "&Change Unattended Password"
msgstr ""
msgstr "&დაუსწრებელი წვდომის პაროლის შეცვლა"

View File

@@ -11,13 +11,13 @@
# Rıdvan CAN <ridvancan@linux-sevenler.org>, 2004.
# obsoleteman <tulliana@gmail.com>, 2008-2009,2011.
# Volkan Gezer <volkangezer@gmail.com>, 2013.
# Emir SARI <emir_sari@icloud.com>, 2022.
# Emir SARI <emir_sari@icloud.com>, 2022, 2023.
msgid ""
msgstr ""
"Project-Id-Version: kdenetwork-kde4\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2022-07-18 00:45+0000\n"
"PO-Revision-Date: 2022-06-29 13:31+0300\n"
"PO-Revision-Date: 2023-05-24 01:01+0300\n"
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
"Language-Team: Turkish <kde-l10n-tr@kde.org>\n"
"Language: tr\n"
@@ -25,7 +25,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Lokalize 22.04.2\n"
"X-Generator: Lokalize 23.07.70\n"
#, kde-format
msgctxt "NAME OF TRANSLATORS"
@@ -90,13 +90,13 @@ msgstr "Bu, krfb uygulamasının dinleyeceği kapı numarasıdır."
#: krfb.kcfg:23 ui/configtcp.ui:16
#, kde-format
msgid "Announce the service on the local network"
msgstr "Servisi yerel ağa duyur"
msgstr "Hizmeti yerel ağa duyur"
#. i18n: ectx: label, entry (noWallet), group (Security)
#: krfb.kcfg:29
#, kde-format
msgid "Do not store passwords in KWallet"
msgstr "Parolaları, KWallet içinde saklama"
msgstr "Parolaları K Cüzdan'da saklama"
#. i18n: ectx: label, entry (allowDesktopControl), group (Security)
#: krfb.kcfg:33
@@ -370,7 +370,7 @@ msgstr ""
"Bu alan aralarında iki nokta üst üste karakteri olacak şekilde "
"bilgisayarınızın adını ve kapı numarasını içerir.\n"
"\n"
"Bu adres sadece bir ipucu niteliği taşır. Bilgisayarınıza erişmek için "
"Bu adres yalnızca bir ipucu niteliği taşır. Bilgisayarınıza erişmek için "
"herhangi bir adresi kullanabilirsiniz.\n"
"\n"
"Masaüstü Paylaşımı ağ ayarlarınıza bakarak adresinizi tahmin etmeye çalışır. "
@@ -542,7 +542,7 @@ msgid ""
msgstr ""
"Eğer bu seçenek açık ise, uzaktan bağlanan kullanıcı klavyeyi ve fareyi "
"kullanabilir. Bu onlara bilgisayarınız üstünde tam kontrol verir, bu yüzden "
"dikkatli olun. Sadece seyredebilen kullanıcılar için bu seçenek kapalı "
"dikkatli olun. Yalnızca seyredebilen kullanıcılar için bu seçenek kapalı "
"olmalıdır."
#. i18n: ectx: property (text), widget (QCheckBox, cbAllowRemoteControl)

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: kdeorg\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2022-07-18 00:45+0000\n"
"PO-Revision-Date: 2022-10-30 07:48\n"
"PO-Revision-Date: 2023-07-03 11:41\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
@@ -14,8 +14,8 @@ msgstr ""
"X-Crowdin-Project: kdeorg\n"
"X-Crowdin-Project-ID: 269464\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /kf5-trunk/messages/krfb/krfb.pot\n"
"X-Crowdin-File-ID: 5437\n"
"X-Crowdin-File: /kf5-stable/messages/krfb/krfb.pot\n"
"X-Crowdin-File-ID: 3448\n"
#, kde-format
msgctxt "NAME OF TRANSLATORS"