input: Rename wl_pointer to weston_pointer
[platform/upstream/weston.git] / src / compositor-rdp.c
1 /*
2  * Copyright © 2013 Hardening <rdp.effort@gmail.com>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <linux/input.h>
31
32 #include <freerdp/freerdp.h>
33 #include <freerdp/listener.h>
34 #include <freerdp/update.h>
35 #include <freerdp/input.h>
36 #include <freerdp/codec/color.h>
37 #include <freerdp/codec/rfx.h>
38 #include <freerdp/codec/nsc.h>
39 #include <winpr/input.h>
40
41 #include "compositor.h"
42 #include "pixman-renderer.h"
43
44 #define MAX_FREERDP_FDS 32
45
46 struct rdp_compositor_config {
47         int width;
48         int height;
49         char *bind_address;
50         int port;
51         char *rdp_key;
52         char *server_cert;
53         char *server_key;
54         char *extra_modes;
55         int env_socket;
56 };
57
58 struct rdp_output;
59
60 struct rdp_compositor {
61         struct weston_compositor base;
62         struct weston_seat main_seat;
63
64         freerdp_listener *listener;
65         struct wl_event_source *listener_events[MAX_FREERDP_FDS];
66         struct rdp_output *output;
67
68         char *server_cert;
69         char *server_key;
70         char *rdp_key;
71         int tls_enabled;
72 };
73
74 enum peer_item_flags {
75         RDP_PEER_ACTIVATED      = (1 << 0),
76         RDP_PEER_OUTPUT_ENABLED = (1 << 1),
77 };
78
79 struct rdp_peers_item {
80         int flags;
81         freerdp_peer *peer;
82         struct weston_seat seat;
83
84         struct wl_list link;
85 };
86
87 struct rdp_output {
88         struct weston_output base;
89         struct wl_event_source *finish_frame_timer;
90         pixman_image_t *shadow_surface;
91
92         struct wl_list peers;
93 };
94
95 struct rdp_peer_context {
96         rdpContext _p;
97         struct rdp_compositor *rdpCompositor;
98
99         /* file descriptors and associated events */
100         int fds[MAX_FREERDP_FDS];
101         struct wl_event_source *events[MAX_FREERDP_FDS];
102
103         RFX_CONTEXT *rfx_context;
104         wStream *encode_stream;
105         RFX_RECT *rfx_rects;
106         NSC_CONTEXT *nsc_context;
107
108         struct rdp_peers_item item;
109 };
110 typedef struct rdp_peer_context RdpPeerContext;
111
112 static void
113 rdp_compositor_config_init(struct rdp_compositor_config *config) {
114         config->width = 640;
115         config->height = 480;
116         config->bind_address = NULL;
117         config->port = 3389;
118         config->rdp_key = NULL;
119         config->server_cert = NULL;
120         config->server_key = NULL;
121         config->extra_modes = NULL;
122         config->env_socket = 0;
123 }
124
125 static void
126 rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
127 {
128         int width, height, nrects, i;
129         pixman_box32_t *region, *rects;
130         uint32_t *ptr;
131         RFX_RECT *rfxRect;
132         rdpUpdate *update = peer->update;
133         SURFACE_BITS_COMMAND *cmd = &update->surface_bits_command;
134         RdpPeerContext *context = (RdpPeerContext *)peer->context;
135
136         stream_clear(context->encode_stream);
137         stream_set_pos(context->encode_stream, 0);
138
139         width = (damage->extents.x2 - damage->extents.x1);
140         height = (damage->extents.y2 - damage->extents.y1);
141
142         cmd->destLeft = damage->extents.x1;
143         cmd->destTop = damage->extents.y1;
144         cmd->destRight = damage->extents.x2;
145         cmd->destBottom = damage->extents.y2;
146         cmd->bpp = 32;
147         cmd->codecID = peer->settings->RemoteFxCodecId;
148         cmd->width = width;
149         cmd->height = height;
150
151         ptr = pixman_image_get_data(image) + damage->extents.x1 +
152                                 damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
153
154         rects = pixman_region32_rectangles(damage, &nrects);
155         context->rfx_rects = realloc(context->rfx_rects, nrects * sizeof *rfxRect);
156
157         for (i = 0; i < nrects; i++) {
158                 region = &rects[i];
159                 rfxRect = &context->rfx_rects[i];
160
161                 rfxRect->x = (region->x1 - damage->extents.x1);
162                 rfxRect->y = (region->y1 - damage->extents.y1);
163                 rfxRect->width = (region->x2 - region->x1);
164                 rfxRect->height = (region->y2 - region->y1);
165         }
166
167         rfx_compose_message(context->rfx_context, context->encode_stream, context->rfx_rects, nrects,
168                         (BYTE *)ptr, width, height,
169                         pixman_image_get_stride(image)
170         );
171
172         cmd->bitmapDataLength = stream_get_length(context->encode_stream);
173         cmd->bitmapData = stream_get_head(context->encode_stream);
174
175         update->SurfaceBits(update->context, cmd);
176 }
177
178
179 static void
180 rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
181 {
182         int width, height;
183         uint32_t *ptr;
184         rdpUpdate *update = peer->update;
185         SURFACE_BITS_COMMAND *cmd = &update->surface_bits_command;
186         RdpPeerContext *context = (RdpPeerContext *)peer->context;
187
188         stream_clear(context->encode_stream);
189         stream_set_pos(context->encode_stream, 0);
190
191         width = (damage->extents.x2 - damage->extents.x1);
192         height = (damage->extents.y2 - damage->extents.y1);
193
194         cmd->destLeft = damage->extents.x1;
195         cmd->destTop = damage->extents.y1;
196         cmd->destRight = damage->extents.x2;
197         cmd->destBottom = damage->extents.y2;
198         cmd->bpp = 32;
199         cmd->codecID = peer->settings->NSCodecId;
200         cmd->width = width;
201         cmd->height = height;
202
203         ptr = pixman_image_get_data(image) + damage->extents.x1 +
204                                 damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
205
206         nsc_compose_message(context->nsc_context, context->encode_stream, (BYTE *)ptr,
207                         cmd->width,     cmd->height,
208                         pixman_image_get_stride(image));
209         cmd->bitmapDataLength = stream_get_length(context->encode_stream);
210         cmd->bitmapData = stream_get_head(context->encode_stream);
211         update->SurfaceBits(update->context, cmd);
212 }
213
214 static void
215 rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_peer *peer)
216 {
217         pixman_image_t *tile;
218         rdpUpdate *update = peer->update;
219         SURFACE_BITS_COMMAND *cmd = &update->surface_bits_command;
220         pixman_box32_t *extends = pixman_region32_extents(region);
221
222         cmd->bpp = 32;
223         cmd->codecID = 0;
224         cmd->width = (extends->x2 - extends->x1);
225         cmd->height = (extends->y2 - extends->y1);;
226         cmd->bitmapDataLength = cmd->width * cmd->height * 4;
227         tile = pixman_image_create_bits(PIXMAN_x8r8g8b8, cmd->width, cmd->height, 0, cmd->width * 4);
228         pixman_image_composite32(PIXMAN_OP_SRC, image, NULL, /* op, src, mask */
229                 tile, extends->x1, extends->y1, /* dest, src_x, src_y */
230                 0, 0, /* mask_x, mask_y */
231                 0, 0, /* dest_x, dest_y */
232                 cmd->width, cmd->height /* width, height */
233         );
234         freerdp_image_flip((BYTE *)pixman_image_get_data(tile),
235                         (BYTE *)pixman_image_get_data(tile),
236                         cmd->width, cmd->height, cmd->bpp
237         );
238         cmd->bitmapData = (BYTE *)pixman_image_get_data(tile);
239         cmd->destLeft = extends->x1;
240         cmd->destTop = extends->y1;
241         cmd->destRight = extends->x2;
242         cmd->destBottom = extends->y2;
243         update->SurfaceBits(peer->context, cmd);
244         pixman_image_unref(tile);
245 }
246
247 static void
248 rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
249 {
250         RdpPeerContext *context = (RdpPeerContext *)peer->context;
251         struct rdp_output *output = context->rdpCompositor->output;
252         rdpSettings *settings = peer->settings;
253         pixman_box32_t *extents = pixman_region32_extents(region);
254
255         int regionSz = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
256
257         if(regionSz > 64 * 64) {
258                 if(settings->RemoteFxCodec)
259                         rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
260                 else if(settings->NSCodec)
261                         rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
262                 else
263                         rdp_peer_refresh_raw(region, output->shadow_surface, peer);
264         } else {
265                 rdp_peer_refresh_raw(region, output->shadow_surface, peer);
266         }
267 }
268
269 static void
270 rdp_output_start_repaint_loop(struct weston_output *output)
271 {
272         uint32_t msec;
273         struct timeval tv;
274
275         gettimeofday(&tv, NULL);
276         msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
277         weston_output_finish_frame(output, msec);
278 }
279
280 static void
281 rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
282 {
283         struct rdp_output *output = container_of(output_base, struct rdp_output, base);
284         struct weston_compositor *ec = output->base.compositor;
285         struct rdp_peers_item *outputPeer;
286
287         pixman_renderer_output_set_buffer(output_base, output->shadow_surface);
288         ec->renderer->repaint_output(&output->base, damage);
289
290         wl_list_for_each(outputPeer, &output->peers, link) {
291                 if ((outputPeer->flags & RDP_PEER_ACTIVATED) &&
292                                 (outputPeer->flags & RDP_PEER_OUTPUT_ENABLED))
293                 {
294                         rdp_peer_refresh_region(damage, outputPeer->peer);
295                 }
296         }
297
298         pixman_region32_subtract(&ec->primary_plane.damage,
299                                  &ec->primary_plane.damage, damage);
300
301         wl_event_source_timer_update(output->finish_frame_timer, 16);
302 }
303
304 static void
305 rdp_output_destroy(struct weston_output *output_base)
306 {
307         struct rdp_output *output = (struct rdp_output *)output_base;
308
309         wl_event_source_remove(output->finish_frame_timer);
310         free(output);
311 }
312
313 static int
314 finish_frame_handler(void *data)
315 {
316         rdp_output_start_repaint_loop(data);
317
318         return 1;
319 }
320
321
322 static struct weston_mode *
323 find_matching_mode(struct weston_output *output, struct weston_mode *target) {
324         struct weston_mode *local;
325
326         wl_list_for_each(local, &output->mode_list, link) {
327                 if((local->width == target->width) && (local->height == target->height))
328                         return local;
329         }
330         return 0;
331 }
332
333 static int
334 rdp_switch_mode(struct weston_output *output, struct weston_mode *target_mode) {
335         struct rdp_output *rdpOutput = container_of(output, struct rdp_output, base);
336         struct rdp_peers_item *rdpPeer;
337         rdpSettings *settings;
338         pixman_image_t *new_shadow_buffer;
339         struct weston_mode *local_mode;
340
341         local_mode = find_matching_mode(output, target_mode);
342         if(!local_mode) {
343                 weston_log("mode %dx%d not available\n", target_mode->width, target_mode->height);
344                 return -ENOENT;
345         }
346
347         if(local_mode == output->current)
348                 return 0;
349
350         output->current->flags = 0;
351         output->current = local_mode;
352         output->current->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
353
354         pixman_renderer_output_destroy(output);
355         pixman_renderer_output_create(output);
356
357         new_shadow_buffer = pixman_image_create_bits(PIXMAN_x8r8g8b8, target_mode->width,
358                         target_mode->height, 0, target_mode->width * 4);
359         pixman_image_composite32(PIXMAN_OP_SRC, rdpOutput->shadow_surface, 0, new_shadow_buffer,
360                         0, 0, 0, 0, 0, 0, target_mode->width, target_mode->height);
361         pixman_image_unref(rdpOutput->shadow_surface);
362         rdpOutput->shadow_surface = new_shadow_buffer;
363
364         wl_list_for_each(rdpPeer, &rdpOutput->peers, link) {
365                 settings = rdpPeer->peer->settings;
366                 if(!settings->DesktopResize) {
367                         /* too bad this peer does not support desktop resize */
368                         rdpPeer->peer->Close(rdpPeer->peer);
369                 } else {
370                         settings->DesktopWidth = target_mode->width;
371                         settings->DesktopHeight = target_mode->height;
372                         rdpPeer->peer->update->DesktopResize(rdpPeer->peer->context);
373                 }
374         }
375         return 0;
376 }
377
378 static int
379 parse_extra_modes(const char *modes_str, struct rdp_output *output) {
380         const char *startAt = modes_str;
381         const char *nextPos;
382         int w, h;
383         struct weston_mode *mode;
384
385         while(startAt && *startAt) {
386                 nextPos = strchr(startAt, 'x');
387                 if(!nextPos)
388                         return -1;
389
390                 w = strtoul(startAt, NULL, 0);
391                 startAt = nextPos + 1;
392                 if(!*startAt)
393                         return -1;
394
395                 h = strtoul(startAt, NULL, 0);
396
397                 if(!w || (w > 3000) || !h || (h > 3000))
398                         return -1;
399                 mode = malloc(sizeof *mode);
400                 if(!mode)
401                         return -1;
402
403                 mode->width = w;
404                 mode->height = h;
405                 mode->refresh = 5;
406                 mode->flags = 0;
407                 wl_list_insert(&output->base.mode_list, &mode->link);
408
409                 startAt = strchr(startAt, ',');
410                 if(startAt && *startAt == ',')
411                         startAt++;
412         }
413         return 0;
414 }
415 static int
416 rdp_compositor_create_output(struct rdp_compositor *c, int width, int height,
417                 const char *extraModes)
418 {
419         struct rdp_output *output;
420         struct wl_event_loop *loop;
421         struct weston_mode *currentMode, *next;
422
423         output = malloc(sizeof *output);
424         if (output == NULL)
425                 return -1;
426         memset(output, 0, sizeof *output);
427
428         wl_list_init(&output->peers);
429         wl_list_init(&output->base.mode_list);
430
431         currentMode = malloc(sizeof *currentMode);
432         if(!currentMode)
433                 goto out_free_output;
434         currentMode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
435         currentMode->width = width;
436         currentMode->height = height;
437         currentMode->refresh = 5;
438         wl_list_insert(&output->base.mode_list, &currentMode->link);
439
440         if(parse_extra_modes(extraModes, output) < 0) {
441                 weston_log("invalid extra modes\n");
442                 goto out_free_output_and_modes;
443         }
444
445         output->base.current = currentMode;
446         weston_output_init(&output->base, &c->base, 0, 0, width, height,
447                         WL_OUTPUT_TRANSFORM_NORMAL);
448
449         output->base.make = "weston";
450         output->base.model = "rdp";
451         output->shadow_surface = pixman_image_create_bits(PIXMAN_x8r8g8b8,
452                         width, height,
453                     NULL,
454                     width * 4);
455         if (output->shadow_surface == NULL) {
456                 weston_log("Failed to create surface for frame buffer.\n");
457                 goto out_output;
458         }
459
460         if (pixman_renderer_output_create(&output->base) < 0)
461                 goto out_shadow_surface;
462
463         weston_output_move(&output->base, 0, 0);
464
465         loop = wl_display_get_event_loop(c->base.wl_display);
466         output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
467
468         output->base.origin = output->base.current;
469         output->base.start_repaint_loop = rdp_output_start_repaint_loop;
470         output->base.repaint = rdp_output_repaint;
471         output->base.destroy = rdp_output_destroy;
472         output->base.assign_planes = NULL;
473         output->base.set_backlight = NULL;
474         output->base.set_dpms = NULL;
475         output->base.switch_mode = rdp_switch_mode;
476         c->output = output;
477
478         wl_list_insert(c->base.output_list.prev, &output->base.link);
479         return 0;
480
481 out_shadow_surface:
482         pixman_image_unref(output->shadow_surface);
483 out_output:
484         weston_output_destroy(&output->base);
485 out_free_output_and_modes:
486         wl_list_for_each_safe(currentMode, next, &output->base.mode_list, link)
487                 free(currentMode);
488 out_free_output:
489         free(output);
490         return -1;
491 }
492
493 static void
494 rdp_restore(struct weston_compositor *ec)
495 {
496 }
497
498 static void
499 rdp_destroy(struct weston_compositor *ec)
500 {
501         struct rdp_compositor *c = (struct rdp_compositor *) ec;
502
503         weston_seat_release(&c->main_seat);
504
505         ec->renderer->destroy(ec);
506         weston_compositor_shutdown(ec);
507
508         free(ec);
509 }
510
511 static
512 int rdp_listener_activity(int fd, uint32_t mask, void *data) {
513         freerdp_listener* instance = (freerdp_listener *)data;
514
515         if (!(mask & WL_EVENT_READABLE))
516                 return 0;
517         if (!instance->CheckFileDescriptor(instance))
518         {
519                 weston_log("failed to check FreeRDP file descriptor\n");
520                 return -1;
521         }
522         return 0;
523 }
524
525 static
526 int rdp_implant_listener(struct rdp_compositor *c, freerdp_listener* instance) {
527         int i, fd;
528         int rcount = 0;
529         void* rfds[MAX_FREERDP_FDS];
530         struct wl_event_loop *loop;
531
532         if (!instance->GetFileDescriptor(instance, rfds, &rcount)) {
533                 weston_log("Failed to get FreeRDP file descriptor\n");
534                 return -1;
535         }
536
537         loop = wl_display_get_event_loop(c->base.wl_display);
538         for (i = 0; i < rcount; i++) {
539                 fd = (int)(long)(rfds[i]);
540                 c->listener_events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
541                                 rdp_listener_activity, instance);
542         }
543
544         for( ; i < MAX_FREERDP_FDS; i++)
545                 c->listener_events[i] = 0;
546         return 0;
547 }
548
549
550 static void
551 rdp_peer_context_new(freerdp_peer* client, RdpPeerContext* context)
552 {
553         context->item.peer = client;
554         context->item.flags = 0;
555
556         context->rfx_context = rfx_context_new();
557         context->rfx_context->mode = RLGR3;
558         context->rfx_context->width = client->settings->DesktopWidth;
559         context->rfx_context->height = client->settings->DesktopHeight;
560         rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
561
562         context->nsc_context = nsc_context_new();
563         rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
564
565         context->encode_stream = stream_new(65536);
566 }
567
568 static void
569 rdp_peer_context_free(freerdp_peer* client, RdpPeerContext* context)
570 {
571         int i;
572         if(!context)
573                 return;
574
575         wl_list_remove(&context->item.link);
576         for(i = 0; i < MAX_FREERDP_FDS; i++) {
577                 if(context->fds[i] != -1)
578                         wl_event_source_remove(context->events[i]);
579         }
580
581         if(context->item.flags & RDP_PEER_ACTIVATED)
582                 weston_seat_release(&context->item.seat);
583         stream_free(context->encode_stream);
584         nsc_context_free(context->nsc_context);
585         rfx_context_free(context->rfx_context);
586         free(context->rfx_rects);
587 }
588
589
590 static int
591 rdp_client_activity(int fd, uint32_t mask, void *data) {
592         freerdp_peer* client = (freerdp_peer *)data;
593
594         if (!client->CheckFileDescriptor(client)) {
595                 weston_log("unable to checkDescriptor for %p\n", client);
596                 goto out_clean;
597         }
598         return 0;
599
600 out_clean:
601         freerdp_peer_context_free(client);
602         freerdp_peer_free(client);
603         return 0;
604 }
605
606 static BOOL
607 xf_peer_capabilities(freerdp_peer* client)
608 {
609         return TRUE;
610 }
611
612
613 struct rdp_to_xkb_keyboard_layout {
614         UINT32 rdpLayoutCode;
615         char *xkbLayout;
616 };
617
618 /* picked from http://technet.microsoft.com/en-us/library/cc766503(WS.10).aspx */
619 static struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
620         {0x00000406, "dk"},
621         {0x00000407, "de"},
622         {0x00000409, "us"},
623         {0x0000040c, "fr"},
624         {0x00000410, "it"},
625         {0x00000813, "be"},
626         {0x00000000, 0},
627 };
628
629 /* taken from 2.2.7.1.6 Input Capability Set (TS_INPUT_CAPABILITYSET) */
630 static char *rdp_keyboard_types[] = {
631         "",     /* 0: unused */
632         "", /* 1: IBM PC/XT or compatible (83-key) keyboard */
633         "", /* 2: Olivetti "ICO" (102-key) keyboard */
634         "", /* 3: IBM PC/AT (84-key) or similar keyboard */
635         "pc102",/* 4: IBM enhanced (101- or 102-key) keyboard */
636         "", /* 5: Nokia 1050 and similar keyboards */
637         "",     /* 6: Nokia 9140 and similar keyboards */
638         ""      /* 7: Japanese keyboard */
639 };
640
641 static BOOL
642 xf_peer_post_connect(freerdp_peer* client)
643 {
644         RdpPeerContext *peerCtx;
645         struct rdp_compositor *c;
646         struct rdp_output *output;
647         rdpSettings *settings;
648         struct xkb_context *xkbContext;
649         struct xkb_rule_names xkbRuleNames;
650         struct xkb_keymap *keymap;
651         int i;
652
653         peerCtx = (RdpPeerContext *)client->context;
654         c = peerCtx->rdpCompositor;
655         output = c->output;
656         settings = client->settings;
657
658         if(!settings->SurfaceCommandsEnabled) {
659                 weston_log("client doesn't support required SurfaceCommands\n");
660                 return FALSE;
661         }
662
663         if(output->base.width != (int)settings->DesktopWidth ||
664                         output->base.height != (int)settings->DesktopHeight)
665         {
666                 if(!settings->DesktopResize) {
667                         weston_log("client don't support desktopResize()\n");
668                         return FALSE;
669                 }
670
671                 /* force the client size */
672                 settings->DesktopWidth = output->base.width;
673                 settings->DesktopHeight = output->base.height;
674                 client->update->DesktopResize(client->context);
675         }
676
677         weston_log("kbd_layout:%x kbd_type:%x kbd_subType:%x kbd_functionKeys:%x\n",
678                         settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType,
679                         settings->KeyboardFunctionKey);
680
681         memset(&xkbRuleNames, 0, sizeof(xkbRuleNames));
682         if(settings->KeyboardType <= 7)
683                 xkbRuleNames.model = rdp_keyboard_types[settings->KeyboardType];
684         for(i = 0; rdp_keyboards[i].xkbLayout; i++) {
685                 if(rdp_keyboards[i].rdpLayoutCode == settings->KeyboardLayout) {
686                         xkbRuleNames.layout = rdp_keyboards[i].xkbLayout;
687                         break;
688                 }
689         }
690
691         keymap = NULL;
692         if(xkbRuleNames.layout) {
693                 xkbContext = xkb_context_new(0);
694                 if(!xkbContext) {
695                         weston_log("unable to create a xkb_context\n");
696                         return FALSE;
697                 }
698
699                 keymap = xkb_keymap_new_from_names(xkbContext, &xkbRuleNames, 0);
700         }
701         weston_seat_init_keyboard(&peerCtx->item.seat, keymap);
702         weston_seat_init_pointer(&peerCtx->item.seat);
703
704         peerCtx->item.flags |= RDP_PEER_ACTIVATED;
705         return TRUE;
706 }
707
708 static BOOL
709 xf_peer_activate(freerdp_peer *client)
710 {
711         return TRUE;
712 }
713
714 static void
715 xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) {
716         wl_fixed_t wl_x, wl_y;
717         RdpPeerContext *peerContext = (RdpPeerContext *)input->context;
718         struct rdp_output *output;
719         uint32_t button = 0;
720
721         if (flags & PTR_FLAGS_MOVE) {
722                 output = peerContext->rdpCompositor->output;
723                 if(x < output->base.width && y < output->base.height) {
724                         wl_x = wl_fixed_from_int((int)x);
725                         wl_y = wl_fixed_from_int((int)y);
726                         notify_motion_absolute(&peerContext->item.seat, weston_compositor_get_time(),
727                                         wl_x, wl_y);
728                 }
729         }
730
731         if (flags & PTR_FLAGS_BUTTON1)
732                 button = BTN_LEFT;
733         else if (flags & PTR_FLAGS_BUTTON2)
734                 button = BTN_RIGHT;
735         else if (flags & PTR_FLAGS_BUTTON3)
736                 button = BTN_MIDDLE;
737
738         if(button) {
739                 notify_button(&peerContext->item.seat, weston_compositor_get_time(), button,
740                         (flags & PTR_FLAGS_DOWN) ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED
741                 );
742         }
743 }
744
745 static void
746 xf_extendedMouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y) {
747         wl_fixed_t wl_x, wl_y;
748         RdpPeerContext *peerContext = (RdpPeerContext *)input->context;
749         struct rdp_output *output;
750
751         output = peerContext->rdpCompositor->output;
752         if(x < output->base.width && y < output->base.height) {
753                 wl_x = wl_fixed_from_int((int)x);
754                 wl_y = wl_fixed_from_int((int)y);
755                 notify_motion_absolute(&peerContext->item.seat, weston_compositor_get_time(),
756                                 wl_x, wl_y);
757         }
758 }
759
760
761 static void
762 xf_input_synchronize_event(rdpInput *input, UINT32 flags)
763 {
764         freerdp_peer *client = input->context->peer;
765         rdpPointerUpdate *pointer = client->update->pointer;
766         RdpPeerContext *peerCtx = (RdpPeerContext *)input->context;
767         struct rdp_output *output = peerCtx->rdpCompositor->output;
768         pixman_box32_t box;
769         pixman_region32_t damage;
770
771         /* disable pointer on the client side */
772         pointer->pointer_system.type = SYSPTR_NULL;
773         pointer->PointerSystem(client->context, &pointer->pointer_system);
774
775         /* sends a full refresh */
776         box.x1 = 0;
777         box.y1 = 0;
778         box.x2 = output->base.width;
779         box.y2 = output->base.height;
780         pixman_region32_init_with_extents(&damage, &box);
781
782         rdp_peer_refresh_region(&damage, client);
783
784         pixman_region32_fini(&damage);
785 }
786
787 extern DWORD KEYCODE_TO_VKCODE_EVDEV[];
788 static uint32_t vk_to_keycode[256];
789 static void
790 init_vk_translator(void)
791 {
792         int i;
793
794         memset(vk_to_keycode, 0, sizeof(vk_to_keycode));
795         for(i = 0; i < 256; i++)
796                 vk_to_keycode[KEYCODE_TO_VKCODE_EVDEV[i] & 0xff] = i-8;
797 }
798
799 static void
800 xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
801 {
802         uint32_t scan_code, vk_code, full_code;
803         enum wl_keyboard_key_state keyState;
804         RdpPeerContext *peerContext = (RdpPeerContext *)input->context;
805         int notify = 0;
806
807         if (flags & KBD_FLAGS_DOWN) {
808                 keyState = WL_KEYBOARD_KEY_STATE_PRESSED;
809                 notify = 1;
810         } else if (flags & KBD_FLAGS_RELEASE) {
811                 keyState = WL_KEYBOARD_KEY_STATE_RELEASED;
812                 notify = 1;
813         }
814
815         if(notify) {
816                 full_code = code;
817                 if(flags & KBD_FLAGS_EXTENDED)
818                         full_code |= KBD_FLAGS_EXTENDED;
819
820                 vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, 4);
821                 if(vk_code > 0xff) {
822                         weston_log("invalid vk_code %x", vk_code);
823                         return;
824                 }
825                 scan_code = vk_to_keycode[vk_code];
826
827
828                 /*weston_log("code=%x ext=%d vk_code=%x scan_code=%x\n", code, (flags & KBD_FLAGS_EXTENDED) ? 1 : 0,
829                                 vk_code, scan_code);*/
830                 notify_key(&peerContext->item.seat, weston_compositor_get_time(),
831                                         scan_code, keyState, STATE_UPDATE_AUTOMATIC);
832         }
833 }
834
835 static void
836 xf_input_unicode_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
837 {
838         weston_log("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
839 }
840
841
842 static void
843 xf_suppress_output(rdpContext *context, BYTE allow, RECTANGLE_16 *area) {
844         RdpPeerContext *peerContext = (RdpPeerContext *)context;
845         if(allow)
846                 peerContext->item.flags |= RDP_PEER_OUTPUT_ENABLED;
847         else
848                 peerContext->item.flags &= (~RDP_PEER_OUTPUT_ENABLED);
849 }
850
851 static int
852 rdp_peer_init(freerdp_peer *client, struct rdp_compositor *c)
853 {
854         int rcount = 0;
855         void *rfds[MAX_FREERDP_FDS];
856         int i, fd;
857         struct wl_event_loop *loop;
858         rdpSettings     *settings;
859         rdpInput *input;
860         RdpPeerContext *peerCtx;
861
862         client->context_size = sizeof(RdpPeerContext);
863         client->ContextNew = (psPeerContextNew)rdp_peer_context_new;
864         client->ContextFree = (psPeerContextFree)rdp_peer_context_free;
865         freerdp_peer_context_new(client);
866
867         peerCtx = (RdpPeerContext *) client->context;
868         peerCtx->rdpCompositor = c;
869
870         settings = client->settings;
871         settings->RdpKeyFile = c->rdp_key;
872         if(c->tls_enabled) {
873                 settings->CertificateFile = c->server_cert;
874                 settings->PrivateKeyFile = c->server_key;
875         } else {
876                 settings->TlsSecurity = FALSE;
877         }
878
879         settings->NlaSecurity = FALSE;
880
881         client->Capabilities = xf_peer_capabilities;
882         client->PostConnect = xf_peer_post_connect;
883         client->Activate = xf_peer_activate;
884
885         client->update->SuppressOutput = xf_suppress_output;
886
887         input = client->input;
888         input->SynchronizeEvent = xf_input_synchronize_event;
889         input->MouseEvent = xf_mouseEvent;
890         input->ExtendedMouseEvent = xf_extendedMouseEvent;
891         input->KeyboardEvent = xf_input_keyboard_event;
892         input->UnicodeKeyboardEvent = xf_input_unicode_keyboard_event;
893         weston_seat_init(&peerCtx->item.seat, &c->base);
894
895         client->Initialize(client);
896
897         if (!client->GetFileDescriptor(client, rfds, &rcount)) {
898                 weston_log("unable to retrieve client fds\n");
899                 return -1;
900         }
901
902         loop = wl_display_get_event_loop(c->base.wl_display);
903         for(i = 0; i < rcount; i++) {
904                 fd = (int)(long)(rfds[i]);
905
906                 peerCtx->fds[i] = fd;
907                 peerCtx->events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
908                                 rdp_client_activity, client);
909         }
910         for( ; i < MAX_FREERDP_FDS; i++) {
911                 peerCtx->fds[i] = -1;
912                 peerCtx->events[i] = 0;
913         }
914
915         wl_list_insert(&c->output->peers, &peerCtx->item.link);
916         return 0;
917 }
918
919
920 static void
921 rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client)
922 {
923         struct rdp_compositor *c = (struct rdp_compositor *)instance->param4;
924         if (rdp_peer_init(client, c) < 0)
925                 return;
926 }
927
928 static struct weston_compositor *
929 rdp_compositor_create(struct wl_display *display,
930                 struct rdp_compositor_config *config,
931                 int *argc, char *argv[], const char *config_file)
932 {
933         struct rdp_compositor *c;
934         char *fd_str;
935         int fd;
936
937         c = malloc(sizeof *c);
938         if (c == NULL)
939                 return NULL;
940
941         memset(c, 0, sizeof *c);
942
943         if (weston_compositor_init(&c->base, display, argc, argv,
944                                    config_file) < 0)
945                 goto err_free;
946
947         weston_seat_init(&c->main_seat, &c->base);
948         c->base.destroy = rdp_destroy;
949         c->base.restore = rdp_restore;
950         c->rdp_key = config->rdp_key ? strdup(config->rdp_key) : NULL;
951
952         /* activate TLS only if certificate/key are available */
953         if(config->server_cert && config->server_key) {
954                 weston_log("TLS support activated\n");
955                 c->server_cert = strdup(config->server_cert);
956                 c->server_key = strdup(config->server_key);
957                 if(!c->server_cert || !c->server_key)
958                         goto err_free_strings;
959                 c->tls_enabled = 1;
960         }
961
962         if (pixman_renderer_init(&c->base) < 0)
963                 goto err_compositor;
964
965         if (rdp_compositor_create_output(c, config->width, config->height, config->extra_modes) < 0)
966                 goto err_compositor;
967
968         if(!config->env_socket) {
969                 c->listener = freerdp_listener_new();
970                 c->listener->PeerAccepted = rdp_incoming_peer;
971                 c->listener->param4 = c;
972                 if(!c->listener->Open(c->listener, config->bind_address, config->port)) {
973                         weston_log("unable to bind rdp socket\n");
974                         goto err_listener;
975                 }
976
977                 if (rdp_implant_listener(c, c->listener) < 0)
978                         goto err_compositor;
979         } else {
980                 /* get the socket from RDP_FD var */
981                 fd_str = getenv("RDP_FD");
982                 if(!fd_str) {
983                         weston_log("RDP_FD env variable not set");
984                         goto err_output;
985                 }
986
987                 fd = strtoul(fd_str, NULL, 10);
988                 if(rdp_peer_init(freerdp_peer_new(fd), c))
989                         goto err_output;
990         }
991
992         return &c->base;
993
994 err_listener:
995         freerdp_listener_free(c->listener);
996 err_output:
997         weston_output_destroy(&c->output->base);
998 err_compositor:
999         weston_compositor_shutdown(&c->base);
1000 err_free_strings:
1001         if(c->rdp_key)
1002                 free(c->rdp_key);
1003         if(c->server_cert)
1004                 free(c->server_cert);
1005         if(c->server_key)
1006                 free(c->server_key);
1007         weston_seat_release(&c->main_seat);
1008 err_free:
1009         free(c);
1010         return NULL;
1011 }
1012
1013 WL_EXPORT struct weston_compositor *
1014 backend_init(struct wl_display *display, int *argc, char *argv[],
1015              const char *config_file)
1016 {
1017         struct rdp_compositor_config config;
1018         rdp_compositor_config_init(&config);
1019         int major, minor, revision;
1020
1021         freerdp_get_version(&major, &minor, &revision);
1022         weston_log("using FreeRDP version %d.%d.%d\n", major, minor, revision);
1023         init_vk_translator();
1024
1025         const struct weston_option rdp_options[] = {
1026                 { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
1027                 { WESTON_OPTION_INTEGER, "width", 0, &config.width },
1028                 { WESTON_OPTION_INTEGER, "height", 0, &config.height },
1029                 { WESTON_OPTION_STRING,  "extra-modes", 0, &config.extra_modes },
1030                 { WESTON_OPTION_STRING,  "address", 0, &config.bind_address },
1031                 { WESTON_OPTION_INTEGER, "port", 0, &config.port },
1032                 { WESTON_OPTION_STRING,  "rdp4-key", 0, &config.rdp_key },
1033                 { WESTON_OPTION_STRING,  "rdp-tls-cert", 0, &config.server_cert },
1034                 { WESTON_OPTION_STRING,  "rdp-tls-key", 0, &config.server_key }
1035         };
1036
1037         parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
1038         return rdp_compositor_create(display, &config, argc, argv, config_file);
1039 }