summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfujiwarat <takao.fujiwara1@gmail.com>2015-04-09 15:20:56 +0900
committerfujiwarat <takao.fujiwara1@gmail.com>2015-04-09 15:20:56 +0900
commitcb93cab84beea2074502b04580d33e51587da83e (patch)
tree62f834e070b04377bcd7bdd992c142f6978e8215
parent90252fa952da2b9a4a33e6f2c33f652d3e9cbbee (diff)
downloadibus-cb93cab84beea2074502b04580d33e51587da83e.tar.gz
ibus-ui-gtk3: Support language icon in KDE5.
TEST=ui/gtk3/ibus-ui-gtk3 Review URL: https://codereview.appspot.com/229740043
-rw-r--r--ui/gtk3/indicator.vala69
-rw-r--r--ui/gtk3/notification-item.xml6
-rw-r--r--ui/gtk3/panel.vala53
3 files changed, 117 insertions, 11 deletions
diff --git a/ui/gtk3/indicator.vala b/ui/gtk3/indicator.vala
index 013b1c48..77a84ade 100644
--- a/ui/gtk3/indicator.vala
+++ b/ui/gtk3/indicator.vala
@@ -44,6 +44,7 @@ class Indicator : IBus.Service
public string label_s { get; set; }
public string label_guide_s { get; set; }
public uint32 ordering_index { get; set; }
+ public GLib.Variant icon_vector { get; set; }
public enum Category {
APPLICATION_STATUS,
@@ -234,6 +235,10 @@ class Indicator : IBus.Service
return new GLib.Variant.string(this.icon_name);
}
+ private GLib.Variant _get_icon_vector(GLib.DBusConnection connection) {
+ return this.icon_vector;
+ }
+
private GLib.Variant _get_icon_desc(GLib.DBusConnection connection) {
return new GLib.Variant.string(this.icon_desc);
}
@@ -318,6 +323,8 @@ class Indicator : IBus.Service
return _get_status(connection);
if (property_name == "IconName")
return _get_icon_name(connection);
+ if (property_name == "IconPixmap")
+ return _get_icon_vector(connection);
if (property_name == "IconAccessibleDesc")
return _get_icon_desc(connection);
if (property_name == "AttentionIconName")
@@ -359,6 +366,12 @@ class Indicator : IBus.Service
if (this.status_s == status_s)
return;
this.status_s = status_s;
+
+ /* This API does not require (this.connection != null)
+ * because service_get_property() can be called when
+ * this.connection emits the "NewStatus" signal or
+ * or m_proxy calls the "RegisterStatusNotifierItem" signal.
+ */
if (this.connection == null)
return;
try {
@@ -377,6 +390,7 @@ class Indicator : IBus.Service
bool changed = false;
if (this.icon_name != icon_name) {
this.icon_name = icon_name;
+ this.icon_vector = null;
changed = true;
}
if (this.icon_desc != icon_desc) {
@@ -385,6 +399,61 @@ class Indicator : IBus.Service
}
if (!changed)
return;
+
+ /* This API does not require (this.connection != null)
+ * because service_get_property() can be called when
+ * this.connection emits the "NewIcon" signal or
+ * or m_proxy calls the "RegisterStatusNotifierItem" signal.
+ */
+ if (this.connection == null)
+ return;
+ try {
+ this.connection.emit_signal(null,
+ this.object_path,
+ NOTIFICATION_ITEM_DBUS_IFACE,
+ "NewIcon",
+ null);
+ } catch(GLib.Error e) {
+ warning("Unable to send signal for NewIcon: %s", e.message);
+ }
+ }
+
+ public void set_cairo_image_surface_full(Cairo.ImageSurface image,
+ string? icon_desc) {
+ int width = image.get_width();
+ int height = image.get_height();
+ int stride = image.get_stride();
+ unowned uint[] data = (uint[]) image.get_data();
+ int length = stride * height / (int) sizeof(uint);
+ if (GLib.BYTE_ORDER == GLib.ByteOrder.LITTLE_ENDIAN) {
+ for (int i = 0; i < length; i++)
+ data[i] = data[i].to_big_endian();
+ }
+ unowned uint8[] data8 = (uint8[]) data;
+ data8.length = stride * height;
+ GLib.Bytes bytes = new GLib.Bytes(data8);
+ GLib.Variant bs =
+ new GLib.Variant.from_bytes(GLib.VariantType.BYTESTRING,
+ bytes,
+ true);
+ GLib.VariantBuilder builder = new GLib.VariantBuilder(
+ new GLib.VariantType("a(iiay)"));
+ builder.open(new GLib.VariantType("(iiay)"));
+ builder.add("i", width);
+ builder.add("i", height);
+ builder.add_value(bs);
+ builder.close();
+ this.icon_vector = new GLib.Variant("a(iiay)", builder);
+ this.icon_name = "";
+
+ if (this.icon_desc != icon_desc)
+ this.icon_desc = icon_desc;
+
+ /* This API does not require (this.connection != null)
+ * because service_get_property() can be called when
+ * this.connection emits the "NewIcon" signal or
+ * or m_proxy calls the "RegisterStatusNotifierItem" signal.
+ */
if (this.connection == null)
return;
try {
diff --git a/ui/gtk3/notification-item.xml b/ui/gtk3/notification-item.xml
index aecb8d9b..6fde3d3e 100644
--- a/ui/gtk3/notification-item.xml
+++ b/ui/gtk3/notification-item.xml
@@ -7,6 +7,12 @@
<property name="Category" type="s" access="read" />
<property name="Status" type="s" access="read" />
<property name="IconName" type="s" access="read" />
+ <!-- IconPixmap is missed in AppIndicator
+ struct containing width, height and image data-->
+ <property name="IconPixmap" type="a(iiay)" access="read">
+ <annotation name="org.qtproject.QtDBus.QtTypeName"
+ value="KDbusImageVector" />
+ </property>
<property name="IconAccessibleDesc" type="s" access="read" />
<property name="AttentionIconName" type="s" access="read" />
<property name="AttentionAccessibleDesc" type="s" access="read" />
diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
index c77bd2f7..748ceb4e 100644
--- a/ui/gtk3/panel.vala
+++ b/ui/gtk3/panel.vala
@@ -72,6 +72,9 @@ class Panel : IBus.PanelService {
private GLib.HashTable<string, Gdk.Pixbuf> m_xkb_icon_pixbufs =
new GLib.HashTable<string, Gdk.Pixbuf>(GLib.str_hash,
GLib.str_equal);
+ private GLib.HashTable<string, Cairo.ImageSurface> m_xkb_icon_image =
+ new GLib.HashTable<string, Cairo.ImageSurface>(GLib.str_hash,
+ GLib.str_equal);
private Gdk.RGBA m_xkb_icon_rgba = Gdk.RGBA(){
red = 0.0, green = 0.0, blue = 0.0, alpha = 1.0 };
private XKBLayout m_xkblayout = new XKBLayout();
@@ -649,13 +652,17 @@ class Panel : IBus.PanelService {
} else
m_xkb_icon_rgba = rgba;
- if (m_xkb_icon_pixbufs.size() > 0) {
- m_xkb_icon_pixbufs.remove_all();
+ if (m_icon_type == IconType.STATUS_ICON) {
+ if (m_xkb_icon_pixbufs.size() > 0) {
+ m_xkb_icon_pixbufs.remove_all();
- if (m_icon_type == IconType.STATUS_ICON) {
if (m_status_icon != null && m_switcher != null)
state_changed();
- } else if (m_icon_type == IconType.INDICATOR) {
+ }
+ } else if (m_icon_type == IconType.INDICATOR) {
+ if (m_xkb_icon_image.size() > 0) {
+ m_xkb_icon_image.remove_all();
+
if (m_indicator != null && m_switcher != null)
state_changed();
}
@@ -962,13 +969,18 @@ class Panel : IBus.PanelService {
Pango.cairo_show_layout(cr, layout);
}
- private Gdk.Pixbuf create_icon_pixbuf_with_string(string symbol) {
- Gdk.Pixbuf pixbuf = m_xkb_icon_pixbufs[symbol];
+ private Cairo.ImageSurface
+ create_cairo_image_surface_with_string(string symbol, bool cache) {
+ Cairo.ImageSurface image = null;
- if (pixbuf != null)
- return pixbuf;
+ if (cache) {
+ image = m_xkb_icon_image[symbol];
- var image = new Cairo.ImageSurface(Cairo.Format.ARGB32, 48, 48);
+ if (image != null)
+ return image;
+ }
+
+ image = new Cairo.ImageSurface(Cairo.Format.ARGB32, 48, 48);
var cr = new Cairo.Context(image);
int width = image.get_width();
int height = image.get_height();
@@ -978,6 +990,23 @@ class Panel : IBus.PanelService {
cr.paint();
cr.set_operator(Cairo.Operator.OVER);
context_render_string(cr, symbol, width, height);
+ image.flush();
+
+ if (cache)
+ m_xkb_icon_image.insert(symbol, image);
+
+ return image;
+ }
+
+ private Gdk.Pixbuf create_icon_pixbuf_with_string(string symbol) {
+ Gdk.Pixbuf pixbuf = m_xkb_icon_pixbufs[symbol];
+
+ if (pixbuf != null)
+ return pixbuf;
+
+ var image = create_cairo_image_surface_with_string(symbol, false);
+ int width = image.get_width();
+ int height = image.get_height();
pixbuf = Gdk.pixbuf_get_from_surface(image, 0, 0, width, height);
m_xkb_icon_pixbufs.insert(symbol, pixbuf);
return pixbuf;
@@ -1274,8 +1303,10 @@ class Panel : IBus.PanelService {
m_status_icon.set_from_pixbuf(pixbuf);
}
else if (m_icon_type == IconType.INDICATOR) {
- /* Appindicator does not support pixbuf. */
- m_indicator.set_icon_full(icon_name, "");
+ Cairo.ImageSurface image =
+ create_cairo_image_surface_with_string(language,
+ true);
+ m_indicator.set_cairo_image_surface_full(image, "");
}
} else {
var theme = Gtk.IconTheme.get_default();