Skip to content

Commit

Permalink
#1707: overlay xpra's icon in the bottom corner of the window icon, s…
Browse files Browse the repository at this point in the history
…o we can more easily distinguish remote windows

git-svn-id: https://xpra.org/svn/Xpra/trunk@17673 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Dec 17, 2017
1 parent 28f72c2 commit 3adf78b
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/xpra/client/client_tray.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def new_backing(self, w, h):
def update_metadata(self, metadata):
log("%s.update_metadata(%s)", self, metadata)

def update_icon(self, width, height, coding, data):
def update_icon(self, img):
#this is the window icon... not the tray icon!
pass

Expand Down
14 changes: 7 additions & 7 deletions src/xpra/client/client_window_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,24 +153,24 @@ def reset_icon(self):
if current_icon:
self.update_icon(*current_icon)

def update_icon(self, width, height, coding, data):
raise Exception("override me!")
def update_icon(self, img):
raise NotImplementedError("override me!")

def is_realized(self):
raise Exception("override me!")
raise NotImplementedError("override me!")

def apply_transient_for(self, wid):
raise Exception("override me!")
raise NotImplementedError("override me!")

def paint_spinner(self, context, area):
raise Exception("override me!")
raise NotImplementedError("override me!")

def _pointer_modifiers(self, event):
raise Exception("override me!")
raise NotImplementedError("override me!")


def xget_u32_property(self, target, name):
raise Exception("override me!")
raise NotImplementedError("override me!")


def is_OR(self):
Expand Down
27 changes: 8 additions & 19 deletions src/xpra/client/gtk_base/gtk_client_window_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
grablog = Logger("grab")


from xpra.os_util import memoryview_to_bytes, bytestostr, WIN32, OSX, POSIX, PYTHON3
from xpra.os_util import bytestostr, WIN32, OSX, POSIX, PYTHON3
from xpra.util import (AdHocStruct, typedict, envint, envbool, nonl,
WORKSPACE_UNSET, WORKSPACE_ALL, WORKSPACE_NAMES, MOVERESIZE_DIRECTION_STRING, SOURCE_INDICATION_STRING,
MOVERESIZE_CANCEL,
Expand All @@ -41,7 +41,6 @@
from xpra.gtk_common.keymap import KEY_TRANSLATIONS
from xpra.client.client_window_base import ClientWindowBase
from xpra.platform.gui import set_fullscreen_monitors, set_shaded
from xpra.codecs.argb.argb import unpremultiply_argb, bgra_to_rgba #@UnresolvedImport
from xpra.platform.gui import add_window_hooks, remove_window_hooks

gtk = import_gtk()
Expand Down Expand Up @@ -83,6 +82,7 @@
BREAK_MOVERESIZE = os.environ.get("XPRA_BREAK_MOVERESIZE", "Escape").split(",")
MOVERESIZE_X11 = envbool("XPRA_MOVERESIZE_X11", POSIX)

ICON_OVERLAY = envbool("XPRA_ICON_OVERLAY", True)
OSX_FOCUS_WORKAROUND = envbool("XPRA_OSX_FOCUS_WORKAROUND", True)
SAVE_WINDOW_ICONS = envbool("XPRA_SAVE_WINDOW_ICONS", False)
UNDECORATED_TRANSIENT_IS_OR = envint("XPRA_UNDECORATED_TRANSIENT_IS_OR", 1)
Expand Down Expand Up @@ -1519,22 +1519,11 @@ def do_scroll_event(self, event):
self._button_action(button_mapping, event, False)


def update_icon(self, width, height, coding, data):
self._current_icon = (width, height, coding, data)
coding = bytestostr(coding)
iconlog("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height, coding, len(data))
if coding == "premult_argb32": #we usually cannot do in-place and this is not performance critical
data = unpremultiply_argb(data)
rgba = memoryview_to_bytes(memoryview(bgra_to_rgba(data)))
pixbuf = get_pixbuf_from_data(rgba, True, width, height, width*4)
else:
loader = PixbufLoader()
loader.write(data)
loader.close()
pixbuf = loader.get_pixbuf()
def update_icon(self, img):
self._current_icon = img
has_alpha = img.mode=="RGBA"
width, height = img.size
rowstride = width * (3+int(has_alpha))
pixbuf = get_pixbuf_from_data(img.tobytes(), has_alpha, width, height, rowstride)
iconlog("%s.set_icon(%s)", self, pixbuf)
self.set_icon(pixbuf)
if SAVE_WINDOW_ICONS:
filename = "client-window-%i-icon-%i.png" % (self._id, int(time.time()))
pixbuf.save(filename, "png")
iconlog("client window icon saved to %s", filename)
48 changes: 43 additions & 5 deletions src/xpra/client/ui_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
from xpra.net.compression import Compressed
from xpra.child_reaper import reaper_cleanup
from xpra.make_thread import make_thread
from xpra.os_util import BytesIOClass, Queue, platform_name, get_machine_id, get_user_uuid, bytestostr, monotonic_time, strtobytes, OSX, POSIX
from xpra.os_util import BytesIOClass, Queue, platform_name, get_machine_id, get_user_uuid, bytestostr, monotonic_time, strtobytes, memoryview_to_bytes, OSX, POSIX
from xpra.util import nonl, std, iround, envint, envfloat, envbool, AtomicInteger, log_screen_sizes, typedict, updict, csv, engs, CLIENT_EXIT, XPRA_APP_ID
from xpra.version_util import get_version_info_full, get_platform_info
try:
Expand Down Expand Up @@ -111,6 +111,9 @@ def add_legacy_names(codecs):

TRAY_DELAY = envint("XPRA_TRAY_DELAY", 0)

ICON_OVERLAY = envbool("XPRA_ICON_OVERLAY", True)
SAVE_WINDOW_ICONS = envbool("XPRA_SAVE_WINDOW_ICONS", False)

WEBCAM_ALLOW_VIRTUAL = envbool("XPRA_WEBCAM_ALLOW_VIRTUAL", False)
WEBCAM_TARGET_FPS = max(1, min(50, envint("XPRA_WEBCAM_FPS", 20)))

Expand Down Expand Up @@ -3440,11 +3443,46 @@ def _process_window_metadata(self, packet):
window.update_metadata(metadata)

def _process_window_icon(self, packet):
wid, w, h, pixel_format, data = packet[1:6]
wid, w, h, coding, data = packet[1:6]
img = self._window_icon_image(wid, w, h, coding, data)
window = self._id_to_window.get(wid)
iconlog("_process_window_icon(%s, %s, %s, %s, %s bytes) window=%s", wid, w, h, pixel_format, len(data), window)
if window:
window.update_icon(w, h, pixel_format, data)
iconlog("_process_window_icon(%s, %s, %s, %s, %s bytes) image=%s, window=%s", wid, w, h, coding, len(data), img, window)
if window and img:
window.update_icon(img)

def _window_icon_image(self, wid, width, height, coding, data):
#convert the data into a pillow image,
#adding the icon overlay (if enabled)
PIL = get_codec("PIL")
assert PIL.Image, "PIL.Image not found"
coding = bytestostr(coding)
iconlog("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height, coding, len(data))
if coding == "premult_argb32": #we usually cannot do in-place and this is not performance critical
from xpra.codecs.argb.argb import unpremultiply_argb #@UnresolvedImport
data = unpremultiply_argb(data)
rowstride = width*4
img = PIL.Image.frombytes("RGBA", (width,height), memoryview_to_bytes(data), "raw", "BGRA", rowstride, 1)
has_alpha = True
else:
buf = BytesIOClass(data)
img = PIL.Image.open(buf)
assert img.mode in ("RGB", "RGBA"), "invalid image mode: %s" % img.mode
has_alpha = img.mode=="RGBA"
rowstride = width * (3+int(has_alpha))
if ICON_OVERLAY:
xpra_icon_filename = get_icon_filename("xpra")
xpra_icon = PIL.Image.open(xpra_icon_filename)
half = xpra_icon.resize((width//2, height//2))
xpra_corner = PIL.Image.new("RGBA", (width, height))
xpra_corner.paste(half, (width//2, height//2, width, height))
composite = PIL.Image.alpha_composite(img, xpra_corner)
img = composite
if SAVE_WINDOW_ICONS:
filename = "client-window-%i-icon-%i.png" % (wid, int(time.time()))
img.save(filename, "png")
iconlog("client window icon saved to %s", filename)
return img


def _process_configure_override_redirect(self, packet):
wid, x, y, w, h = packet[1:6]
Expand Down
7 changes: 5 additions & 2 deletions src/xpra/server/window/window_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@

MAX_PIXELS_PREFER_RGB = envint("XPRA_MAX_PIXELS_PREFER_RGB", 4096)

ARGB_ICONS = envbool("XPRA_ARGB_ICONS", True)
PNG_ICONS = envbool("XPRA_PNG_ICONS", True)

DELTA = envbool("XPRA_DELTA", True)
MIN_DELTA_SIZE = envint("XPRA_MIN_DELTA_SIZE", 1024)
MAX_DELTA_SIZE = envint("XPRA_MAX_DELTA_SIZE", 32768)
Expand Down Expand Up @@ -614,8 +617,8 @@ def compress_and_send_window_icon(self):
#use png if supported and if "premult_argb32" is not supported by the client (ie: html5)
#or if we must downscale it (bigger than what the client is willing to deal with),
#or if we want to save window icons
has_png = PIL and ("png" in self.window_icon_encodings)
has_premult = "premult_argb32" in self.window_icon_encodings
has_png = PIL and PNG_ICONS and ("png" in self.window_icon_encodings)
has_premult = ARGB_ICONS and "premult_argb32" in self.window_icon_encodings
use_png = has_png and (SAVE_WINDOW_ICONS or w>max_w or h>max_h or w*h>=1024 or (not has_premult) or (pixel_format!="BGRA"))
iconlog("compress_and_send_window_icon: %sx%s (max-size=%s, standard-size=%s), sending as png=%s, has_png=%s, has_premult=%s, pixel_format=%s", w, h, self.window_icon_max_size, self.window_icon_size, use_png, has_png, has_premult, pixel_format)
if use_png:
Expand Down

0 comments on commit 3adf78b

Please sign in to comment.