Skip to content

Commit

Permalink
add "png_window_icons" option for sending window icons in png format,…
Browse files Browse the repository at this point in the history
… use it in the android version by default

git-svn-id: https://xpra.org/svn/Xpra/trunk@176 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Sep 20, 2011
1 parent 22dc8f0 commit 8445dd5
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 22 deletions.
32 changes: 27 additions & 5 deletions android/src/org/xpra/XpraWindow.java
@@ -1,5 +1,6 @@
package org.xpra;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -42,10 +43,11 @@ public class XpraWindow extends RelativeLayout implements ClientWindow, OnKeyLis
protected AndroidXpraClient client = null;

protected RelativeLayout topBar = null;
protected ImageView imageView = null;
protected Bitmap backing = null;
protected ImageView windowIcon = null;
protected ImageButton maximise = null;
protected ImageButton close = null;
protected ImageView imageView = null;
protected Bitmap backing = null;

protected boolean maximized = false;
protected AbsoluteLayoutParams unMaximizedLayoutParams = null;
Expand Down Expand Up @@ -83,10 +85,11 @@ protected void init(XpraActivity context, AndroidXpraClient _client, int _id, in
this.id = _id;
this.metadata = new HashMap<String, Object>();
this.override_redirect = _override_redirect;
this.imageView = (ImageView) this.findViewById(R.id.xpra_window_contents);
this.topBar = (RelativeLayout) this.findViewById(R.id.xpra_window_top_bar);
this.windowIcon = (ImageView) this.findViewById(R.id.xpra_window_icon);
this.maximise = (ImageButton) this.findViewById(R.id.xpra_window_maximize);
this.close = (ImageButton) this.findViewById(R.id.xpra_window_close);
this.topBar = (RelativeLayout) this.findViewById(R.id.xpra_window_top_bar);
this.imageView = (ImageView) this.findViewById(R.id.xpra_window_contents);

//adjust location so it is always shown:
int min_margin = 32;
Expand Down Expand Up @@ -359,7 +362,26 @@ public void update_metadata(Map<String, Object> newMetadata) {
((TextView) this.findViewById(R.id.xpra_window_title)).setText(this.title);
Object icon = newMetadata.get("icon");
this.log("update_metadata(" + newMetadata + ") icon="+icon+", type="+(icon==null?null:icon.getClass()));
// this.setTitle(title);
if (icon!=null) {
List<?> iconData = (List<?>) icon;
int w = ((BigInteger) iconData.get(0)).intValue();
int h = ((BigInteger) iconData.get(1)).intValue();
byte[] raw_format = (byte[]) iconData.get(2);
String format = new String(raw_format);
this.log("update_metadata(" + newMetadata + ") found "+w+"x"+h+" icon in "+format+" format");
if (format.equals("png")) {
byte[] blob = (byte[]) iconData.get(3);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
while (w>64 || h>this.offsetY) {
options.inSampleSize *= 2;
w = w/2;
h = h/2;
}
Bitmap bmp = BitmapFactory.decodeByteArray(blob, 0, blob.length, options);
this.windowIcon.setImageBitmap(bmp);
}
}
// Map<?,?> size_constraints = (Map<?,?>)
// metadata.get("size-constraints");
}
Expand Down
1 change: 1 addition & 0 deletions java/src/xpra/AbstractClient.java
Expand Up @@ -329,6 +329,7 @@ public void send_hello(String enc_pass) {
caps.put("desktop_size", dims);
if (this.jpeg>0)
caps.put("jpeg", this.jpeg);
caps.put("png_window_icons", true);
this.send("hello", caps);
}

Expand Down
27 changes: 16 additions & 11 deletions src/xpra/client.py
Expand Up @@ -129,17 +129,22 @@ def metadata_replace(match):

if "icon" in self._metadata:
(width, height, coding, data) = self._metadata["icon"]
assert coding == "premult_argb32"
cairo_surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
cairo_surf.get_data()[:] = data
# FIXME: We round-trip through PNG. This is ridiculous, but faster
# than doing a bunch of alpha un-premultiplying and byte-swapping
# by hand in Python (better still would be to write some Pyrex,
# but I don't have time right now):
loader = gtk.gdk.PixbufLoader()
cairo_surf.write_to_png(loader)
loader.close()
pixbuf = loader.get_pixbuf()
if coding == "premult_argb32":
cairo_surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
cairo_surf.get_data()[:] = data
# FIXME: We round-trip through PNG. This is ridiculous, but faster
# than doing a bunch of alpha un-premultiplying and byte-swapping
# by hand in Python (better still would be to write some Pyrex,
# but I don't have time right now):
loader = gtk.gdk.PixbufLoader()
cairo_surf.write_to_png(loader)
loader.close()
pixbuf = loader.get_pixbuf()
else:
loader = gtk.gdk.PixbufLoader(coding)
loader.write(data, len(data))
loader.close()
pixbuf = loader.get_pixbuf()
self.set_icon(pixbuf)

def _new_backing(self, w, h):
Expand Down
24 changes: 18 additions & 6 deletions src/xpra/server.py
Expand Up @@ -272,6 +272,8 @@ def __init__(self, clobber, sockets, password_file, pulseaudio, clipboard, randr
if (is_override_redirect(window) and is_mapped(window)):
self._add_new_or_window(window)

self.png_window_icons = False

## These may get set by the client:
self.xkbmap_print = None
self.xkbmap_query = None
Expand Down Expand Up @@ -535,11 +537,20 @@ def _make_metadata(self, window, propname):
elif propname == "icon":
surf = window.get_property("icon")
if surf is not None:
assert surf.get_format() == cairo.FORMAT_ARGB32
assert surf.get_stride() == 4 * surf.get_width()
return {"icon": (surf.get_width(), surf.get_height(),
"premult_argb32", str(surf.get_data()))
}
w = surf.get_width()
h = surf.get_height()
log("found new window icon: %sx%s, sending as png=%s" % (w,h,self.png_window_icons))
if self.png_window_icons:
img = Image.frombuffer("RGBA", (w,h), surf.get_data(), "raw", "RGBA", 0, 1)
output = StringIO.StringIO()
img.save(output, 'PNG')
raw_data = output.getvalue()
return {"icon": (w, h, "png", str(raw_data)) }
else:

assert surf.get_format() == cairo.FORMAT_ARGB32
assert surf.get_stride() == 4 * surf.get_width()
return {"icon": (w, h, "premult_argb32", str(surf.get_data())) }
else:
return {}
elif propname == "client-machine":
Expand Down Expand Up @@ -692,7 +703,7 @@ def _contents_changed(self, window, event):

def _calculate_capabilities(self, client_capabilities):
capabilities = {}
for cap in ("deflate", "__prerelease_version", "challenge_response", "jpeg", "keymap", "xkbmap_query", "xmodmap_data", "modifiers"):
for cap in ("deflate", "__prerelease_version", "challenge_response", "jpeg", "keymap", "xkbmap_query", "xmodmap_data", "modifiers", "png_window_icons"):
if cap in client_capabilities:
capabilities[cap] = client_capabilities[cap]
return capabilities
Expand Down Expand Up @@ -811,6 +822,7 @@ def login_failed(*args):
#always clear modifiers before setting a new keymap
self._make_keymask_match([])
self.set_keymap()
self.png_window_icons = capabilities.get("png_window_icons", False)
# now we can set the modifiers to match the client
modifiers = capabilities.get("modifiers", [])
log.debug("setting modifiers to %s" % str(modifiers))
Expand Down

0 comments on commit 8445dd5

Please sign in to comment.