summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2015-02-21 16:34:35 +0100
committerJavier <dev.git@javispedro.com>2015-02-21 16:34:35 +0100
commit40bee9911209e2e9e9c30bdb1a87443f7e36a3f1 (patch)
tree96387394251be15120b10db8d11cc049818627bf
parentf56b5b34e2a14327021168ff3ad6ce49cdd27bed (diff)
downloadmdock-40bee9911209e2e9e9c30bdb1a87443f7e36a3f1.tar.gz
mdock-40bee9911209e2e9e9c30bdb1a87443f7e36a3f1.zip
add red dot if any window on item needs attention
-rw-r--r--libmdock/mdock-item.c56
-rw-r--r--libmdock/mdock-item.h1
2 files changed, 56 insertions, 1 deletions
diff --git a/libmdock/mdock-item.c b/libmdock/mdock-item.c
index 68cfb80..6ee7b6a 100644
--- a/libmdock/mdock-item.c
+++ b/libmdock/mdock-item.c
@@ -31,6 +31,7 @@ struct _MDockItemPrivate
guint icon_size;
GdkPixbuf *icon;
GList *windows;
+ gboolean needs_attention;
};
G_DEFINE_TYPE (MDockItem, mdock_item, GTK_TYPE_WIDGET)
@@ -41,6 +42,7 @@ enum {
PROP_DESKTOP_APP_INFO,
PROP_N_WINDOWS,
PROP_DISPLAY_NAME,
+ PROP_NEEDS_ATTENTION,
N_PROPERTIES
};
@@ -107,6 +109,30 @@ static void mdock_item_update_icon_geometry(MDockItem *self)
}
}
+static void mdock_item_update_needs_attention(MDockItem *self)
+{
+ gboolean needs_it = FALSE;
+
+ for (GList *l = self->priv->windows; l; l = g_list_next(l)) {
+ WnckWindow *window = WNCK_WINDOW(l->data);
+ needs_it |= wnck_window_or_transient_needs_attention(window);
+ }
+
+ if (needs_it != self->priv->needs_attention) {
+ self->priv->needs_attention = needs_it;
+ gtk_widget_queue_draw(GTK_WIDGET(self));
+ g_object_notify_by_pspec(G_OBJECT(self),
+ obj_properties[PROP_NEEDS_ATTENTION]);
+ }
+}
+
+static void handle_window_state_changed(WnckWindow *window, WnckWindowState changed_mask, WnckWindowState new_state, MDockItem *self)
+{
+ if (changed_mask & (WNCK_WINDOW_STATE_DEMANDS_ATTENTION | WNCK_WINDOW_STATE_URGENT)) {
+ mdock_item_update_needs_attention(self);
+ }
+}
+
static void mdock_item_realize(GtkWidget *widget)
{
MDockItem *self = MDOCK_ITEM(widget);
@@ -163,7 +189,11 @@ static gboolean mdock_item_expose(GtkWidget *widget, GdkEventExpose *event)
if (self->priv->windows) {
double circle_radius = self->priv->icon_size / 8.0;
cairo_save(cr);
- cairo_set_source_rgba(cr, 0.4, 0.4, 0.6, 0.8);
+ if (self->priv->needs_attention) {
+ cairo_set_source_rgba(cr, 0.9, 0.3, 0.3, 1.0);
+ } else {
+ cairo_set_source_rgba(cr, 0.4, 0.4, 0.6, 0.8);
+ }
cairo_translate(cr, self->priv->icon_size / 2.0, self->priv->icon_size - circle_radius / 2.0 - 1.0);
cairo_arc(cr, 0, 0, circle_radius, 0, 2 * M_PI);
cairo_fill(cr);
@@ -214,6 +244,9 @@ static void mdock_item_get_property(GObject *object,
case PROP_DISPLAY_NAME:
g_value_set_string(value, mdock_item_get_display_name(self));
break;
+ case PROP_NEEDS_ATTENTION:
+ g_value_set_boolean(value, self->priv->needs_attention);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
@@ -240,6 +273,7 @@ static void mdock_item_init(MDockItem *self)
self->priv = MDOCK_ITEM_GET_PRIVATE (self);
self->priv->pinned = FALSE;
self->priv->icon_size = REQUISITION_ICON_SIZE;
+ self->priv->needs_attention = FALSE;
gtk_widget_add_events(GTK_WIDGET(self),
GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
@@ -285,6 +319,12 @@ mdock_item_class_init(MDockItemClass *klass)
"",
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_NEEDS_ATTENTION] = g_param_spec_boolean("needs-attention",
+ "Needs attention",
+ "Whether any of the windows in this item requires attention",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties(obj_class, N_PROPERTIES, obj_properties);
g_type_class_add_private (obj_class, sizeof (MDockItemPrivate));
@@ -386,6 +426,11 @@ GdkPixbuf *mdock_item_get_icon_pixbuf(MDockItem *self)
return self->priv->icon;
}
+gboolean mdock_item_needs_attention(MDockItem *self)
+{
+ return self->priv->needs_attention;
+}
+
void mdock_item_add_window(MDockItem *self, WnckWindow *window)
{
if (!self->priv->windows) {
@@ -398,6 +443,11 @@ void mdock_item_add_window(MDockItem *self, WnckWindow *window)
mdock_item_update_icon(self);
}
mdock_item_update_icon_geometry_for_window(self, window);
+ if (wnck_window_or_transient_needs_attention(window)) {
+ mdock_item_update_needs_attention(self);
+ }
+ g_signal_connect_object(window, "state-changed",
+ G_CALLBACK(handle_window_state_changed), self, 0);
g_object_notify_by_pspec(G_OBJECT(self), obj_properties[PROP_N_WINDOWS]);
}
@@ -409,6 +459,10 @@ void mdock_item_remove_window(MDockItem *self, WnckWindow *window)
// we want to redraw in order to remove the "active" indicator.
gtk_widget_queue_draw(GTK_WIDGET(self));
}
+ if (wnck_window_or_transient_needs_attention(window)) {
+ mdock_item_update_needs_attention(self);
+ }
+ g_signal_handlers_disconnect_by_data(window, self);
g_object_notify_by_pspec(G_OBJECT(self), obj_properties[PROP_N_WINDOWS]);
}
diff --git a/libmdock/mdock-item.h b/libmdock/mdock-item.h
index 739c966..bb7a2ab 100644
--- a/libmdock/mdock-item.h
+++ b/libmdock/mdock-item.h
@@ -64,6 +64,7 @@ void mdock_item_launch(MDockItem *self);
const gchar *mdock_item_get_display_name(MDockItem *self);
GdkPixbuf *mdock_item_get_icon_pixbuf(MDockItem *self);
+gboolean mdock_item_needs_attention(MDockItem *self);
void mdock_item_add_window(MDockItem *self, WnckWindow *window);
void mdock_item_remove_window(MDockItem *self, WnckWindow *window);