wlfreerdp: initial Wayland client
Implement an initial Wayland client, which will build if the wayland-client development libraries are detected (or if -DWITH_WAYLAND:BOOL=ON is set). It is currently view-only, but inputs will be implemented soon. It uses the software SHM interface, which means it does not require GL acceleration to run. It should be compatible with any compositor Signed-off-by: Manuel Bachmann <tarnyko@tarnyko.net>
This commit is contained in:
parent
9ce862edc8
commit
d48adecd6c
@ -389,8 +389,10 @@ if(UNIX OR CYGWIN)
|
|||||||
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
|
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
|
||||||
check_include_files(poll.h HAVE_POLL_H)
|
check_include_files(poll.h HAVE_POLL_H)
|
||||||
set(X11_FEATURE_TYPE "RECOMMENDED")
|
set(X11_FEATURE_TYPE "RECOMMENDED")
|
||||||
|
set(WAYLAND_FEATURE_TYPE "RECOMMENDED")
|
||||||
else()
|
else()
|
||||||
set(X11_FEATURE_TYPE "DISABLED")
|
set(X11_FEATURE_TYPE "DISABLED")
|
||||||
|
set(WAYLAND_FEATURE_TYPE "DISABLED")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_PCSC_WINPR)
|
if(WITH_PCSC_WINPR)
|
||||||
@ -400,6 +402,9 @@ endif()
|
|||||||
set(X11_FEATURE_PURPOSE "X11")
|
set(X11_FEATURE_PURPOSE "X11")
|
||||||
set(X11_FEATURE_DESCRIPTION "X11 client and server")
|
set(X11_FEATURE_DESCRIPTION "X11 client and server")
|
||||||
|
|
||||||
|
set(WAYLAND_FEATURE_PURPOSE "Wayland")
|
||||||
|
set(WAYLAND_FEATURE_DESCRIPTION "Wayland client")
|
||||||
|
|
||||||
set(DIRECTFB_FEATURE_TYPE "OPTIONAL")
|
set(DIRECTFB_FEATURE_TYPE "OPTIONAL")
|
||||||
set(DIRECTFB_FEATURE_PURPOSE "DirectFB")
|
set(DIRECTFB_FEATURE_PURPOSE "DirectFB")
|
||||||
set(DIRECTFB_FEATURE_DESCRIPTION "DirectFB client")
|
set(DIRECTFB_FEATURE_DESCRIPTION "DirectFB client")
|
||||||
@ -462,6 +467,7 @@ set(GSM_FEATURE_DESCRIPTION "GSM audio codec library")
|
|||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(X11_FEATURE_TYPE "DISABLED")
|
set(X11_FEATURE_TYPE "DISABLED")
|
||||||
|
set(WAYLAND_FEATURE_TYPE "DISABLED")
|
||||||
set(ZLIB_FEATURE_TYPE "DISABLED")
|
set(ZLIB_FEATURE_TYPE "DISABLED")
|
||||||
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
||||||
set(ALSA_FEATURE_TYPE "DISABLED")
|
set(ALSA_FEATURE_TYPE "DISABLED")
|
||||||
@ -479,6 +485,7 @@ if(APPLE)
|
|||||||
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
|
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
|
||||||
set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
|
set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
|
||||||
set(X11_FEATURE_TYPE "OPTIONAL")
|
set(X11_FEATURE_TYPE "OPTIONAL")
|
||||||
|
set(WAYLAND_FEATURE_TYPE "DISABLED")
|
||||||
if(IOS)
|
if(IOS)
|
||||||
set(X11_FEATURE_TYPE "DISABLED")
|
set(X11_FEATURE_TYPE "DISABLED")
|
||||||
set(ALSA_FEATURE_TYPE "DISABLED")
|
set(ALSA_FEATURE_TYPE "DISABLED")
|
||||||
@ -493,6 +500,7 @@ endif()
|
|||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
set(X11_FEATURE_TYPE "DISABLED")
|
set(X11_FEATURE_TYPE "DISABLED")
|
||||||
|
set(WAYLAND_FEATURE_TYPE "DISABLED")
|
||||||
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
||||||
set(ALSA_FEATURE_TYPE "DISABLED")
|
set(ALSA_FEATURE_TYPE "DISABLED")
|
||||||
set(PULSE_FEATURE_TYPE "DISABLED")
|
set(PULSE_FEATURE_TYPE "DISABLED")
|
||||||
@ -506,6 +514,7 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
|
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
|
||||||
|
find_feature(Wayland ${WAYLAND_FEATURE_TYPE} ${WAYLAND_FEATURE_PURPOSE} ${WAYLAND_FEATURE_DESCRIPTION})
|
||||||
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
|
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
|
||||||
if (${WITH_DIRECTFB})
|
if (${WITH_DIRECTFB})
|
||||||
message(WARNING "DIRECTFB is orphaned and not maintained see docs/README.directfb for details")
|
message(WARNING "DIRECTFB is orphaned and not maintained see docs/README.directfb for details")
|
||||||
|
@ -36,6 +36,10 @@ if(FREERDP_VENDOR)
|
|||||||
add_subdirectory(X11)
|
add_subdirectory(X11)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_WAYLAND)
|
||||||
|
add_subdirectory(Wayland)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
if(IOS)
|
if(IOS)
|
||||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/iOS")
|
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/iOS")
|
||||||
|
34
client/Wayland/CMakeLists.txt
Normal file
34
client/Wayland/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
# FreeRDP Wayland Client cmake build script
|
||||||
|
#
|
||||||
|
# Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
set(MODULE_NAME "wlfreerdp")
|
||||||
|
set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND")
|
||||||
|
|
||||||
|
include_directories(${WAYLAND_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_SRCS
|
||||||
|
wlfreerdp.c)
|
||||||
|
|
||||||
|
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS})
|
||||||
|
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBRARIES} freerdp-client freerdp)
|
||||||
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||||
|
|
||||||
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Wayland")
|
420
client/Wayland/wlfreerdp.c
Normal file
420
client/Wayland/wlfreerdp.c
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Wayland Client Interface
|
||||||
|
*
|
||||||
|
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <freerdp/freerdp.h>
|
||||||
|
#include <freerdp/client/cmdline.h>
|
||||||
|
#include <freerdp/channels/channels.h>
|
||||||
|
#include <freerdp/gdi/gdi.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
struct display
|
||||||
|
{
|
||||||
|
struct wl_display* display;
|
||||||
|
struct wl_registry* registry;
|
||||||
|
struct wl_compositor* compositor;
|
||||||
|
struct wl_shell* shell;
|
||||||
|
struct wl_shm* shm;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct buffer
|
||||||
|
{
|
||||||
|
struct wl_buffer* buffer;
|
||||||
|
void* shm_data;
|
||||||
|
int busy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
struct wl_surface* surface;
|
||||||
|
struct wl_shell_surface* shell_surface;
|
||||||
|
struct wl_callback* callback;
|
||||||
|
struct buffer buffers[2];
|
||||||
|
struct display* display;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wl_context
|
||||||
|
{
|
||||||
|
rdpContext _p;
|
||||||
|
struct display* display;
|
||||||
|
struct window* window;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void wl_buffer_release(void* data, struct wl_buffer* wl_buffer)
|
||||||
|
{
|
||||||
|
struct buffer* buffer = data;
|
||||||
|
|
||||||
|
buffer->busy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_listener wl_buffer_listener =
|
||||||
|
{
|
||||||
|
wl_buffer_release
|
||||||
|
};
|
||||||
|
|
||||||
|
static void window_redraw(void* data, struct wl_callback* callback, uint32_t time);
|
||||||
|
static const struct wl_callback_listener wl_callback_listener =
|
||||||
|
{
|
||||||
|
window_redraw
|
||||||
|
};
|
||||||
|
|
||||||
|
static void window_redraw(void* data, struct wl_callback* callback, uint32_t time)
|
||||||
|
{
|
||||||
|
struct window* window = data;
|
||||||
|
struct wl_shm_pool* shm_pool;
|
||||||
|
struct buffer* buffer;
|
||||||
|
int fd;
|
||||||
|
int fdt;
|
||||||
|
|
||||||
|
if (!window->buffers[0].busy)
|
||||||
|
buffer = &window->buffers[0];
|
||||||
|
else if (!window->buffers[1].busy)
|
||||||
|
buffer = &window->buffers[1];
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
fd = shm_open("wlfreerdp_shm", O_CREAT | O_TRUNC | O_RDWR, 0666);
|
||||||
|
fdt = ftruncate(fd, window->width * window->height * 4);
|
||||||
|
if (fdt != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "window_redraw: could not allocate memory\n");
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->shm_data = mmap(0, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (buffer->shm_data == MAP_FAILED)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "window_redraw: failed to memory map buffer\n");
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
|
||||||
|
buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
|
||||||
|
wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
|
||||||
|
wl_shm_pool_destroy(shm_pool);
|
||||||
|
shm_unlink("wlfreerdp_shm");
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* this is the real surface data */
|
||||||
|
memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4);
|
||||||
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
|
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||||
|
|
||||||
|
if (callback) wl_callback_destroy(callback);
|
||||||
|
window->callback = wl_surface_frame(window->surface);
|
||||||
|
wl_callback_add_listener(window->callback, &wl_callback_listener, window);
|
||||||
|
wl_surface_commit(window->surface);
|
||||||
|
|
||||||
|
buffer->busy = 1;
|
||||||
|
munmap(buffer->shm_data, window->width * window->height * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_shell_surface_handle_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
|
||||||
|
{
|
||||||
|
wl_shell_surface_pong(shell_surface, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_shell_surface_listener wl_shell_surface_listener =
|
||||||
|
{
|
||||||
|
wl_shell_surface_handle_ping
|
||||||
|
};
|
||||||
|
|
||||||
|
static void wl_registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
struct display* display = data;
|
||||||
|
|
||||||
|
if (strcmp(interface, "wl_compositor") == 0)
|
||||||
|
display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
|
||||||
|
else if (strcmp(interface, "wl_shell") == 0)
|
||||||
|
display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
|
||||||
|
else if (strcmp(interface, "wl_shm") == 0)
|
||||||
|
display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wl_registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_registry_listener wl_registry_listener =
|
||||||
|
{
|
||||||
|
wl_registry_handle_global,
|
||||||
|
wl_registry_handle_global_remove
|
||||||
|
};
|
||||||
|
|
||||||
|
int wl_context_new(freerdp* instance, rdpContext* context)
|
||||||
|
{
|
||||||
|
context->channels = freerdp_channels_new();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wl_context_free(freerdp* instance, rdpContext* context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void wl_begin_paint(rdpContext* context)
|
||||||
|
{
|
||||||
|
rdpGdi* gdi;
|
||||||
|
|
||||||
|
gdi = context->gdi;
|
||||||
|
gdi->primary->hdc->hwnd->invalid->null = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wl_end_paint(rdpContext* context)
|
||||||
|
{
|
||||||
|
rdpGdi* gdi;
|
||||||
|
struct display* display;
|
||||||
|
struct window* window;
|
||||||
|
struct wl_context* context_w;
|
||||||
|
|
||||||
|
gdi = context->gdi;
|
||||||
|
if (gdi->primary->hdc->hwnd->invalid->null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
context_w = (struct wl_context*) context;
|
||||||
|
display = context_w->display;
|
||||||
|
window = context_w->window;
|
||||||
|
|
||||||
|
realloc(window->data, gdi->width * gdi->height * 4);
|
||||||
|
memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4);
|
||||||
|
wl_display_dispatch(display->display);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL wl_pre_connect(freerdp* instance)
|
||||||
|
{
|
||||||
|
struct display* display;
|
||||||
|
struct wl_context* context;
|
||||||
|
|
||||||
|
freerdp_channels_pre_connect(instance->context->channels, instance);
|
||||||
|
|
||||||
|
display = malloc(sizeof(*display));
|
||||||
|
display->display = wl_display_connect(NULL);
|
||||||
|
|
||||||
|
if (!display->display)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "wl_pre_connect: failed to connect to Wayland compositor\n");
|
||||||
|
fprintf(stderr, "Please check that the XDG_RUNTIME_DIR environment variable is properly set.\n");
|
||||||
|
free(display);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
display->registry = wl_display_get_registry(display->display);
|
||||||
|
wl_registry_add_listener(display->registry, &wl_registry_listener, display);
|
||||||
|
wl_display_roundtrip(display->display);
|
||||||
|
|
||||||
|
if (!display->compositor || !display->shell || !display->shm)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "wl_pre_connect: failed to find needed compositor interfaces\n");
|
||||||
|
free(display);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put Wayland data in the context here */
|
||||||
|
context = (struct wl_context*) instance->context;
|
||||||
|
context->display = display;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL wl_post_connect(freerdp* instance)
|
||||||
|
{
|
||||||
|
struct window* window;
|
||||||
|
struct wl_context* context;
|
||||||
|
|
||||||
|
context = (struct wl_context*) instance->context;
|
||||||
|
|
||||||
|
window = malloc(sizeof(*window));
|
||||||
|
window->width = instance->settings->DesktopWidth;
|
||||||
|
window->height = instance->settings->DesktopHeight;
|
||||||
|
window->buffers[0].busy = 0;
|
||||||
|
window->buffers[1].busy = 0;
|
||||||
|
window->callback = NULL;
|
||||||
|
window->display = context->display;
|
||||||
|
window->surface = wl_compositor_create_surface(window->display->compositor);
|
||||||
|
window->shell_surface = wl_shell_get_shell_surface(window->display->shell, window->surface);
|
||||||
|
|
||||||
|
wl_shell_surface_add_listener(window->shell_surface, &wl_shell_surface_listener, NULL);
|
||||||
|
wl_shell_surface_set_title(window->shell_surface, "FreeRDP");
|
||||||
|
wl_shell_surface_set_toplevel(window->shell_surface);
|
||||||
|
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||||
|
|
||||||
|
/* GC/GDI logic here */
|
||||||
|
rdpGdi* gdi;
|
||||||
|
|
||||||
|
gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_32BPP, NULL);
|
||||||
|
gdi = instance->context->gdi;
|
||||||
|
|
||||||
|
/* fill buffer with first image here */
|
||||||
|
window->data = malloc (gdi->width * gdi->height *4);
|
||||||
|
memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4);
|
||||||
|
instance->update->BeginPaint = wl_begin_paint;
|
||||||
|
instance->update->EndPaint = wl_end_paint;
|
||||||
|
|
||||||
|
/* put Wayland data in the context here */
|
||||||
|
context->window = window;
|
||||||
|
|
||||||
|
freerdp_channels_post_connect(instance->context->channels, instance);
|
||||||
|
|
||||||
|
window_redraw(window, NULL, 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wlfreerdp_run(freerdp* instance)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int fds;
|
||||||
|
int max_fds;
|
||||||
|
int rcount;
|
||||||
|
int wcount;
|
||||||
|
void* rfds[32];
|
||||||
|
void* wfds[32];
|
||||||
|
fd_set rfds_set;
|
||||||
|
fd_set wfds_set;
|
||||||
|
|
||||||
|
ZeroMemory(rfds, sizeof(rfds));
|
||||||
|
ZeroMemory(wfds, sizeof(wfds));
|
||||||
|
|
||||||
|
freerdp_connect(instance);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
rcount = 0;
|
||||||
|
wcount = 0;
|
||||||
|
if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
|
||||||
|
{
|
||||||
|
printf("Failed to get FreeRDP file descriptor");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
|
||||||
|
{
|
||||||
|
printf("Failed to get FreeRDP file descriptor");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_fds = 0;
|
||||||
|
FD_ZERO(&rfds_set);
|
||||||
|
FD_ZERO(&wfds_set);
|
||||||
|
|
||||||
|
for (i = 0; i < rcount; i++)
|
||||||
|
{
|
||||||
|
fds = (int)(long)(rfds[i]);
|
||||||
|
|
||||||
|
if (fds > max_fds)
|
||||||
|
max_fds = fds;
|
||||||
|
|
||||||
|
FD_SET(fds, &rfds_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_fds == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1)
|
||||||
|
{
|
||||||
|
if (!((errno == EAGAIN) ||
|
||||||
|
(errno == EWOULDBLOCK) ||
|
||||||
|
(errno == EINPROGRESS) ||
|
||||||
|
(errno == EINTR)))
|
||||||
|
{
|
||||||
|
printf("wlfreerdp_run: select failed\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freerdp_check_fds(instance) != TRUE)
|
||||||
|
{
|
||||||
|
printf("Failed to check FreeRDP file descriptor\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE)
|
||||||
|
{
|
||||||
|
printf("Failed to check channel manager file descriptor\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct display* display;
|
||||||
|
struct window* window;
|
||||||
|
struct wl_context* context;
|
||||||
|
|
||||||
|
context = (struct wl_context*) instance->context;
|
||||||
|
display = context->display;
|
||||||
|
window = context->window;
|
||||||
|
free(window->buffers[0].shm_data);
|
||||||
|
free(window->buffers[1].shm_data);
|
||||||
|
free(window->data);
|
||||||
|
|
||||||
|
wl_buffer_destroy(window->buffers[0].buffer);
|
||||||
|
wl_buffer_destroy(window->buffers[1].buffer);
|
||||||
|
wl_shell_surface_destroy(window->shell_surface);
|
||||||
|
wl_surface_destroy(window->surface);
|
||||||
|
wl_shm_destroy(display->shm);
|
||||||
|
wl_shell_destroy(display->shell);
|
||||||
|
wl_compositor_destroy(display->compositor);
|
||||||
|
wl_registry_destroy(display->registry);
|
||||||
|
wl_display_disconnect(display->display);
|
||||||
|
|
||||||
|
freerdp_channels_close(instance->context->channels, instance);
|
||||||
|
freerdp_channels_free(instance->context->channels);
|
||||||
|
freerdp_free(instance);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
freerdp* instance;
|
||||||
|
|
||||||
|
freerdp_channels_global_init();
|
||||||
|
|
||||||
|
instance = freerdp_new();
|
||||||
|
instance->PreConnect = wl_pre_connect;
|
||||||
|
instance->PostConnect = wl_post_connect;
|
||||||
|
|
||||||
|
instance->ContextSize = sizeof(struct wl_context);
|
||||||
|
instance->ContextNew = wl_context_new;
|
||||||
|
instance->ContextFree = wl_context_free;
|
||||||
|
freerdp_context_new(instance);
|
||||||
|
|
||||||
|
status = freerdp_client_parse_command_line_arguments(argc, argv, instance->settings);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
freerdp_client_load_addins(instance->context->channels, instance->settings);
|
||||||
|
|
||||||
|
wlfreerdp_run(instance);
|
||||||
|
|
||||||
|
freerdp_channels_global_uninit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
46
cmake/FindWayland.cmake
Normal file
46
cmake/FindWayland.cmake
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# - Find Wayland
|
||||||
|
# Find the Wayland libraries
|
||||||
|
#
|
||||||
|
# This module defines the following variables:
|
||||||
|
# WAYLAND_FOUND - true if WAYLAND_INCLUDE_DIR & WAYLAND_LIBRARY are found
|
||||||
|
# WAYLAND_LIBRARIES - Set when WAYLAND_LIBRARY is found
|
||||||
|
# WAYLAND_INCLUDE_DIRS - Set when WAYLAND_INCLUDE_DIR is found
|
||||||
|
#
|
||||||
|
# WAYLAND_INCLUDE_DIR - where to find wayland-client.h, etc.
|
||||||
|
# WAYLAND_LIBRARY - the Wayland client library
|
||||||
|
#
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
find_path(WAYLAND_INCLUDE_DIR NAMES wayland-client.h
|
||||||
|
DOC "The Wayland include directory"
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(WAYLAND_LIBRARY NAMES wayland-client
|
||||||
|
DOC "The Wayland client library"
|
||||||
|
)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARY WAYLAND_INCLUDE_DIR)
|
||||||
|
|
||||||
|
if(WAYLAND_FOUND)
|
||||||
|
set( WAYLAND_LIBRARIES ${WAYLAND_LIBRARY} )
|
||||||
|
set( WAYLAND_INCLUDE_DIRS ${WAYLAND_INCLUDE_DIR} )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(WAYLAND_INCLUDE_DIR WAYLAND_LIBRARY)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user