1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include "channels/disp.h"
21 #include "common/cursor.h"
22 #include "common/display.h"
23 #include "common/recording.h"
24 #include "input.h"
25 #include "keyboard.h"
26 #include "rdp.h"
27 #include "settings.h"
28 
29 #include <freerdp/freerdp.h>
30 #include <freerdp/input.h>
31 #include <guacamole/client.h>
32 #include <guacamole/user.h>
33 
34 #include <stdlib.h>
35 
guac_rdp_user_mouse_handler(guac_user * user,int x,int y,int mask)36 int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) {
37 
38     guac_client* client = user->client;
39     guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
40 
41     pthread_rwlock_rdlock(&(rdp_client->lock));
42 
43     /* Skip if not yet connected */
44     freerdp* rdp_inst = rdp_client->rdp_inst;
45     if (rdp_inst == NULL)
46         goto complete;
47 
48     /* Store current mouse location/state */
49     guac_common_cursor_update(rdp_client->display->cursor, user, x, y, mask);
50 
51     /* Report mouse position within recording */
52     if (rdp_client->recording != NULL)
53         guac_common_recording_report_mouse(rdp_client->recording, x, y, mask);
54 
55     /* If button mask unchanged, just send move event */
56     if (mask == rdp_client->mouse_button_mask)
57         rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_MOVE, x, y);
58 
59     /* Otherwise, send events describing button change */
60     else {
61 
62         /* Mouse buttons which have JUST become released */
63         int released_mask =  rdp_client->mouse_button_mask & ~mask;
64 
65         /* Mouse buttons which have JUST become pressed */
66         int pressed_mask  = ~rdp_client->mouse_button_mask &  mask;
67 
68         /* Release event */
69         if (released_mask & 0x07) {
70 
71             /* Calculate flags */
72             int flags = 0;
73             if (released_mask & 0x01) flags |= PTR_FLAGS_BUTTON1;
74             if (released_mask & 0x02) flags |= PTR_FLAGS_BUTTON3;
75             if (released_mask & 0x04) flags |= PTR_FLAGS_BUTTON2;
76 
77             rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
78 
79         }
80 
81         /* Press event */
82         if (pressed_mask & 0x07) {
83 
84             /* Calculate flags */
85             int flags = PTR_FLAGS_DOWN;
86             if (pressed_mask & 0x01) flags |= PTR_FLAGS_BUTTON1;
87             if (pressed_mask & 0x02) flags |= PTR_FLAGS_BUTTON3;
88             if (pressed_mask & 0x04) flags |= PTR_FLAGS_BUTTON2;
89             if (pressed_mask & 0x08) flags |= PTR_FLAGS_WHEEL | 0x78;
90             if (pressed_mask & 0x10) flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88;
91 
92             /* Send event */
93             rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
94 
95         }
96 
97         /* Scroll event */
98         if (pressed_mask & 0x18) {
99 
100             /* Down */
101             if (pressed_mask & 0x08)
102                 rdp_inst->input->MouseEvent(
103                         rdp_inst->input,
104                         PTR_FLAGS_WHEEL | 0x78,
105                         x, y);
106 
107             /* Up */
108             if (pressed_mask & 0x10)
109                 rdp_inst->input->MouseEvent(
110                         rdp_inst->input,
111                         PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88,
112                         x, y);
113 
114         }
115 
116         rdp_client->mouse_button_mask = mask;
117     }
118 
119 complete:
120     pthread_rwlock_unlock(&(rdp_client->lock));
121 
122     return 0;
123 }
124 
guac_rdp_user_key_handler(guac_user * user,int keysym,int pressed)125 int guac_rdp_user_key_handler(guac_user* user, int keysym, int pressed) {
126 
127     guac_client* client = user->client;
128     guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
129     int retval = 0;
130 
131     pthread_rwlock_rdlock(&(rdp_client->lock));
132 
133     /* Report key state within recording */
134     if (rdp_client->recording != NULL)
135         guac_common_recording_report_key(rdp_client->recording,
136                 keysym, pressed);
137 
138     /* Skip if keyboard not yet ready */
139     if (rdp_client->keyboard == NULL)
140         goto complete;
141 
142     /* Update keysym state */
143     retval = guac_rdp_keyboard_update_keysym(rdp_client->keyboard,
144                 keysym, pressed, GUAC_RDP_KEY_SOURCE_CLIENT);
145 
146 complete:
147     pthread_rwlock_unlock(&(rdp_client->lock));
148 
149     return retval;
150 
151 }
152 
guac_rdp_user_size_handler(guac_user * user,int width,int height)153 int guac_rdp_user_size_handler(guac_user* user, int width, int height) {
154 
155     guac_client* client = user->client;
156     guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
157     guac_rdp_settings* settings = rdp_client->settings;
158     freerdp* rdp_inst = rdp_client->rdp_inst;
159 
160     /* Convert client pixels to remote pixels */
161     width  = width  * settings->resolution / user->info.optimal_resolution;
162     height = height * settings->resolution / user->info.optimal_resolution;
163 
164     /* Send display update */
165     guac_rdp_disp_set_size(rdp_client->disp, settings, rdp_inst, width, height);
166 
167     return 0;
168 
169 }
170 
171