2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU Library General Public License for more details.
12
* You should have received a copy of the GNU General Public License
13
* along with this program; if not, write to the Free Software
14
* Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
19
#include <X11/extensions/Xdamage.h>
21
static GdkPixmap* pixmap = NULL;
22
static GtkWidget* main_window = NULL;
23
static Damage damage = None;
26
int width = 400, height = 400;
30
on_realize(GtkWidget* widget, gpointer data)
32
GdkDisplay* display = gdk_display_get_default();
35
main_xwindow = GDK_WINDOW_XWINDOW(widget->window);
37
pixmap = gdk_pixmap_new(widget->window, width, height, -1);
38
clone_ctx = gdk_cairo_create(GDK_DRAWABLE(pixmap));
39
cairo_set_operator(clone_ctx, CAIRO_OPERATOR_CLEAR);
40
cairo_paint(clone_ctx);
41
cairo_destroy(clone_ctx);
43
XDamageQueryExtension (GDK_DISPLAY_XDISPLAY(display),
44
&event_base, &error_base);
46
damage = XDamageCreate(GDK_DISPLAY_XDISPLAY(display),
47
GDK_PIXMAP_XID(pixmap),
48
XDamageReportBoundingBox);
51
gtk_window_resize(GTK_WINDOW(main_window), width, height);
55
on_delete_event(GtkWidget* widget, GdkEvent* event, gpointer data)
62
on_expose_event(GtkWidget* widget, GdkEventExpose* event, gpointer data)
68
cairo_t* clone = gdk_cairo_create(GDK_DRAWABLE(pixmap));
69
cairo_t* ctx = gdk_cairo_create(GDK_DRAWABLE(widget->window));
71
cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR);
73
cairo_set_operator(ctx, CAIRO_OPERATOR_OVER);
74
cairo_set_source_surface(ctx, cairo_get_target(clone), 0, 0);
85
clone(gboolean enable)
87
GdkScreen* screen = gdk_screen_get_default();
89
GdkAtom ccm_atom = gdk_atom_intern_static_string("_CCM_CLIENT_MESSAGE");
90
GdkAtom clone_atom = enable ?
91
gdk_atom_intern_static_string("_CCM_CLONE_SCREEN_ENABLE") :
92
gdk_atom_intern_static_string("_CCM_CLONE_SCREEN_DISABLE");
94
event.client.type = GDK_CLIENT_EVENT;
95
event.client.window = gdk_screen_get_root_window(screen);
96
event.client.send_event = TRUE;
97
event.client.message_type = ccm_atom;
98
event.client.data_format = 32;
99
event.client.data.l[0] = gdk_x11_atom_to_xatom(clone_atom);
100
event.client.data.l[1] = GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(screen));
101
event.client.data.l[2] = GDK_DRAWABLE_XID(pixmap);
102
event.client.data.l[3] = gdk_drawable_get_depth(GDK_DRAWABLE(pixmap));
103
event.client.data.l[4] = main_xwindow;
105
gdk_event_send_clientmessage_toall(&event);
106
gtk_widget_queue_draw(main_window);
110
on_configure_event(GtkWidget* widget, GdkEventConfigure* event, gpointer data)
113
(event->width != width || event->height != height))
115
GdkDisplay* display = gdk_display_get_default();
118
width = event->width;
119
height = event->height;
122
if (pixmap) g_object_unref(pixmap);
123
XDamageDestroy(GDK_DISPLAY_XDISPLAY(display), damage);
125
pixmap = gdk_pixmap_new(widget->window, width, height, -1);
126
ctx = gdk_cairo_create(GDK_DRAWABLE(pixmap));
127
cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR);
131
damage = XDamageCreate(GDK_DISPLAY_XDISPLAY(display),
132
GDK_PIXMAP_XID(pixmap),
133
XDamageReportBoundingBox);
142
on_filter_event(XEvent* xevent, GdkEvent* event, gpointer data)
144
if (xevent->type == event_base + XDamageNotify)
146
XDamageSubtract(xevent->xany.display, damage, None, None);
147
gtk_widget_queue_draw(main_window);
150
return GDK_FILTER_CONTINUE;
154
main(gint argc, gchar** argv)
156
gtk_init(&argc, &argv);
158
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
159
g_signal_connect(main_window, "realize", G_CALLBACK(on_realize), NULL);
160
g_signal_connect(main_window, "delete-event", G_CALLBACK(on_delete_event), NULL);
161
g_signal_connect(main_window, "expose-event", G_CALLBACK(on_expose_event), NULL);
162
g_signal_connect(main_window, "configure-event", G_CALLBACK(on_configure_event), NULL);
164
gdk_window_add_filter(NULL, (GdkFilterFunc)on_filter_event, NULL);
166
gtk_widget_set_app_paintable(main_window, TRUE);
167
gtk_widget_realize(main_window);
168
gdk_window_set_back_pixmap(main_window->window, NULL, FALSE);
169
gtk_widget_show(main_window);
174
if (pixmap) g_object_unref(pixmap);