Use PKGDATADIR from autoconf to locate the cursor image
[cteddy.git] / src / cteddy.cxx
blob032a23634d0c38f631c1864ed7558ac02169c831
1 // Copyright 2008 Philip Allison <sane@not.co.uk>
3 // This file is part of cteddy.
4 //
5 // cteddy is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // cteddy is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with cteddy. If not, see <http://www.gnu.org/licenses/>.
18 #include <iostream>
20 #include <gtk/gtk.h>
22 GtkWidget* window;
23 GError* gerr = NULL;
24 GdkPixbuf* pixbuf;
25 gint width, height;
27 gboolean handle_expose(GtkWidget* widget, GdkEventExpose* event)
29 cairo_t* cairo = gdk_cairo_create(widget->window);
31 cairo_set_source_rgba (cairo, 1.0f, 1.0f, 1.0f, 0.0f);
32 cairo_set_operator (cairo, CAIRO_OPERATOR_SOURCE);
33 cairo_paint (cairo);
35 gdk_cairo_set_source_pixbuf(cairo, pixbuf, 0.0f, 0.0f);
37 cairo_rectangle(cairo, 0.0f, 0.0f,
38 static_cast<double>(width), static_cast<double>(height));
39 cairo_fill(cairo);
41 cairo_destroy(cairo);
43 return false;
46 gboolean window_clicked(GtkWidget* widget, GdkEventButton* event)
48 if (event->type == GDK_BUTTON_PRESS)
50 switch(event->button)
52 case 1:
53 gtk_window_begin_move_drag(GTK_WINDOW(window),
54 event->button, static_cast<gint>(event->x_root),
55 static_cast<gint>(event->y_root), event->time);
56 break;
57 default:
58 gtk_main_quit();
59 break;
62 return true;
65 void handle_screen(GtkWidget* window, GdkScreen* old, gpointer data)
67 GdkScreen* s = gtk_widget_get_screen(window);
68 GdkColormap* c = gdk_screen_get_rgba_colormap(s);
69 if (!c)
70 c = gdk_screen_get_rgb_colormap(s);
71 gtk_widget_set_colormap(window, c);
74 int main (int argc, char* argv[])
76 gtk_init(&argc, &argv);
78 if (argc < 2)
80 std::cerr << "Usage: " << argv[0] << " <image>" << std::endl;
81 return 1;
84 pixbuf = gdk_pixbuf_new_from_file(argv[1], &gerr);
85 if (gerr)
87 std::cerr << "Cannot load image: " << gerr->message << std::endl;
88 g_error_free(gerr);
89 return 1;
92 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
94 gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
95 g_signal_connect(G_OBJECT(window), "expose-event", G_CALLBACK(handle_expose), NULL);
96 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
97 g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(window_clicked), NULL);
98 g_signal_connect(G_OBJECT(window), "screen-changed", G_CALLBACK(handle_screen), NULL);
101 // Grap pixmap and alpha-thresholded bitmap from original pixmap
102 GdkPixmap* pixmap;
103 GdkBitmap* bitmap;
104 gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &bitmap, 128);
106 // Set window size to image size
107 gdk_drawable_get_size(pixmap, &width, &height);
108 gtk_widget_set_size_request(window, width, height);
110 // If we have an alpha channel on the image, set the window's input shape,
111 // clearing it completely first
112 if (bitmap)
114 gtk_widget_input_shape_combine_mask(window, NULL, 0, 0);
115 gtk_widget_input_shape_combine_mask(window, bitmap, 0, 0);
118 g_object_unref(G_OBJECT(pixmap));
119 g_object_unref(G_OBJECT(bitmap));
122 gtk_window_set_title(GTK_WINDOW(window), "cteddy");
123 gtk_window_set_resizable(GTK_WINDOW(window), false);
124 gtk_window_set_decorated(GTK_WINDOW(window), false);
125 gtk_widget_set_app_paintable(window, true);
127 handle_screen(window, NULL, NULL);
129 // Have to do this before we can use window->window as a GdkWindow*
130 gtk_widget_realize(window);
133 // Load in the heart-shaped cursor image and use it for our window's cursor
134 GdkPixbuf* heart = gdk_pixbuf_new_from_file(PKGDATADIR "/heart.png", &gerr);
135 if (gerr)
137 std::cerr << "Cannot load image: " << gerr->message << std::endl;
138 g_error_free(gerr);
139 return 1;
141 GdkCursor* cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
142 heart, 12, 12);
143 gdk_window_set_cursor(window->window, cursor);
146 gdk_window_set_back_pixmap(window->window, NULL, false);
148 g_object_set(G_OBJECT(window), "focus-on-map", false, NULL);
150 gtk_widget_show_all(window);
152 gtk_main();
154 return 0;