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