From 1800bd57b3543a87bc6ecbcc5a758c1b64a0e97c Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Mon, 26 Jan 2015 16:20:13 +0000 Subject: [PATCH] #775: forward _NET_SHOWING_DESKTOP and implement it for both X11 and win32 git-svn-id: https://xpra.org/svn/Xpra/trunk@8554 3bb7dfac-3a0b-4e04-842a-767bc560f471 --- src/tests/xpra/test_apps/test_show_desktop.py | 46 +++++++++++++++++++ src/xpra/client/ui_client_base.py | 10 +++- src/xpra/platform/gui.py | 5 ++ src/xpra/platform/win32/gui.py | 15 ++++++ src/xpra/platform/xposix/gui.py | 15 ++++++ src/xpra/server/source.py | 6 +++ src/xpra/x11/gtk_x11/wm.py | 4 ++ src/xpra/x11/server.py | 6 +++ 8 files changed, 106 insertions(+), 1 deletion(-) create mode 100755 src/tests/xpra/test_apps/test_show_desktop.py diff --git a/src/tests/xpra/test_apps/test_show_desktop.py b/src/tests/xpra/test_apps/test_show_desktop.py new file mode 100755 index 0000000000..31aa290eab --- /dev/null +++ b/src/tests/xpra/test_apps/test_show_desktop.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +import gtk + +width = 400 +height = 200 +def main(): + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + #window = gtk.Window(gtk.WINDOW_POPUP) + window.set_size_request(width, height) + window.connect("delete_event", gtk.mainquit) + vbox = gtk.VBox() + + def send_net_showing_desktop(v): + from xpra.x11.gtk_x11 import gdk_display_source + assert gdk_display_source + from xpra.gtk_common.gobject_compat import get_xid + from xpra.x11.bindings.window_bindings import constants, X11WindowBindings #@UnresolvedImport + X11Window = X11WindowBindings() + root = window.get_window().get_screen().get_root_window() + root_xid = get_xid(root) + SubstructureNotifyMask = constants["SubstructureNotifyMask"] + SubstructureRedirectMask = constants["SubstructureRedirectMask"] + event_mask = SubstructureNotifyMask | SubstructureRedirectMask + X11Window.sendClientMessage(root_xid, root_xid, False, event_mask, "_NET_SHOWING_DESKTOP", v) + + b = gtk.Button("Show Desktop") + def show_desktop(*args): + send_net_showing_desktop(1) + b.connect('clicked', show_desktop) + vbox.add(b) + + b = gtk.Button("Not Show Desktop") + def not_show_desktop(*args): + send_net_showing_desktop(0) + b.connect('clicked', not_show_desktop) + vbox.add(b) + + window.add(vbox) + window.show_all() + gtk.main() + return 0 + + +if __name__ == "__main__": + main() diff --git a/src/xpra/client/ui_client_base.py b/src/xpra/client/ui_client_base.py index 638c9e67c1..b1a465e262 100644 --- a/src/xpra/client/ui_client_base.py +++ b/src/xpra/client/ui_client_base.py @@ -32,7 +32,7 @@ from xpra.client.keyboard_helper import KeyboardHelper from xpra.platform import set_application_name from xpra.platform.features import MMAP_SUPPORTED, SYSTEM_TRAY_SUPPORTED, CLIPBOARD_WANT_TARGETS, CLIPBOARD_GREEDY, CLIPBOARDS -from xpra.platform.gui import (ready as gui_ready, get_vrefresh, get_antialias_info, get_double_click_time, +from xpra.platform.gui import (ready as gui_ready, get_vrefresh, get_antialias_info, get_double_click_time, show_desktop, get_double_click_distance, get_native_notifier_classes, get_native_tray_classes, get_native_system_tray_classes, get_native_tray_menu_helper_classes, get_dpi, get_xdpi, get_ydpi, get_number_of_desktops, get_desktop_names, ClientExtras) from xpra.codecs.codec_constants import get_PIL_decodings @@ -967,6 +967,7 @@ def make_hello(self): "window.raise" : True, #only implemented on posix with the gtk client: "window.initiate-moveresize": False, + "show-desktop" : True, "raw_window_icons" : True, "system_tray" : self.client_supports_system_tray, "xsettings-tuple" : True, @@ -2005,6 +2006,12 @@ def _process_raise_window(self, packet): #only implemented in gtk2 for now pass + def _process_show_desktop(self, packet): + show = packet[1] + log("calling %s(%s)", show_desktop, show) + show_desktop(show) + + def _process_initiate_moveresize(self, packet): wid = packet[1] window = self._id_to_window.get(wid) @@ -2089,6 +2096,7 @@ def delhandler(k): "new-tray": self._process_new_tray, "raise-window": self._process_raise_window, "initiate-moveresize": self._process_initiate_moveresize, + "show-desktop": self._process_show_desktop, "window-move-resize": self._process_window_move_resize, "window-resized": self._process_window_resized, "cursor": self._process_cursor, diff --git a/src/xpra/platform/gui.py b/src/xpra/platform/gui.py index 907b17e41f..f98389c399 100644 --- a/src/xpra/platform/gui.py +++ b/src/xpra/platform/gui.py @@ -110,6 +110,10 @@ def remove_window_hooks(window): pass +def show_desktop(show): + pass + + def gl_check(): return None #no problem @@ -157,6 +161,7 @@ def fnames(l): "do_ready", "do_init", "gl_check", + "show_desktop", "ClientExtras", "take_screenshot", "get_native_tray_menu_helper_classes", diff --git a/src/xpra/platform/win32/gui.py b/src/xpra/platform/win32/gui.py index 5e0f1bb502..0c55926ad9 100644 --- a/src/xpra/platform/win32/gui.py +++ b/src/xpra/platform/win32/gui.py @@ -380,6 +380,21 @@ def get_window_frame_sizes(): log.warn("failed to get window frame size information: %s", e) return None +def show_desktop(b): + #not defined in win32con.. + MIN_ALL = 419 + MIN_ALL_UNDO = 416 + if bool(b): + v = MIN_ALL + else: + v = MIN_ALL_UNDO + try: + root = win32gui.FindWindow("Shell_TrayWnd", None) + assert root is not None, "cannot find 'Shell_TrayWnd'" + win32api.SendMessage(root, win32con.WM_COMMAND, v, 0) + except Exception as e: + log.warn("failed to call show_desktop(%s): %s", b, e) + class ClientExtras(object): def __init__(self, client, opts): diff --git a/src/xpra/platform/xposix/gui.py b/src/xpra/platform/xposix/gui.py index 76169e181a..2ba3e4a37f 100644 --- a/src/xpra/platform/xposix/gui.py +++ b/src/xpra/platform/xposix/gui.py @@ -286,6 +286,21 @@ def x11_bell(): return False +def show_desktop(b): + try: + from xpra.x11.gtk_x11 import gdk_display_source + assert gdk_display_source + from xpra.x11.bindings.window_bindings import constants, X11WindowBindings #@UnresolvedImport + X11Window = X11WindowBindings() + root_xid = X11Window.getDefaultRootWindow() + SubstructureNotifyMask = constants["SubstructureNotifyMask"] + SubstructureRedirectMask = constants["SubstructureRedirectMask"] + event_mask = SubstructureNotifyMask | SubstructureRedirectMask + X11Window.sendClientMessage(root_xid, root_xid, False, event_mask, "_NET_SHOWING_DESKTOP", int(bool(b))) + except Exception as e: + log.warn("failed to call show_desktop(%s): %s", b, e) + + def get_info(): from xpra.platform.gui import get_info_base i = get_info_base() diff --git a/src/xpra/server/source.py b/src/xpra/server/source.py index 8785b9163b..af5762a1dd 100644 --- a/src/xpra/server/source.py +++ b/src/xpra/server/source.py @@ -285,6 +285,7 @@ def init_vars(self): self.notify_startup_complete = False self.control_commands = [] self.metadata_supported = [] + self.show_desktop_allowed = False self.supports_transparency = False self.vrefresh = -1 self.double_click_time = -1 @@ -506,6 +507,7 @@ def parse_batch_int(value, varname): self.notify_startup_complete = c.boolget("notify-startup-complete") self.control_commands = c.strlistget("control_commands") self.metadata_supported = c.strlistget("metadata.supported", DEFAULT_METADATA_SUPPORTED) + self.show_desktop_allowed = c.boolget("show-desktop") self.vrefresh = c.intget("vrefresh", -1) self.double_click_time = c.intget("double_click.time") self.double_click_distance = c.intpair("double_click.distance") @@ -1348,6 +1350,10 @@ def updated_desktop_size(self, root_w, root_h, max_w, max_h): return False + def show_desktop(self, show): + if self.show_desktop_allowed: + self.send("show-desktop", show) + def initiate_moveresize(self, wid, window, x_root, y_root, direction, button, source_indication): if not self.can_send_window(window) or not self.window_initiate_moveresize: return diff --git a/src/xpra/x11/gtk_x11/wm.py b/src/xpra/x11/gtk_x11/wm.py index 7c94fa79cf..675f3977d3 100644 --- a/src/xpra/x11/gtk_x11/wm.py +++ b/src/xpra/x11/gtk_x11/wm.py @@ -185,6 +185,7 @@ class Wm(gobject.GObject): "new-window": one_arg_signal, # X11 bell event: "bell": one_arg_signal, + "show-desktop": one_arg_signal, # You can emit this to cause the WM to quit, or the WM may # spontaneously raise it if another WM takes over the display. By # default, unmanages all windows: @@ -370,6 +371,9 @@ def do_xpra_client_message_event(self, event): # _NET_WM_DESKTOP # _NET_WM_STATE log("do_xpra_client_message_event(%s)", event) + if event.message_type=="_NET_SHOWING_DESKTOP": + show = bool(event.data[0]) + self.emit("show-desktop", show) def _lost_wm_selection(self, selection): log.info("Lost WM selection %s, exiting", selection) diff --git a/src/xpra/x11/server.py b/src/xpra/x11/server.py index 1faef9d67c..b8d3653b33 100644 --- a/src/xpra/x11/server.py +++ b/src/xpra/x11/server.py @@ -212,6 +212,7 @@ def x11_init(self): self._wm.connect("new-window", self._new_window_signaled) self._wm.connect("bell", self._bell_signaled) self._wm.connect("quit", lambda _: self.quit(True)) + self._wm.connect("show-desktop", self._show_desktop) #save default xsettings: self.default_xsettings = XSettingsHelper().get_settings() @@ -561,6 +562,11 @@ def _bell_signaled(self, wm, event): ss.bell(wid, event.device, event.percent, event.pitch, event.duration, event.bell_class, event.bell_id, event.bell_name or "") + def _show_desktop(self, wm, show): + log("show_desktop(%s, %s)", wm, show) + for ss in self._server_sources.values(): + ss.show_desktop(show) + def _focus(self, server_source, wid, modifiers): focuslog("focus wid=%s has_focus=%s", wid, self._has_focus)