1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2003 Richard Hult <richard@imendio.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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 GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include <config.h>
22 #include <gdk/gdk.h>
23 #include <gdk/gdkx.h>
24 #include <gtk/gtk.h>
25 #include "drw-utils.h"
26 
27 static GdkPixbuf *
create_tile_pixbuf(GdkPixbuf * dest_pixbuf,GdkPixbuf * src_pixbuf,GdkRectangle * field_geom,guint alpha,GdkColor * bg_color)28 create_tile_pixbuf (GdkPixbuf    *dest_pixbuf,
29 		    GdkPixbuf    *src_pixbuf,
30 		    GdkRectangle *field_geom,
31 		    guint         alpha,
32 		    GdkColor     *bg_color)
33 {
34 	gboolean need_composite;
35 	gboolean use_simple;
36 	gdouble  cx, cy;
37 	gdouble  colorv;
38 	gint     pwidth, pheight;
39 
40 	need_composite = (alpha < 255 || gdk_pixbuf_get_has_alpha (src_pixbuf));
41 	use_simple = (dest_pixbuf == NULL);
42 
43 	if (dest_pixbuf == NULL)
44 		dest_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
45 					      FALSE, 8,
46 					      field_geom->width, field_geom->height);
47 
48 	if (need_composite && use_simple)
49 		colorv = ((bg_color->red & 0xff00) << 8) |
50 			(bg_color->green & 0xff00) |
51 			((bg_color->blue & 0xff00) >> 8);
52 	else
53 		colorv = 0;
54 
55 	pwidth = gdk_pixbuf_get_width (src_pixbuf);
56 	pheight = gdk_pixbuf_get_height (src_pixbuf);
57 
58 	for (cy = 0; cy < field_geom->height; cy += pheight) {
59 		for (cx = 0; cx < field_geom->width; cx += pwidth) {
60 			if (need_composite && !use_simple)
61 				gdk_pixbuf_composite (src_pixbuf, dest_pixbuf,
62 						      cx, cy,
63 						      MIN (pwidth, field_geom->width - cx),
64 						      MIN (pheight, field_geom->height - cy),
65 						      cx, cy,
66 						      1.0, 1.0,
67 						      GDK_INTERP_BILINEAR,
68 						      alpha);
69 			else if (need_composite && use_simple)
70 				gdk_pixbuf_composite_color (src_pixbuf, dest_pixbuf,
71 							    cx, cy,
72 							    MIN (pwidth, field_geom->width - cx),
73 							    MIN (pheight, field_geom->height - cy),
74 							    cx, cy,
75 							    1.0, 1.0,
76 							    GDK_INTERP_BILINEAR,
77 							    alpha,
78 							    65536, 65536, 65536,
79 							    colorv, colorv);
80 			else
81 				gdk_pixbuf_copy_area (src_pixbuf,
82 						      0, 0,
83 						      MIN (pwidth, field_geom->width - cx),
84 						      MIN (pheight, field_geom->height - cy),
85 						      dest_pixbuf,
86 						      cx, cy);
87 		}
88 	}
89 
90 	return dest_pixbuf;
91 }
92 
93 static gboolean
window_draw_event(GtkWidget * widget,cairo_t * cr,gpointer data)94 window_draw_event   (GtkWidget      *widget,
95 		     cairo_t        *cr,
96 		     gpointer        data)
97 {
98 	int              width;
99 	int              height;
100 
101 	gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
102 
103 	cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
104 	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
105 	cairo_paint (cr);
106 
107 	/* draw a box */
108 	cairo_rectangle (cr, 0, 0, width, height);
109 	cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 0.5);
110 	cairo_fill (cr);
111 
112 	return FALSE;
113 }
114 
115 static void
set_pixmap_background(GtkWidget * window)116 set_pixmap_background (GtkWidget *window)
117 {
118 	GdkScreen    *screen;
119 	GdkPixbuf    *tmp_pixbuf, *pixbuf, *tile_pixbuf;
120 	GdkRectangle  rect;
121 	GdkColor      color;
122 	gint          width, height, scale;
123 	cairo_t      *cr;
124 
125 	gtk_widget_realize (window);
126 
127 	screen = gtk_widget_get_screen (window);
128 	scale = gtk_widget_get_scale_factor (window);
129 	width = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale;
130 	height = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) / scale;
131 
132 	tmp_pixbuf = gdk_pixbuf_get_from_window (gdk_screen_get_root_window (screen),
133 						 0,
134 						 0,
135 						 width, height);
136 
137 	pixbuf = gdk_pixbuf_new_from_file (IMAGEDIR "/ocean-stripes.png", NULL);
138 
139 	rect.x = 0;
140 	rect.y = 0;
141 	rect.width = width;
142 	rect.height = height;
143 
144 	color.red = 0;
145 	color.blue = 0;
146 	color.green = 0;
147 
148 	tile_pixbuf = create_tile_pixbuf (NULL,
149 					  pixbuf,
150 					  &rect,
151 					  155,
152 					  &color);
153 
154 	g_object_unref (pixbuf);
155 
156 	gdk_pixbuf_composite (tile_pixbuf,
157 			      tmp_pixbuf,
158 			      0,
159 			      0,
160 			      width,
161 			      height,
162 			      0,
163 			      0,
164 			      scale,
165 			      scale,
166 			      GDK_INTERP_NEAREST,
167 			      225);
168 
169 	g_object_unref (tile_pixbuf);
170 
171 	cr = gdk_cairo_create (gtk_widget_get_window (window));
172 	gdk_cairo_set_source_pixbuf (cr, tmp_pixbuf, 0, 0);
173 	cairo_paint (cr);
174 
175 	g_object_unref (tmp_pixbuf);
176 
177 	cairo_destroy (cr);
178 }
179 
180 void
drw_setup_background(GtkWidget * window)181 drw_setup_background (GtkWidget *window)
182 {
183 	GdkScreen    *screen;
184 	gboolean      is_composited;
185 
186 	screen = gtk_widget_get_screen (window);
187 	is_composited = gdk_screen_is_composited (screen);
188 
189 	if (is_composited) {
190 		g_signal_connect (window, "draw", G_CALLBACK (window_draw_event), window);
191 	} else {
192 		set_pixmap_background (window);
193 	}
194 }
195 
196