Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2# This file is part of Xpra. 

3# Copyright (C) 2015-2019 Antoine Martin <antoine@xpra.org> 

4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any 

5# later version. See the file COPYING for details. 

6 

7from collections import namedtuple 

8import dbus.service 

9 

10from xpra.dbus.helper import dbus_to_native, native_to_dbus 

11from xpra.dbus.common import init_session_bus 

12from xpra.server.dbus.dbus_server_base import DBUS_Server_Base, INTERFACE, BUS_NAME 

13from xpra.util import parse_scaling_value, from0to100, DETACH_REQUEST 

14from xpra.log import ( 

15 Logger, 

16 add_debug_category, remove_debug_category, 

17 disable_debug_for, enable_debug_for, 

18 ) 

19log = Logger("dbus", "server") 

20 

21 

22Rectangle = namedtuple("Workarea", "x,y,width,height") 

23 

24 

25def n(*args): 

26 return dbus_to_native(*args) 

27def ni(*args): 

28 return int(n(*args)) 

29def ns(*args): 

30 return str(n(*args)) 

31def nb(*args): 

32 return bool(n(*args)) 

33 

34 

35class DBUS_Server(DBUS_Server_Base): 

36 

37 def __init__(self, server=None, extra=""): 

38 bus = init_session_bus() 

39 name = BUS_NAME 

40 if extra: 

41 name += extra.replace(".", "_").replace(":", "_") 

42 super().__init__(bus, server, name) 

43 self._properties.update({ 

44 "idle-timeout" : ("idle_timeout", ni), 

45 "server-idle-timeout" : ("server_idle_timeout", ni), 

46 "name" : ("session_name", ns), 

47 }) 

48 

49 

50 @dbus.service.method(INTERFACE, in_signature='i') 

51 def Focus(self, wid): 

52 wid = ni(wid) 

53 self.log(".Focus(%i)", wid) 

54 self.server.control_command_focus(wid) 

55 

56 @dbus.service.method(INTERFACE, in_signature='') 

57 def Suspend(self): 

58 self.log(".Suspend()") 

59 self.server.control_command_suspend() 

60 

61 @dbus.service.method(INTERFACE, in_signature='') 

62 def Resume(self): 

63 self.log(".Resume()") 

64 self.server.control_command_resume() 

65 

66 @dbus.service.method(INTERFACE, in_signature='') 

67 def Ungrab(self): 

68 self.log(".Ungrab()") 

69 self.server.control_command_resume() 

70 

71 

72 @dbus.service.method(INTERFACE, in_signature='s') 

73 def Start(self, command): 

74 c = ns(command) 

75 self.log(".Start(%s)", c) 

76 self.server.do_control_command_start(True, c) 

77 

78 @dbus.service.method(INTERFACE, in_signature='s') 

79 def StartChild(self, command): 

80 c = ns(command) 

81 self.log(".StartChild(%s)", c) 

82 self.server.do_control_command_start(False, c) 

83 

84 @dbus.service.method(INTERFACE, in_signature='sb') 

85 def ToggleFeature(self, feature, state): 

86 f, s = ns(feature), ns(state) 

87 self.log(".ToggleFeature(%s, %s)", f, s) 

88 self.server.control_command_toggle_feature(f, s) 

89 

90 

91 @dbus.service.method(INTERFACE, in_signature='i') 

92 def KeyPress(self, keycode): 

93 k = ni(keycode) 

94 self.log(".KeyPress(%i)", k) 

95 self.server.control_command_key(str(k), press=True) 

96 

97 @dbus.service.method(INTERFACE, in_signature='i') 

98 def KeyRelease(self, keycode): 

99 k = ni(keycode) 

100 self.log(".KeyRelease(%i)", k) 

101 self.server.control_command_key(str(k), press=False) 

102 

103 @dbus.service.method(INTERFACE, in_signature='') 

104 def ClearKeysPressed(self): 

105 self.log(".ClearKeysPressed()") 

106 self.server.clear_keys_pressed() 

107 

108 @dbus.service.method(INTERFACE, in_signature='ii') 

109 def SetKeyboardRepeat(self, repeat_delay, repeat_interval): 

110 d, i = ni(repeat_delay), ni(repeat_interval) 

111 self.log(".SetKeyboardRepeat(%i, %i)", d, i) 

112 self.server.set_keyboard_repeat(d, i) 

113 

114 

115 @dbus.service.method(INTERFACE, in_signature='iii') 

116 def MovePointer(self, wid, x, y): 

117 wid, x, y = ni(wid), ni(x), ni(y) 

118 self.log(".MovePointer(%i, %i, %i)", wid, x, y) 

119 self.server._move_pointer(ni(wid), (ni(x), ni(y))) 

120 

121 @dbus.service.method(INTERFACE, in_signature='ib') 

122 def MouseClick(self, button, pressed): 

123 button, pressed = ni(button), nb(pressed) 

124 self.log(".MouseClick%s", (button, pressed)) 

125 device_id = -1 

126 self.server.button_action(None, button, pressed, device_id) 

127 

128 

129 @dbus.service.method(INTERFACE, in_signature='iiii') 

130 def SetWorkarea(self, x, y, w, h): 

131 x, y, w, h = ni(x), ni(y), ni(w), ni(h) 

132 self.log(".SetWorkarea%s", (x, y, w, h)) 

133 workarea = Rectangle(x=x, y=y, width=w, height=h) 

134 self.server.set_workarea(workarea) 

135 

136 

137 @dbus.service.method(INTERFACE, in_signature='iiiii') 

138 def SetVideoRegion(self, wid, x, y, w, h): 

139 wid, x, y, w, h = ni(wid), ni(x), ni(y), ni(w), ni(h) 

140 self.log(".SetVideoRegion%s", (wid, x, y, w, h)) 

141 self.server.control_command_video_region(wid, x, y, w, h) 

142 

143 @dbus.service.method(INTERFACE, in_signature='ib') 

144 def SetVideoRegionEnabled(self, wid, enabled): 

145 wid, enabled = ni(wid), nb(enabled) 

146 self.log(".SetVideoRegionEnabled(%i, %s)", wid, enabled) 

147 self.server.control_command_video_region_enabled(wid, enabled) 

148 

149 @dbus.service.method(INTERFACE, in_signature='ib') 

150 def SetVideoRegionDetection(self, wid, detection): 

151 wid, detection = ni(wid), nb(detection) 

152 self.log(".SetVideoRegionDetection(%i, %s)", wid, detection) 

153 self.server.control_command_video_region_detection(wid, detection) 

154 

155 @dbus.service.method(INTERFACE, in_signature='iaai') 

156 def SetVideoRegionExclusionZones(self, wid, zones): 

157 wid = ni(wid) 

158 nzones = [] 

159 for zone in zones: 

160 nzones.append([ni(x) for x in zone]) 

161 log("SetVideoRegionExclusionZones(%i, %s)", wid, nzones) 

162 self.server.control_command_video_region_exclusion_zones(wid, nzones) 

163 

164 @dbus.service.method(INTERFACE, in_signature='i') 

165 def ResetVideoRegion(self, wid): 

166 wid = ni(wid) 

167 self.log(".ResetVideoRegion(%i)", wid) 

168 self.server.control_command_reset_video_region(wid) 

169 

170 

171 

172 @dbus.service.method(INTERFACE, in_signature='ii') 

173 def LockBatchDelay(self, wid, delay): 

174 wid, delay = ni(wid), ni(delay) 

175 self.log(".LockBatchDelay(%i, %i)", wid, delay) 

176 self.server.control_command_lock_batch_delay(wid, delay) 

177 

178 @dbus.service.method(INTERFACE, in_signature='i') 

179 def UnlockBatchDelay(self, wid): 

180 wid = ni(wid) 

181 self.log(".UnlockBatchDelay(%i)", wid) 

182 self.server.control_command_unlock_batch_delay(wid) 

183 

184 

185 @dbus.service.method(INTERFACE, in_signature='', out_signature='a{is}') 

186 def ListWindows(self): 

187 d = {} 

188 for wid, window in self.server._id_to_window.items(): 

189 try: 

190 d[wid] = window.get_property("title") 

191 except Exception: # pragma: no cover 

192 d[wid] = str(window) 

193 self.log(".ListWindows()=%s", d) 

194 return d 

195 

196 

197 @dbus.service.method(INTERFACE, in_signature='s') 

198 def SetLock(self, lock): 

199 s = ns(lock) 

200 self.log(".SetLock(%s)", s) 

201 self.server.control_command_set_lock(s) 

202 

203 @dbus.service.method(INTERFACE, in_signature='s') 

204 def SetSharing(self, sharing): 

205 s = ns(sharing) 

206 self.log(".SetSharing(%s)", s) 

207 self.server.control_command_set_sharing(s) 

208 

209 

210 @dbus.service.method(INTERFACE, in_signature='s') 

211 def SetUIDriver(self, uuid): 

212 s = ns(uuid) 

213 self.log(".SetUIDriver(%s)", s) 

214 self.server.control_command_set_ui_driver(s) 

215 

216 

217 @dbus.service.method(INTERFACE, in_signature='i') 

218 def SetIdleTimeout(self, value): 

219 nvalue = ni(value) 

220 self.log(".SetIdleTimeout(%s)", nvalue) 

221 self.server.control_command_idle_timeout(nvalue) 

222 

223 

224 @dbus.service.method(INTERFACE, in_signature='ii') 

225 def MoveWindowToWorkspace(self, wid, workspace): 

226 wid, workspace = ni(wid), ni(workspace) 

227 self.log(".MoveWindowToWorkspace(%i, %i)", wid, workspace) 

228 self.server.control_command_workspace(wid, workspace) 

229 

230 @dbus.service.method(INTERFACE, in_signature='is') 

231 def SetWindowScaling(self, wid, scaling): 

232 wid, scaling = ni(wid), ns(scaling) 

233 self.log(".SetWindowScaling(%i, %s)", wid, scaling) 

234 s = parse_scaling_value(scaling) 

235 self.server.control_command_scaling(s, wid) 

236 

237 @dbus.service.method(INTERFACE, in_signature='is') 

238 def SetWindowScalingControl(self, wid, scaling_control): 

239 wid = ni(wid) 

240 self.log(".SetWindowScalingControl(%i, %s)", wid, scaling_control) 

241 if scaling_control.lower() in ("auto", "on"): 

242 sc = None 

243 else: 

244 sc = from0to100(int(ns(scaling_control))) 

245 self.server.control_command_scaling_control(sc, wid) 

246 

247 @dbus.service.method(INTERFACE, in_signature='is') 

248 def SetWindowEncoding(self, wid, encoding): 

249 wid, encoding = ni(wid), ns(encoding) 

250 self.log(".SetWindowEncoding(%i, %s)", wid, encoding) 

251 self.server.control_command_encoding(encoding, wid) 

252 

253 @dbus.service.method(INTERFACE, in_signature='i') 

254 def RefreshWindow(self, wid): 

255 wid = ni(wid) 

256 self.log(".RefreshWindow(%i)", wid) 

257 self.server.control_command_refresh(wid) 

258 

259 

260 @dbus.service.method(INTERFACE, in_signature='ai') 

261 def RefreshWindows(self, window_ids): 

262 wids = [ni(x) for x in window_ids] 

263 self.log(".RefreshWindows(%s)", wids) 

264 self.server.control_command_refresh(*wids) 

265 

266 @dbus.service.method(INTERFACE, in_signature='') 

267 def RefreshAllWindows(self): 

268 self.log(".RefreshAllWindows()") 

269 self.server.control_command_refresh(*self.server._id_to_window.keys()) 

270 

271 

272 @dbus.service.method(INTERFACE, in_signature='') 

273 def ResetWindowFilters(self): 

274 self.log(".ResetWindowFilters()") 

275 self.server.reset_window_filters() 

276 

277 

278 @dbus.service.method(INTERFACE, in_signature='s') 

279 def EnableDebug(self, category): 

280 c = ns(category) 

281 self.log(".EnableDebug(%s)", c) 

282 add_debug_category(c) 

283 enable_debug_for(c) 

284 

285 @dbus.service.method(INTERFACE, in_signature='s') 

286 def DisableDebug(self, category): 

287 c = ns(category) 

288 self.log(".DisableDebug(%s)", c) 

289 remove_debug_category(c) 

290 disable_debug_for(c) 

291 

292 

293 @dbus.service.method(INTERFACE, in_signature='isss') 

294 def SendNotification(self, nid, title, message, uuids): 

295 nid, title, message, uuids = ni(nid), ns(title), ns(message), ns(uuids) 

296 self.log(".SendNotification%s", (nid, title, message, uuids)) 

297 self.server.control_command_send_notification(nid, title, message, uuids) 

298 

299 @dbus.service.method(INTERFACE, in_signature='is') 

300 def CloseNotification(self, nid, uuids): 

301 nid, uuids = ni(nid), ns(uuids) 

302 self.log(".CloseNotification%s", (nid, uuids)) 

303 self.server.control_command_close_notification(nid, uuids) 

304 

305 

306 @dbus.service.method(INTERFACE, in_signature='sii') 

307 def SetClipboardProperties(self, direction, max_copyin, max_copyout): 

308 #keep direction unchanged if not specified 

309 max_copyin, max_copyout = ni(max_copyin), ni(max_copyout) 

310 direction = ns(direction) or self.server.clipboard_direction 

311 self.log(".SetClipboardProperties%s", (direction, max_copyin, max_copyout)) 

312 self.server.control_command_clipboard_direction(direction, max_copyin, max_copyout) 

313 

314 

315 @dbus.service.method(INTERFACE, in_signature='', out_signature='a{ss}') 

316 def ListClients(self): 

317 d = {} 

318 for p, source in self.server._server_sources.items(): 

319 try: 

320 d[source.uuid] = str(p) 

321 except KeyError: 

322 d[str(source)] = str(p) 

323 self.log(".ListClients()=%s", d) 

324 return d 

325 

326 @dbus.service.method(INTERFACE, in_signature='s') 

327 def DetachClient(self, uuid): 

328 s = ns(uuid) 

329 self.log(".DetachClient(%s)", s) 

330 for p, source in self.server._server_sources.items(): 

331 if source.uuid==s: 

332 self.log("matched %s", source) 

333 self.server.disconnect_client(p, DETACH_REQUEST) 

334 

335 @dbus.service.method(INTERFACE) 

336 def DetachAllClients(self): 

337 self.log(".DetachAllClients() will detach: %s", self.server._server_sources) 

338 for p in self.server._server_sources.keys(): 

339 self.server.disconnect_client(p, DETACH_REQUEST) 

340 

341 

342 @dbus.service.method(INTERFACE, in_signature='as') 

343 def SendUIClientCommand(self, args): 

344 nargs = n(args) 

345 log("SendUIClientCommand(%s)", nargs) 

346 for src in self.server._server_sources.values(): 

347 if src.ui_client: 

348 src.send_client_command(*nargs) 

349 

350 

351 @dbus.service.method(INTERFACE, in_signature='', out_signature='a{sv}', async_callbacks=("callback", "errback")) 

352 def GetAllInfo(self, callback, errback): 

353 self.log(".GetAllInfo()") 

354 def gotinfo(_proto, info): 

355 try: 

356 v = dbus.types.Dictionary((str(k), native_to_dbus(v)) for k,v in info.items()) 

357 #v = native_to_dbus(info) 

358 log("native_to_dbus(..)=%s", v) 

359 callback(v) 

360 except Exception as e: # pragma: no cover 

361 log("GetAllInfo:gotinfo", exc_info=True) 

362 errback(str(e)) 

363 v = self.server.get_all_info(gotinfo) 

364 self.log(".GetAllInfo()=%s", v) 

365 return v 

366 

367 @dbus.service.method(INTERFACE, in_signature='s', out_signature='a{sv}', async_callbacks=("callback", "errback")) 

368 def GetInfo(self, subsystem, callback, errback): 

369 self.log(".GetInfo(%s)", subsystem) 

370 def gotinfo(_proto, info): 

371 sub = info.get(subsystem) 

372 try: 

373 v = dbus.types.Dictionary((str(k), native_to_dbus(v)) for k,v in sub.items()) 

374 log("native_to_dbus(..)=%s", v) 

375 callback(v) 

376 except Exception as e: # pragma: no cover 

377 log("GetInfo:gotinfo", exc_info=True) 

378 errback(str(e)) 

379 v = self.server.get_all_info(gotinfo) 

380 self.log(".GetInfo(%s)=%s", subsystem, v) 

381 return v