1 /*
2  * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include "prefdb.h"
17 #include "composite.h"
18 #include <gdkmm.h>
19 #include <glibmm/i18n.h>
20 
21 double red, green, blue, alpha, width;
22 std::list<Trace::Point> points;
23 
Popup(int x1,int y1,int x2,int y2)24 Popup::Popup(int x1, int y1, int x2, int y2) : Gtk::Window(Gtk::WINDOW_POPUP), rect(x1, y1, x2-x1, y2-y1) {
25 	if (!is_composited())
26 		throw std::runtime_error(_("'composite' not available"));
27 
28 	Glib::RefPtr<Gdk::Visual> visual = get_screen()->get_rgba_visual();
29 	gtk_widget_set_visual(Widget::gobj(), visual->gobj());
30 	signal_draw().connect(sigc::mem_fun(*this, &Popup::on_draw));
31 	realize();
32 	move(x1, y1);
33 	resize(x2-x1, y2-y1);
34 	get_window()->input_shape_combine_region(Cairo::Region::create(), 0, 0);
35 	// tell compiz to leave this window the hell alone
36 	get_window()->set_type_hint(Gdk::WINDOW_TYPE_HINT_DESKTOP);
37 }
38 
invalidate(int x1,int y1,int x2,int y2)39 void Popup::invalidate(int x1, int y1, int x2, int y2) {
40 	if (get_mapped()) {
41 		Gdk::Rectangle inv(x1 - rect.get_x(), y1 - rect.get_y(), x2-x1, y2-y1);
42 		get_window()->invalidate_rect(inv, false);
43 	} else
44 		show();
45 }
46 
Composite()47 Composite::Composite() {
48 #define N 128
49 	int w = gdk_screen_width();
50 	int h = gdk_screen_height();
51 	num_x = (gdk_screen_width()  - 1)/N + 1;
52 	num_y = (gdk_screen_height() - 1)/N + 1;
53 	pieces = new Popup**[num_x];
54 	for (int i = 0; i < num_x; i++) {
55 		pieces[i] = new Popup*[num_y];
56 		for (int j = 0; j < num_y; j++)
57 			pieces[i][j] = new Popup(i*N,j*N,MIN((i+1)*N,w),MIN((j+1)*N,h));
58 
59 	}
60 }
61 
draw(Point p,Point q)62 void Composite::draw(Point p, Point q) {
63 	if (!points.size()) {
64 		points.push_back(p);
65 	}
66 	points.push_back(q);
67 	int x1 = (int)(p.x < q.x ? p.x : q.x);
68 	int x2 = (int)(p.x < q.x ? q.x : p.x);
69 	int y1 = (int)(p.y < q.y ? p.y : q.y);
70 	int y2 = (int)(p.y < q.y ? q.y : p.y);
71 	int bw = (int)(width/2.0) + 2;
72 	x1 -= bw; y1 -= bw;
73 	x2 += bw; y2 += bw;
74 	if (x1 < 0)
75 		x1 = 0;
76 	if (y1 < 0)
77 		y1 = 0;
78 	for (int i = x1/N; i<num_x && i<=x2/N; i++)
79 		for (int j = y1/N; j<num_y && j<=y2/N; j++)
80 			pieces[i][j]->invalidate(x1, y1, x2, y2);
81 }
82 
start_()83 void Composite::start_() {
84 	RGBA rgba = prefs.color.get();
85 	red = rgba.color.get_red_p();
86 	green = rgba.color.get_green_p();
87 	blue = rgba.color.get_blue_p();
88 	alpha = ((double)rgba.alpha)/65535.0;
89 	width = prefs.trace_width.get();
90 }
91 
draw_line(Cairo::RefPtr<Cairo::Context> ctx)92 void Popup::draw_line(Cairo::RefPtr<Cairo::Context> ctx) {
93 	if (!points.size())
94 		return;
95 	std::list<Trace::Point>::iterator i = points.begin();
96 	ctx->move_to (i->x, i->y);
97 	for (; i != points.end(); i++)
98 		ctx->line_to (i->x, i->y);
99 	ctx->set_source_rgba((red+0.5)/2.0, (green+0.5)/2.0, (blue+0.5)/2.0, alpha/2.0);
100 	ctx->set_line_width(width+1.0);
101 	ctx->set_line_cap(Cairo::LINE_CAP_ROUND);
102 	ctx->set_line_join(Cairo::LINE_JOIN_ROUND);
103 	ctx->stroke_preserve();
104 
105 	ctx->set_source_rgba(red, green, blue, alpha);
106 	ctx->set_line_width(width*0.7);
107 	ctx->stroke();
108 
109 }
110 
on_draw(const::Cairo::RefPtr<::Cairo::Context> & ctx)111 bool Popup::on_draw(const ::Cairo::RefPtr< ::Cairo::Context>& ctx) {
112 	ctx->set_operator(Cairo::OPERATOR_SOURCE);
113 	ctx->set_source_rgba(0.0, 0.0, 0.0, 0.0);
114 	ctx->paint();
115 
116 	ctx->translate(-rect.get_x(), -rect.get_y());
117 	draw_line(ctx);
118 
119 	return false;
120 }
121 
end_()122 void Composite::end_() {
123 	points.clear();
124 	for (int i = 0; i < num_x; i++)
125 		for (int j = 0; j < num_y; j++)
126 			pieces[i][j]->hide();
127 }
128 
~Composite()129 Composite::~Composite() {
130 	for (int i = 0; i < num_x; i++) {
131 		for (int j = 0; j < num_y; j++)
132 			delete pieces[i][j];
133 		delete[] pieces[i];
134 	}
135 	delete[] pieces;
136 }
137