summaryrefslogtreecommitdiffstats
path: root/tightvnc-1.3dev5-vncviewer-alpha-cursor.patch
blob: c9b31e7679151afe9e48bf29c05d8e03d05a2375 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
--- vnc_unixsrc.orig/vncviewer/cursor.c	2003-01-15 04:46:52.000000000 -0500
+++ vnc_unixsrc/vncviewer/cursor.c	2005-02-05 12:28:10.000000000 -0500
@@ -472,6 +472,140 @@
   int offset, bytesPerPixel;
   char *pos;
 
+#define alphahack
+#ifdef alphahack
+  /* hack to have cursor transparency at 32bpp <runge@karlrunge.com> */
+  static int alphablend = -1;
+
+  if (alphablend < 0) {
+	/* you have to set NO_ALPHABLEND=1 in your environment to disable */
+	if (getenv("NO_ALPHABLEND")) {
+		alphablend = 0;
+	} else {
+		alphablend = 1;
+	}
+  }
+
+  bytesPerPixel = myFormat.bitsPerPixel / 8;
+
+  if (alphablend && bytesPerPixel == 4) {
+	unsigned long pixel, put, *upos, *upix;
+	int got_alpha = 0, rsX, rsY, rsW, rsH;
+	static XImage *image = NULL;
+	static int iwidth = 128;
+
+	if (! image) {
+		/* watch out for tiny fb (rare) */
+		if (iwidth > si.framebufferWidth) {
+			iwidth = si.framebufferWidth;
+		}
+		if (iwidth > si.framebufferHeight) {
+			iwidth = si.framebufferHeight;
+		}
+
+		/* initialize an XImage with a chunk of desktopWin */
+		image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth,
+		    AllPlanes, ZPixmap);
+	}
+
+	/* first check if there is any non-zero alpha channel data at all: */
+	for (y = 0; y < rcHeight; y++) {
+		for (x = 0; x < rcWidth; x++) {
+			int alpha;
+
+			offset = y * rcWidth + x;
+			pos = (char *)&rcSource[offset * bytesPerPixel];
+
+			upos = (unsigned long *) pos;
+			alpha = (*upos & 0xff000000) >> 24;
+			if (alpha) {
+				got_alpha = 1;
+				break;
+			}
+		}
+		if (got_alpha) {
+			break;
+		}
+	}
+
+	if (!got_alpha) {
+		/* no alpha channel data, fallback to the old way */
+		goto oldway;
+	}
+
+	/* load the saved fb patch in to image (faster way?) */
+	XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight,
+	    AllPlanes, ZPixmap, image, 0, 0);
+	upix = (unsigned long *)image->data;
+
+	/* if the richcursor is clipped, the fb patch will be smaller */
+	rsW = rcWidth;
+	rsX = 0;	/* used to denote a shift from the left side */
+	x = rcCursorX - rcHotX;
+	if (x < 0) {
+		rsW += x;
+		rsX = -x;
+	} else if (x + rsW > si.framebufferWidth) {
+		rsW = si.framebufferWidth - x;
+	}
+	rsH = rcHeight;
+	rsY = 0;	/* used to denote a shift from the top side */
+	y = rcCursorY - rcHotY;
+	if (y < 0) {
+		rsH += y;
+		rsY = -y;
+	} else if (y + rsH > si.framebufferHeight) {
+		rsH = si.framebufferHeight - y;
+	}
+
+	/*
+	 * now loop over the cursor data, blend in the fb values,
+	 * and then overwrite the fb (CopyDataToScreen())
+	 */
+	for (y = 0; y < rcHeight; y++) {
+		y0 = rcCursorY - rcHotY + y;
+		if (y0 < 0 || y0 >= si.framebufferHeight) {
+			continue;	/* clipped */
+		}
+		for (x = 0; x < rcWidth; x++) {
+			int alpha, color_curs, color_fb, i;
+
+			x0 = rcCursorX - rcHotX + x;
+			if (x0 < 0 || x0 >= si.framebufferWidth) {
+				continue;	/* clipped */
+			}
+
+			offset = y * rcWidth + x;
+			pos = (char *)&rcSource[offset * bytesPerPixel];
+
+			/* extract secret alpha byte from rich cursor: */
+			upos = (unsigned long *) pos;
+			alpha = (*upos & 0xff000000) >> 24;	/* XXX MSB? */
+
+			/* extract the pixel from the fb: */
+			pixel = *(upix + (y-rsY)*iwidth + (x-rsX));
+
+			put = 0;
+			/* for simplicity, blend all 4 bytes */
+			for (i = 0; i < 4; i++) {
+				int sh = i*8;
+				color_curs = ((0xff << sh) & *upos) >> sh;
+				color_fb   = ((0xff << sh) & pixel) >> sh;
+
+				/* XXX assumes pre-multipled color_curs */
+				color_fb = color_curs
+				    + ((0xff - alpha) * color_fb)/0xff;
+				put |= color_fb << sh;
+			}
+			/* place in the fb: */
+	    		CopyDataToScreen((char *)&put, x0, y0, 1, 1);
+		}
+	}
+	return;
+  }
+oldway:
+#endif
+
   bytesPerPixel = myFormat.bitsPerPixel / 8;
 
   /* FIXME: Speed optimization is possible. */