#include "mdock-window.h" #include "thumbnailer.h" #define MDOCK_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), MDOCK_TYPE_WINDOW, MDockWindowPrivate)) #define SCREENSHOT_DELAY 100 struct _MDockWindowPrivate { GtkTable *table; GtkImage *icon; GtkLabel *title; GtkWidget *close_btn; GtkImage *img; guint screenshot_timeout; gboolean preligth : 1; gboolean selected : 1; }; G_DEFINE_TYPE(MDockWindow, mdock_window, GTK_TYPE_EVENT_BOX) enum MDockItemWindowSelectorProperties { PROP_0, PROP_WINDOW, N_PROPERTIES }; static GParamSpec *obj_properties[N_PROPERTIES] = { NULL }; static void handle_close_btn_clicked(MDockWindow *self, GtkToolButton *toolbtn) { wnck_window_close(self->window, gtk_get_current_event_time()); } static void update_state(MDockWindow *self) { if (gtk_widget_is_sensitive(GTK_WIDGET(self))) { GtkStateType state = GTK_STATE_NORMAL; if (self->priv->preligth) { state = GTK_STATE_PRELIGHT; } else if (self->priv->selected) { state = GTK_STATE_SELECTED; } gtk_widget_set_state(GTK_WIDGET(self), state); } } static gboolean screenshot_delay_timeout(gpointer user_data) { MDockWindow *self = MDOCK_WINDOW(user_data); if (wnck_window_is_active(self->window)) { mdock_window_update_screenshot(self); } self->priv->screenshot_timeout = 0; return G_SOURCE_REMOVE; } static void handle_window_name_changed(MDockWindow *self, WnckWindow *window) { gtk_label_set_label(self->priv->title, wnck_window_get_name(self->window)); // May be a good time to refresh the screenshot if (wnck_window_is_active(window)) { mdock_window_schedule_screenshot(self); } } static void handle_window_icon_changed(MDockWindow *self, WnckWindow *window) { gtk_image_set_from_pixbuf(self->priv->icon, wnck_window_get_icon(self->window)); if (wnck_window_is_active(window)) { mdock_window_schedule_screenshot(self); } } static gboolean mdock_window_enter_notify(GtkWidget *widget, GdkEventCrossing *event) { MDockWindow *self = MDOCK_WINDOW(widget); GtkWidget *event_widget = gtk_get_event_widget((GdkEvent*) event); if (event_widget == widget && event->detail != GDK_NOTIFY_INFERIOR) { self->priv->preligth = TRUE; update_state(self); } return FALSE; } static gboolean mdock_window_leave_notify(GtkWidget *widget, GdkEventCrossing *event) { MDockWindow *self = MDOCK_WINDOW(widget); GtkWidget *event_widget = gtk_get_event_widget((GdkEvent*) event); if (event_widget == widget && event->detail != GDK_NOTIFY_INFERIOR) { self->priv->preligth = FALSE; update_state(self); } return FALSE; } static void mdock_window_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { MDockWindow *self = MDOCK_WINDOW(object); switch (property_id) { case PROP_WINDOW: self->window = g_value_get_object(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void mdock_window_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { MDockWindow *self = MDOCK_WINDOW(object); switch (property_id) { case PROP_WINDOW: g_value_set_object(value, self->window); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; } } static void mdock_window_constructed(GObject *object) { MDockWindow *self = MDOCK_WINDOW(object); G_OBJECT_CLASS(mdock_window_parent_class)->constructed(object); thumbnailer_enable_for_window(self->window); self->priv->icon = GTK_IMAGE(gtk_image_new_from_pixbuf(wnck_window_get_icon(self->window))); gtk_table_attach(self->priv->table, GTK_WIDGET(self->priv->icon), 0, 1, 0, 1, 0, 0, 0, 0); gtk_widget_show(GTK_WIDGET(self->priv->icon)); self->priv->title = GTK_LABEL(gtk_label_new(wnck_window_get_name(self->window))); gtk_label_set_max_width_chars(self->priv->title, 20); gtk_table_attach(self->priv->table, GTK_WIDGET(self->priv->title), 1, 2, 0, 1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0); gtk_widget_show(GTK_WIDGET(self->priv->title)); self->priv->close_btn = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_CLOSE)); gtk_table_attach(self->priv->table, self->priv->close_btn, 2, 3, 0, 1, 0, 0, 0, 0); if (wnck_window_get_actions(self->window) & WNCK_WINDOW_ACTION_CLOSE) { gtk_widget_show(self->priv->close_btn); g_signal_connect_object(self->priv->close_btn, "clicked", G_CALLBACK(handle_close_btn_clicked), self, G_CONNECT_SWAPPED); } self->priv->img = GTK_IMAGE(gtk_image_new()); gtk_table_attach(self->priv->table, GTK_WIDGET(self->priv->img), 0, 3, 1, 2, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0); gtk_widget_show(GTK_WIDGET(self->priv->img)); g_signal_connect_object(self->window, "name-changed", G_CALLBACK(handle_window_name_changed), self, G_CONNECT_SWAPPED); g_signal_connect_object(self->window, "icon-changed", G_CALLBACK(handle_window_icon_changed), self, G_CONNECT_SWAPPED); } static void mdock_window_dispose(GObject *object) { MDockWindow *self = MDOCK_WINDOW(object); if (self->priv->screenshot_timeout) { g_source_remove(self->priv->screenshot_timeout); self->priv->screenshot_timeout = 0; } G_OBJECT_CLASS(mdock_window_parent_class)->dispose(object); } static void mdock_window_class_init (MDockWindowClass *klass) { GObjectClass *obj_class = G_OBJECT_CLASS(klass); obj_class->set_property = mdock_window_set_property; obj_class->get_property = mdock_window_get_property; obj_class->constructed = mdock_window_constructed; obj_class->dispose = mdock_window_dispose; GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); widget_class->enter_notify_event = mdock_window_enter_notify; widget_class->leave_notify_event = mdock_window_leave_notify; g_type_class_add_private(obj_class, sizeof (MDockWindowPrivate)); obj_properties[PROP_WINDOW] = g_param_spec_object("window", "The WnckWindow corresponding to this window", "Set the WnckWindow the options in this menu apply to", WNCK_TYPE_WINDOW, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(obj_class, N_PROPERTIES, obj_properties); } static void mdock_window_init(MDockWindow *self) { self->priv = MDOCK_WINDOW_GET_PRIVATE(self); self->priv->table = GTK_TABLE(gtk_table_new(2, 3, FALSE)); gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(self->priv->table)); gtk_widget_add_events(GTK_WIDGET(self), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_show(GTK_WIDGET(self->priv->table)); } void mdock_window_update_screenshot(MDockWindow *self) { g_return_if_fail(self->window); thumbnailer_update_thumbnail(self->window); gtk_image_set_from_pixmap(self->priv->img, thumbnailer_get_thumbnail(self->window), NULL); } void mdock_window_schedule_screenshot(MDockWindow *self) { g_return_if_fail(self->window); if (!self->priv->screenshot_timeout) { self->priv->screenshot_timeout = gtk_timeout_add(SCREENSHOT_DELAY, screenshot_delay_timeout, self); } } MDockWindow *mdock_window_new(WnckWindow *window) { return g_object_new(MDOCK_TYPE_WINDOW, "window", window, NULL); }