Skip to content

Commit

Permalink
#775: forward _NET_WM_STRUT_PARTIAL or _NET_WM_STRUT and set it if we…
Browse files Browse the repository at this point in the history
… have the X11 bindings

git-svn-id: https://xpra.org/svn/Xpra/trunk@8552 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jan 26, 2015
1 parent 33c287e commit 40b32df
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 19 deletions.
23 changes: 23 additions & 0 deletions src/tests/xpra/test_apps/test_window_strut.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env python

#code found here:
#http://stackoverflow.com/a/3859540/428751
import gtk

class PyGtkWidgetDockExample:
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_default_size(100, gtk.gdk.screen_height())
self.window.move(gtk.gdk.screen_width()-100, 0)
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
self.window.show()
self.window.window.property_change("_NET_WM_STRUT", "CARDINAL", 32,
gtk.gdk.PROP_MODE_REPLACE, [0, 100, 0, 0])

def main():
PyGtkWidgetDockExample()
gtk.main()


if __name__ == "__main__":
main()
7 changes: 7 additions & 0 deletions src/xpra/client/client_window_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,17 @@ def metadata_replace(match):
if b"bypass-compositor" in metadata:
self.set_bypass_compositor(metadata.intget("bypass-compositor"))

if b"strut" in metadata:
self.set_strut(metadata.dictget("strut"))


def set_bypass_compositor(self, v):
pass #see gtk2 client

def set_strut(self, d):
pass #see gtk2 client


def set_size_constraints(self, size_constraints, max_window_size):
self._set_initial_position = size_constraints.get("set-initial-position")
hints = {}
Expand Down
3 changes: 2 additions & 1 deletion src/xpra/client/gtk_base/gtk_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ def make_hello(self):
ms += ["command", "workspace", "above", "below", "sticky"]
if os.name=="posix":
#this is only really supported on X11, but posix is easier to check for..
ms += ["bypass-compositor"]
#strut could also be supported on other platforms I guess
ms += ["bypass-compositor", "strut"]
log("metadata.supported: %s", ms)
capabilities["metadata.supported"] = ms
#we need the bindings to support initiate-moveresize (posix only for now):
Expand Down
26 changes: 25 additions & 1 deletion src/xpra/client/gtk_base/gtk_client_window_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
eventslog = Logger("events")


from xpra.util import AdHocStruct, bytestostr, WORKSPACE_UNSET, WORKSPACE_ALL
from xpra.util import AdHocStruct, bytestostr, typedict, WORKSPACE_UNSET, WORKSPACE_ALL
from xpra.gtk_common.gobject_compat import import_gtk, import_gdk, import_cairo, import_pixbufloader
from xpra.gtk_common.gtk_util import get_pixbuf_from_data
from xpra.gtk_common.keymap import KEY_TRANSLATIONS
Expand Down Expand Up @@ -298,6 +298,30 @@ def set_bypass_compositor(self, v):
prop_set(self.get_window(), "_NET_WM_BYPASS_COMPOSITOR", "u32", v)


def set_strut(self, strut):
if not HAS_X11_BINDINGS:
return
log("strut=%s", strut)
d = typedict(strut)
values = []
for x in ("left", "right", "top", "bottom"):
values.append(d.intget(x, 0))
has_partial = False
for x in ("left_start_y", "left_end_y",
"right_start_y", "right_end_y",
"top_start_x", "top_end_x",
"bottom_start_x", "bottom_end_x"):
if x in d:
has_partial = True
values.append(d.intget(x, 0))
log("setting strut=%s, has partial=%s", values, has_partial)
if not self.is_realized():
self.realize()
if has_partial:
prop_set(self.get_window(), "_NET_WM_STRUT_PARTIAL", ["u32"], values)
prop_set(self.get_window(), "_NET_WM_STRUT", ["u32"], values[:4])


def set_fullscreen(self, fullscreen):
if self._fullscreen is None or self._fullscreen!=fullscreen:
#note: the "_fullscreen" flag is updated by the window-state-event, not here
Expand Down
32 changes: 17 additions & 15 deletions src/xpra/x11/gtk_x11/prop.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,25 @@ class NetWMStrut(object):
def __init__(self, disp, data):
# This eats both _NET_WM_STRUT and _NET_WM_STRUT_PARTIAL. If we are
# given a _NET_WM_STRUT instead of a _NET_WM_STRUT_PARTIAL, then it
# will be only length 4 instead of 12, but _force_length will zero-pad
# and _NET_WM_STRUT is *defined* as a _NET_WM_STRUT_PARTIAL where the
# extra fields are zero... so it all works out.
data = _force_length("_NET_WM_STRUT or _NET_WM_STRUT_PARTIAL", data, 4 * 12)
(self.left, self.right, self.top, self.bottom,
self.left_start_y, self.left_end_y,
self.right_start_y, self.right_end_y,
self.top_start_x, self.top_end_x,
self.bottom_start_x, self.bottom_stop_x,
) = struct.unpack("=" + "I" * 12, data)
# will be only length 4 instead of 12, we just don't define the other values
# and let the client deal with it appropriately
if len(data)==16:
self.left, self.right, self.top, self.bottom = struct.unpack("=IIII", data)
else:
data = _force_length("_NET_WM_STRUT or _NET_WM_STRUT_PARTIAL", data, 4 * 12)
(self.left, self.right, self.top, self.bottom,
self.left_start_y, self.left_end_y,
self.right_start_y, self.right_end_y,
self.top_start_x, self.top_end_x,
self.bottom_start_x, self.bottom_stop_x,
) = struct.unpack("=" + "I" * 12, data)

def todict(self):
return self.__dict__

def __str__(self):
return "NetWMStrut(%s)" % str(self.left, self.right, self.top, self.bottom,
self.left_start_y, self.left_end_y,
self.right_start_y, self.right_end_y,
self.top_start_x, self.top_end_x,
self.bottom_start_x, self.bottom_stop_x)
return "NetWMStrut(%s)" % self.todict()


class MotifWMHints(object):
def __init__(self, disp, data):
Expand Down
4 changes: 2 additions & 2 deletions src/xpra/x11/gtk_x11/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,13 @@ def __init__(self, client_window):
use_xshm = USE_XSHM and (not self.is_OR() and not self.is_tray())
self._composite = CompositeHelper(self.client_window, False, use_xshm)
self.property_names = ["pid", "transient-for", "fullscreen", "bypass-compositor", "maximized", "window-type", "role", "group-leader",
"xid", "workspace", "has-alpha", "opacity"]
"xid", "workspace", "has-alpha", "opacity", "strut"]

def get_property_names(self):
return self.property_names

def get_dynamic_property_names(self):
return ("title", "size-hints", "fullscreen", "bypass-compositor", "maximized", "opacity", "workspace")
return ("title", "size-hints", "fullscreen", "bypass-compositor", "maximized", "opacity", "workspace", "strut")


def managed_connect(self, detailed_signal, handler, *args):
Expand Down

0 comments on commit 40b32df

Please sign in to comment.