diff --git a/src/xpra/server/server_base.py b/src/xpra/server/server_base.py index 25ed4d4f6d..8452b11d54 100644 --- a/src/xpra/server/server_base.py +++ b/src/xpra/server/server_base.py @@ -1209,6 +1209,10 @@ def do_parse_screen_info(self, ss): self.set_desktop_geometry_attributes(w, h) return w, h + def set_screen_geometry_attributes(self, w, h): + #by default, use the screen as desktop area: + self.set_desktop_geometry_attributes(w, h) + def set_desktop_geometry_attributes(self, w, h): self.calculate_desktops() self.calculate_workarea(w, h) @@ -2144,7 +2148,7 @@ def _screen_size_changed(self, screen): #randr has resized the screen, tell the client (if it supports it) w, h = screen.get_width(), screen.get_height() screenlog("new screen dimensions: %ix%i", w, h) - self.set_desktop_geometry_attributes(w, h) + self.set_screen_geometry_attributes(w, h) self.idle_add(self.send_updated_screen_size) def get_root_window_size(self): diff --git a/src/xpra/x11/gtk2/models/window.py b/src/xpra/x11/gtk2/models/window.py index 23b1cffb44..b6d1cb9b4e 100644 --- a/src/xpra/x11/gtk2/models/window.py +++ b/src/xpra/x11/gtk2/models/window.py @@ -137,7 +137,7 @@ class WindowModel(BaseWindowModel): "_NET_WM_STRUT", "_NET_WM_STRUT_PARTIAL"] _MODELTYPE = "Window" - def __init__(self, parking_window, client_window): + def __init__(self, parking_window, client_window, desktop_geometry): """Register a new client window with the WM. Raises an Unmanageable exception if this window should not be @@ -147,6 +147,7 @@ def __init__(self, parking_window, client_window): super(WindowModel, self).__init__(client_window) self.parking_window = parking_window self.corral_window = None + self.desktop_geometry = desktop_geometry #extra state attributes so we can unmanage() the window cleanly: self.in_save_set = False self.client_reparented = False @@ -164,8 +165,19 @@ def setup(self): x, y, w, h, _ = self.client_window.get_geometry() # We enable PROPERTY_CHANGE_MASK so that we can call # x11_get_server_time on this window. + # clamp this window to the desktop size: + if self.desktop_geometry: + dw, dh = self.desktop_geometry + if x+w<0: + x = 10-w + elif x>=dw: + x = dw-10 + if y+h<0: + y = 10-h + elif y>dh: + y = dh-10 self.corral_window = gtk.gdk.Window(self.parking_window, - x = x, y = y, width =w, height= h, + x=x, y=y, width=w, height=h, window_type=gtk.gdk.WINDOW_CHILD, wclass=gtk.gdk.INPUT_OUTPUT, event_mask=gtk.gdk.PROPERTY_CHANGE_MASK, @@ -210,6 +222,25 @@ def setup(self): self.client_window.get_geometry() + def update_desktop_geometry(self, width, height): + if self.desktop_geometry==(width, height): + return #no need to do anything + self.desktop_geometry = (width, height) + x, y, w, h = self.corral_window.get_geometry()[:4] + nx, ny = 0, 0 + if x+w<0: + nx = 10-w + elif x>=width: + nx = width-10 + if y+h<0: + ny = 10-h + elif y>height: + ny = height-10 + if nx or ny: + log("update_desktop_geometry(%i, %i) adjusting corral window to new location: %i,%i", width, height, nx, ny) + self.corral_window.move(nx, ny) + + def _read_initial_X11_properties(self): metalog("read_initial_X11_properties() window") super(WindowModel, self)._read_initial_X11_properties() diff --git a/src/xpra/x11/gtk2/wm.py b/src/xpra/x11/gtk2/wm.py index db622903b2..49679e5f00 100644 --- a/src/xpra/x11/gtk2/wm.py +++ b/src/xpra/x11/gtk2/wm.py @@ -273,7 +273,7 @@ def __init__(self, replace_other_wm, wm_name, display=None): if (w.get_window_type() == gtk.gdk.WINDOW_FOREIGN and not X11Window.is_override_redirect(w.xid) and X11Window.is_mapped(w.xid)): - log("Wm managing pre-existing child") + log("Wm managing pre-existing child window %#x", w.xid) self._manage_client(w) # Also watch for focus change events on the root window @@ -288,6 +288,9 @@ def __init__(self, replace_other_wm, wm_name, display=None): def root_set(self, *args): prop_set(self._root, *args) + def root_get(self, *args): + return prop_get(self._root, *args) + def set_dpi(self, xdpi, ydpi): #this is used by some newer versions of the dummy driver (xf86-driver-dummy) #(and will not be honoured by anything else..) @@ -304,6 +307,9 @@ def set_desktop_geometry(self, width, height): v = [width, height] screenlog("_NET_DESKTOP_GEOMETRY=%s", v) self.root_set("_NET_DESKTOP_GEOMETRY", ["u32"], v) + #update all the windows: + for model in self._windows.values(): + model.update_desktop_geometry(width, height) def set_default_frame_extents(self, v): framelog("set_default_frame_extents(%s)", v) @@ -345,7 +351,8 @@ def _manage_client(self, gdkwindow): def do_manage_client(self, gdkwindow): try: - win = WindowModel(self._root, gdkwindow) + desktop_geometry = self.root_get("_NET_DESKTOP_GEOMETRY", ["u32"], True, False) + win = WindowModel(self._root, gdkwindow, desktop_geometry) except Unmanageable: log("Window disappeared on us, never mind") return diff --git a/src/xpra/x11/server.py b/src/xpra/x11/server.py index d2a54fb830..035ee7d5d6 100644 --- a/src/xpra/x11/server.py +++ b/src/xpra/x11/server.py @@ -303,6 +303,13 @@ def get_window_info(self, window): return info + def set_screen_geometry_attributes(self, w, h): + #only run the default code if there are no clients, + #when we have clients, this should have been done already + #in the code that synchonizes the screen resolution + if len(self._server_sources)==0: + X11ServerBase.set_screen_geometry_attributes(self, w, h) + def set_desktops(self, names): if self._wm: self._wm.set_desktop_list(names)