1 // Copyright 2008 Philip Allison <sane@not.co.uk>
3 // This file is part of cteddy.
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.
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/>.
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
);
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
));
46 gboolean
window_clicked(GtkWidget
* widget
, GdkEventButton
* event
)
48 if (event
->type
== GDK_BUTTON_PRESS
)
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
);
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
);
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
);
80 std::cerr
<< "Usage: " << argv
[0] << " <image>" << std::endl
;
84 pixbuf
= gdk_pixbuf_new_from_file(argv
[1], &gerr
);
87 std::cerr
<< "Cannot load image: " << gerr
->message
<< std::endl
;
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
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
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
);
137 std::cerr
<< "Cannot load image: " << gerr
->message
<< std::endl
;
141 GdkCursor
* cursor
= gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
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
);