Skip to content

Commit

Permalink
#1707: overlay xpra's icon on top the window icon, use that window ic…
Browse files Browse the repository at this point in the history
…on as tray icon (as long as there is only one)

git-svn-id: https://xpra.org/svn/Xpra/trunk@17691 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Dec 18, 2017
1 parent 8a89644 commit f9e927b
Showing 1 changed file with 55 additions and 13 deletions.
68 changes: 55 additions & 13 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, memoryview_to_bytes, 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, WIN32
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,7 +111,7 @@ def add_legacy_names(codecs):

TRAY_DELAY = envint("XPRA_TRAY_DELAY", 0)

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

WEBCAM_ALLOW_VIRTUAL = envbool("XPRA_WEBCAM_ALLOW_VIRTUAL", False)
Expand Down Expand Up @@ -329,6 +329,7 @@ def __init__(self):
self.clipboard_helper = None
self.menu_helper = None
self.tray = None
self.overlay_image = None
self.notifier = None
self.in_remote_logging = False
self.local_logging = None
Expand Down Expand Up @@ -452,6 +453,13 @@ def setup_xpra_tray(*args):
else:
#show shortly after the main loop starts running:
self.timeout_add(TRAY_DELAY, setup_xpra_tray)
if ICON_OVERLAY>0 and ICON_OVERLAY<=100:
icon_filename = get_icon_filename("xpra")
try:
from PIL import Image
self.overlay_image = Image.open(icon_filename)
except Exception as e:
log("init_ui failed to load overlay icon '%s': %s", icon_filename, e)

notifylog("client_supports_notifications=%s", self.client_supports_notifications)
if self.client_supports_notifications:
Expand Down Expand Up @@ -3449,33 +3457,65 @@ def _process_window_icon(self, packet):
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)
self.set_tray_icon()

def set_tray_icon(self):
#find all the window icons,
#and if they are all using the same one, then use it as tray icon
#otherwise use the default icon
if not self.tray:
return
if WIN32:
#the icon ends up looking garbled on win32,
#and we somehow also lose the settings that can keep us in the visible systray list
#so don't bother
return
windows = tuple(w for w in self._window_to_id.keys() if not w.is_tray())
#get all the icons:
icons = tuple(getattr(w, "_current_icon", None) for w in windows)
if icons and not any(True for icon in icons if icon is None):
icon = icons[0]
for i in icons[1:]:
if i!=icon:
#found a different icon
icon = None
break
if icon:
has_alpha = icon.mode=="RGBA"
width, height = icon.size
rowstride = width * (3+int(has_alpha))
rgb_data = icon.tobytes("raw")
self.tray.set_icon_from_data(rgb_data, has_alpha, width, height, rowstride)
return
#this sets the default icon (badly named function!)
self.tray.set_icon()

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"
from PIL import Image
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)
img = 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)
img = 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), PIL.Image.ANTIALIAS)
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)
if self.overlay_image:
assert ICON_OVERLAY>0 and ICON_OVERLAY<=100
overlay_width = max(1, width*ICON_OVERLAY//100)
overlay_height = max(1, height*ICON_OVERLAY//100)
half = self.overlay_image.resize((overlay_width, overlay_height), Image.ANTIALIAS)
xpra_corner = Image.new("RGBA", (width, height))
xpra_corner.paste(half, (width-overlay_width, height-overlay_height, width, height))
composite = Image.alpha_composite(img, xpra_corner)
img = composite
if SAVE_WINDOW_ICONS:
filename = "client-window-%i-icon-%i.png" % (wid, int(time.time()))
Expand Down Expand Up @@ -3503,6 +3543,8 @@ def _process_lost_window(self, packet):
self.destroy_window(wid, window)
if len(self._id_to_window)==0:
windowlog("last window gone, clearing key repeat")
self.set_tray_icon()


def destroy_window(self, wid, window):
windowlog("destroy_window(%s, %s)", wid, window)
Expand Down

0 comments on commit f9e927b

Please sign in to comment.