1 /* $Id: eyes.c 2397 2007-01-17 17:46:35Z nick $
3 * Copyright (c) Benedikt Meurer <benedikt.meurer@unix-ag.uni-siegen.de>>
4 * Copyright (c) Danny Milosavljevic <danny_milo@gmx.net>
5 * Copyright (c) Dave Camp
6 * Copyright (c) Davyd Madeley <davyd@madeley.id.au>
7 * Copyright (c) Nick Schermer <nick@xfce.org>
8 * Copyright (c) Mikko Vartiainen <mvartiainen@gmail.com>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 * You should have received a copy of the GNU General Public License along with
21 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 * Place, Suite 330, Boston, MA 02111-1307 USA
33 #include <sys/types.h>
37 #include <libhildondesktop/libhildondesktop.h>
41 #include "accelerometer.h"
44 #define EYES_ROOT "Eyes"
45 #define DEFAULTTHEME "Default"
46 #define UPDATE_TIMEOUT 100
48 #define EYES_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE (obj,\
49 EYES_TYPE_HOME_PLUGIN,\
52 HD_DEFINE_PLUGIN_MODULE (EyesPlugin, eyes_plugin, HD_TYPE_HOME_PLUGIN_ITEM)
54 /*****************************
55 *** Eyes Plugin Functions ***
56 *****************************/
58 calculate_pupil_xy (EyesPluginContent *eyes_applet,
60 gint *pupil_x, gint *pupil_y, GtkWidget* widget)
68 gfloat xalign, yalign;
71 width = GTK_WIDGET(widget)->allocation.width;
72 height = GTK_WIDGET(widget)->allocation.height;
73 gtk_misc_get_alignment(GTK_MISC(widget), &xalign, &yalign);
80 if ( nx*nx/((eyes_applet->eye_width/2.0 - eyes_applet->pupil_width / 2)*(eyes_applet->eye_width/2.0 - eyes_applet->pupil_width/2)) + ny*ny/((eyes_applet->eye_height/2 - eyes_applet->pupil_height/2)*(eyes_applet->eye_height/2 - eyes_applet->pupil_height/2)) < 1 )
82 *pupil_x = nx + eyes_applet->eye_width / 2;
83 *pupil_y = ny + eyes_applet->eye_height / 2;
90 temp = hypot ((eyes_applet->eye_width / 2) * sina, (eyes_applet->eye_height / 2) * cosa);
91 temp -= hypot ((eyes_applet->pupil_width / 2) * sina, (eyes_applet->pupil_height / 2) * cosa);
92 temp -= hypot ((eyes_applet->wall_thickness / 2) * sina, (eyes_applet->wall_thickness / 2) * cosa);
94 *pupil_x = temp * sina + (eyes_applet->eye_width / 2);
95 *pupil_y = temp * cosa + (eyes_applet->eye_height / 2);
101 draw_eye (EyesPluginContent *eyes,
107 GdkRectangle rect, r1, r2;
109 pixbuf = gdk_pixbuf_copy (eyes->eye_image);
110 r1.x = pupil_x - eyes->pupil_width / 2;
111 r1.y = pupil_y - eyes->pupil_height / 2;
112 r1.width = eyes->pupil_width;
113 r1.height = eyes->pupil_height;
116 r2.width = eyes->eye_width;
117 r2.height = eyes->eye_height;
118 if (gdk_rectangle_intersect (&r1, &r2, &rect))
120 gdk_pixbuf_composite (eyes->pupil_image, pixbuf,
125 pupil_x - eyes->pupil_width / 2,
126 pupil_y - eyes->pupil_height / 2, 1.0, 1.0,
129 gtk_image_set_from_pixbuf (GTK_IMAGE (eyes->eyes[eye_num]),
132 g_object_unref (G_OBJECT (pixbuf));
138 timer_cb(EyesPluginContent *eyes)
141 gint pupil_x, pupil_y;
144 for (i = 0; i < eyes->num_eyes; i++)
146 if (GTK_WIDGET_REALIZED(eyes->eyes[i]))
148 accel_read(&x, &y, &z);
152 if ((x != eyes->pointer_last_x[i]) || (y != eyes->pointer_last_y[i]))
155 calculate_pupil_xy (eyes, x, y, &pupil_x, &pupil_y, eyes->eyes[i]);
156 draw_eye (eyes, i, pupil_x, pupil_y);
158 eyes->pointer_last_x[i] = x;
159 eyes->pointer_last_y[i] = y;
170 properties_load(EyesPluginContent *eyes)
174 if (eyes->active_theme)
175 path = g_build_filename(THEMESDIR, eyes->active_theme, NULL);
177 path = g_build_filename(THEMESDIR, DEFAULTTHEME, NULL);
179 load_theme(eyes, path);
187 setup_eyes(EyesPluginContent *eyes)
189 g_warning ("setup_eyes");
192 if (eyes->hbox != NULL)
194 gtk_widget_destroy(eyes->hbox);
198 eyes->hbox = gtk_hbox_new(FALSE, 0);
199 gtk_container_add(GTK_CONTAINER(eyes->align), GTK_WIDGET(eyes->hbox));
201 eyes->eyes = g_new0 (GtkWidget *, eyes->num_eyes);
202 eyes->pointer_last_x = g_new0 (gint, eyes->num_eyes);
203 eyes->pointer_last_y = g_new0 (gint, eyes->num_eyes);
205 for (i = 0; i < eyes->num_eyes; i++)
207 eyes->eyes[i] = gtk_image_new ();
209 gtk_widget_set_size_request(GTK_WIDGET(eyes->eyes[i]),
213 gtk_widget_show(eyes->eyes[i]);
215 gtk_box_pack_start(GTK_BOX(eyes->hbox), eyes->eyes[i],
218 if ((eyes->num_eyes != 1) && (i == 0))
219 gtk_misc_set_alignment (GTK_MISC (eyes->eyes[i]), 1.0, 0.5);
220 else if ((eyes->num_eyes != 1) && (i == eyes->num_eyes - 1))
221 gtk_misc_set_alignment (GTK_MISC (eyes->eyes[i]), 0.0, 0.5);
223 gtk_misc_set_alignment (GTK_MISC (eyes->eyes[i]), 0.5, 0.5);
225 eyes->pointer_last_x[i] = G_MAXINT;
226 eyes->pointer_last_y[i] = G_MAXINT;
230 eyes->eye_height / 2);
233 gtk_widget_show(eyes->hbox);
239 eyes_applet_fill(EyesPluginContent *eyes)
241 gtk_widget_show_all(GTK_WIDGET(eyes->align));
243 if (eyes->timeout_id == 0)
245 eyes->timeout_id = g_timeout_add (UPDATE_TIMEOUT,
246 (GtkFunction)timer_cb, eyes);
257 combobox_changed (GtkComboBox *combobox,
258 EyesPluginContent *eyes)
260 gchar *selected = gtk_combo_box_get_active_text (combobox);
262 if (eyes->active_theme)
263 g_free (eyes->active_theme);
265 eyes->active_theme = g_strdup (selected);
268 properties_load(eyes);
270 eyes_applet_fill(eyes);
276 eyes_properties_dialog (XfcePanelPlugin *plugin,
277 EyesPluginContent *eyes)
279 GtkWidget *dlg, *hbox, *label, *combobox;
285 xfce_panel_plugin_block_menu (plugin);
287 dlg = xfce_titled_dialog_new_with_buttons (_("Eyes"),
288 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (plugin))),
289 GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
290 GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
293 gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_CENTER);
294 gtk_window_set_icon_name (GTK_WINDOW (dlg), "xfce4-settings");
296 g_signal_connect (dlg, "response", G_CALLBACK (eyes_properties_dialog_response),
299 hbox = gtk_hbox_new(FALSE, 6);
300 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), hbox, FALSE, FALSE, 0);
301 gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
303 label = gtk_label_new_with_mnemonic (_("_Select a theme:"));
304 gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
306 combobox = gtk_combo_box_new_text ();
307 gtk_box_pack_start (GTK_BOX (hbox), combobox, FALSE, TRUE, 0);
309 if (eyes->active_theme)
310 current = g_strdup (eyes->active_theme);
312 current = g_strdup (DEFAULTTHEME);
314 if ((dir = g_dir_open(THEMESDIR, 0, NULL)) == NULL)
316 gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), current);
320 for (i = 0; (entry = g_dir_read_name(dir)) != NULL; i++)
322 gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), entry);
324 if (strcmp (entry, current) == 0)
325 gtk_combo_box_set_active (GTK_COMBO_BOX(combobox), i);
333 gtk_label_set_mnemonic_widget (GTK_LABEL (label), combobox);
335 g_signal_connect(G_OBJECT(combobox), "changed",
336 G_CALLBACK(combobox_changed), eyes);
338 gtk_widget_show_all (dlg);
343 /******************************
344 *** Panel Plugin Functions ***
345 ******************************/
347 eyes_free_data(EyesPluginContent *eyes)
349 g_warning("eyes_free_data");
350 g_return_if_fail(eyes != NULL);
352 if (eyes->timeout_id != 0)
353 g_source_remove (eyes->timeout_id);
356 g_free (eyes->pointer_last_x);
357 g_free (eyes->pointer_last_y);
359 if (eyes->active_theme != NULL)
360 g_free (eyes->active_theme);
362 if (eyes->eye_image != NULL)
363 g_object_unref (G_OBJECT (eyes->eye_image));
365 if (eyes->pupil_image != NULL)
366 g_object_unref (G_OBJECT (eyes->pupil_image));
368 if (eyes->theme_dir != NULL)
369 g_free(eyes->theme_dir);
371 if (eyes->theme_name != NULL)
372 g_free(eyes->theme_name);
374 if (eyes->eye_filename != NULL)
375 g_free(eyes->eye_filename);
377 if (eyes->pupil_filename != NULL)
378 g_free(eyes->pupil_filename);
384 eyes_read_rc_file (EyesPluginContent *eyes)
386 g_warning ("eyes_read_rc");
391 if (eyes->active_theme != NULL)
393 g_free (eyes->active_theme);
394 eyes->active_theme = NULL;
397 if ((file = xfce_panel_plugin_lookup_rc_file (plugin)) != NULL)
399 rc = xfce_rc_simple_open (file, TRUE);
404 tmp = xfce_rc_read_entry (rc, "theme", DEFAULTTHEME);
407 eyes->active_theme = g_strdup (tmp);
413 if (eyes->active_theme == NULL)
414 eyes->active_theme = g_strdup (DEFAULTTHEME);
419 eyes_write_rc_file (XfcePanelPlugin *plugin,
420 EyesPluginContent *eyes)
425 if (!(file = xfce_panel_plugin_save_location (plugin, TRUE)))
428 rc = xfce_rc_simple_open (file, FALSE);
434 if (eyes->active_theme != NULL)
435 xfce_rc_write_entry (rc, "theme", eyes->active_theme);
441 static EyesPluginContent *
444 g_warning ("eyes_plugin_new");
445 EyesPluginContent *eyes;
447 eyes = g_new0(EyesPluginContent, 1);
449 eyes->align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
451 gtk_widget_show(GTK_WIDGET(eyes->align));
453 eyes_read_rc_file (eyes);
455 properties_load(eyes);
457 eyes_applet_fill(eyes);
462 static void eyes_check_desktop (GObject *gobject, GParamSpec *pspec, EyesPluginContent *eyes)
464 g_warning ("eyes_check_desktop");
465 gchar *name = pspec->name;
467 g_object_get (gobject, name, &status, NULL);
469 eyes_applet_fill(eyes);
470 } else if (eyes->timeout_id != 0) {
471 g_source_remove (eyes->timeout_id);
472 eyes->timeout_id = 0;
476 static void eyes_plugin_dispose (GObject *object)
478 g_warning ("eyes_plugin_dispose");
480 G_OBJECT_CLASS (eyes_plugin_parent_class)->dispose (object);
483 static void eyes_plugin_finalize (GObject *object)
485 g_warning ("eyes_plugin_finalize");
486 EyesPlugin *self = EYES_HOME_PLUGIN (object);
488 eyes_free_data(self->priv);
490 G_OBJECT_CLASS (eyes_plugin_parent_class)->finalize (object);
494 eyes_plugin_realize (GtkWidget *widget)
496 g_warning ("eyes_plugin_realize");
497 GdkScreen *screen = gtk_widget_get_screen (widget);
498 gtk_widget_set_colormap (widget, gdk_screen_get_rgba_colormap (screen));
499 gtk_widget_set_app_paintable (widget, TRUE);
501 GTK_WIDGET_CLASS (eyes_plugin_parent_class)->realize (widget);
505 eyes_plugin_expose_event (GtkWidget *widget, GdkEventExpose *event)
507 g_warning ("eyes_plugin_expose_event");
510 cr = gdk_cairo_create (GDK_DRAWABLE (widget->window));
511 gdk_cairo_region (cr, event->region);
514 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
515 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
520 return GTK_WIDGET_CLASS (eyes_plugin_parent_class)->expose_event (widget, event);
524 eyes_plugin_init (EyesPlugin *desktop_plugin)
526 g_warning ("eyes_plugin_init");
527 EyesPluginContent *eyes;
529 eyes = eyes_plugin_new (desktop_plugin);
530 desktop_plugin->priv = eyes;
532 g_signal_connect (desktop_plugin, "notify::is-on-current-desktop",
533 G_CALLBACK (eyes_check_desktop), eyes);
535 gtk_container_add (GTK_CONTAINER (desktop_plugin), eyes->align);
539 eyes_plugin_class_init (EyesPluginClass *klass) {
540 g_warning ("eyes_plugin_class_init");
541 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
542 GObjectClass *object_class = G_OBJECT_CLASS (klass);
544 object_class->dispose = eyes_plugin_dispose;
545 object_class->finalize = eyes_plugin_finalize;
547 widget_class->realize = eyes_plugin_realize;
548 widget_class->expose_event = eyes_plugin_expose_event;
549 g_type_class_add_private (klass, sizeof (EyesPluginContent));
553 eyes_plugin_class_finalize (EyesPluginClass *class) {}