Skip to content

Commit

Permalink
#1284: clamp OR windows to the monitors we have
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@13669 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Sep 12, 2016
1 parent 464d927 commit 42b3837
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
67 changes: 65 additions & 2 deletions src/xpra/client/gtk_base/gtk_client_window_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def init_window(self, metadata):
self._current_frame_extents = None
self._screen = -1
self._frozen = False
self.OR_offset = None
#add platform hooks
self.on_realize_cb = {}
self.connect_after("realize", self.on_realize)
Expand Down Expand Up @@ -275,8 +276,16 @@ def focus_out(*args):

#try to honour the initial position
geomlog("setup_window() position=%s, set_initial_position=%s, OR=%s, decorated=%s", self._pos, self._set_initial_position, self.is_OR(), self.get_decorated())
if self._pos!=(0, 0) or self._set_initial_position:
if self._pos!=(0, 0) or self._set_initial_position or self.is_OR():
x,y = self._pos
if self.is_OR():
#make sure OR windows are mapped on screen
if self._client._current_screen_sizes:
w, h = self._size
self.OR_offset = self.calculate_OR_offset(x, y, w, h)
if self.OR_offset:
x += self.OR_offset[0]
y += self.OR_offset[1]
if not self.is_OR() and self.get_decorated():
#try to adjust for window frame size if we can figure it out:
#Note: we cannot just call self.get_window_frame_size() here because
Expand All @@ -296,6 +305,51 @@ def focus_out(*args):
self.move(x, y)
self.set_default_size(*self._size)

def calculate_OR_offset(self, wx, wy, ww, wh):
ss = self._client._current_screen_sizes
if not ss:
return None
if len(ss)!=1:
geomlog("cannot handle one more than one screen for OR offset: %s", )
return None
screen0 = ss[0]
monitors = screen0[5]
if not monitors:
geomlog("screen %s lacks monitors information: %s", screen0)
return None
distances = {}
for i, monitor in enumerate(monitors):
plug_name, x, y, w, h = monitor[:5]
if wx>=x and wx+ww<=x+w and wy+wh<=y+h:
geomlog("window fits in monitor %i: %s", i, plug_name)
return None
xdists = (wx-x, wx+ww-x, wx-(x+w), wx+ww-(x+w))
ydists = (wy-y, wy+wh-y, wy-(y+h), wy+wh-(y+h))
distance = min((abs(v) for v in xdists))+min((abs(v) for v in ydists))
distances[distance] = i
#so it doesn't fit... choose the closest monitor and make it fit
geomlog("OR window distances: %s", distances)
closest = min(distances.keys())
i = distances[closest]
monitor = monitors[i]
plug_name, x, y, w, h = monitor[:5]
geomlog("calculating OR offset for monitor %i: %s", i, plug_name)
if ww>w or wh>=h:
geomlog("window %ix%i is bigger than the monitor %i: %s %ix%i, not adjusting it", ww, wh, i, plug_name, w, h)
return None
dx = 0
dy = 0
if wx<x:
dx = x-wx
elif wx+ww>x+w:
dx = (x+w) - (wx+ww)
if wy<y:
dy = y-wy
elif wy+wh>y+h:
dy = (y+h) - (wy+wh)
assert dx!=0 or dy!=0
geomlog("calculate_OR_offset%s=%s", (wx, wy, ww, wh), (dx, dy))
return dx, dy

def when_realized(self, identifier, callback, *args):
if self.is_realized():
Expand Down Expand Up @@ -1040,6 +1094,10 @@ def move_resize(self, x, y, w, h, resize_counter=0):
geomlog("window %i move_resize%s", self._id, (x, y, w, h, resize_counter))
w = max(1, w)
h = max(1, h)
if self.OR_offset:
x += self.OR_offset[0]
y += self.OR_offset[1]
#TODO: check this doesn't move it off-screen!
self._resize_counter = resize_counter
window = self.get_window()
if window.get_position()==(x, y):
Expand Down Expand Up @@ -1110,7 +1168,12 @@ def do_delete_event(self, event):


def _pointer_modifiers(self, event):
pointer = self._client.cp(event.x_root, event.y_root)
x = event.x_root
y = event.y_root
if self.OR_offset:
x -= self.OR_offset[0]
y -= self.OR_offset[1]
pointer = self._client.cp(x, y)
modifiers = self._client.mask_to_names(event.state)
buttons = []
for mask, button in self.BUTTON_MASK.items():
Expand Down
3 changes: 3 additions & 0 deletions src/xpra/client/ui_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ def __init__(self):
self._suspended_at = 0
self._button_state = {}
self._on_handshake = []
self._current_screen_sizes = None

self.init_aliases()

Expand Down Expand Up @@ -987,6 +988,7 @@ def update_screen_size(self):
self.screen_size_change_pending = False
u_root_w, u_root_h = self.get_root_size()
root_w, root_h = self.cp(u_root_w, u_root_h)
self._current_screen_sizes = self.get_screen_sizes()
sss = self.get_screen_sizes(self.xscale, self.yscale)
ndesktops = get_number_of_desktops()
desktop_names = get_desktop_names()
Expand Down Expand Up @@ -1330,6 +1332,7 @@ def make_hello(self):
desktop_names = get_desktop_names()
capabilities["desktop.names"] = desktop_names
ss = self.get_screen_sizes()
self._current_screen_sizes = ss
log.info(" desktop size is %sx%s with %s screen%s:", u_root_w, u_root_h, len(ss), engs(ss))
log_screen_sizes(u_root_w, u_root_h, ss)
if self.xscale!=1 or self.yscale!=1:
Expand Down

0 comments on commit 42b3837

Please sign in to comment.