1 /*
2  * Copyright © 2007 Novell, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of
9  * Novell, Inc. not be used in advertising or publicity pertaining to
10  * distribution of the software without specific, written prior permission.
11  * Novell, Inc. makes no representations about the suitability of this
12  * software for any purpose. It is provided "as is" without express or
13  * implied warranty.
14  *
15  * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17  * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author: David Reveman <davidr@novell.com>
24  */
25 
26 #include <stdlib.h>
27 
28 #include <compiz-core.h>
29 
30 static void
setCursorMatrix(CompCursor * c)31 setCursorMatrix (CompCursor *c)
32 {
33     c->matrix = c->image->texture.matrix;
34     c->matrix.x0 -= (c->x * c->matrix.xx);
35     c->matrix.y0 -= (c->y * c->matrix.yy);
36 }
37 
38 void
addCursor(CompScreen * s)39 addCursor (CompScreen *s)
40 {
41     CompCursor *c;
42 
43     c = malloc (sizeof (CompCursor));
44     if (c)
45     {
46 	c->screen = s;
47 	c->image  = NULL;
48 	c->x	  = 0;
49 	c->y	  = 0;
50 
51 	c->next    = s->cursors;
52 	s->cursors = c;
53 
54 	updateCursor (c, 0, 0, 0);
55 
56 	/* XFixesHideCursor (s->display->display, s->root); */
57     }
58 }
59 
60 Bool
damageCursorRect(CompCursor * c,Bool initial,BoxPtr rect)61 damageCursorRect (CompCursor *c,
62 		  Bool       initial,
63 		  BoxPtr     rect)
64 {
65     return FALSE;
66 }
67 
68 void
addCursorDamageRect(CompCursor * c,BoxPtr rect)69 addCursorDamageRect (CompCursor *c,
70 		     BoxPtr     rect)
71 {
72     REGION region;
73 
74     if (c->screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
75 	return;
76 
77     region.extents = *rect;
78 
79     if (!(*c->screen->damageCursorRect) (c, FALSE, &region.extents))
80     {
81 	region.extents.x1 += c->x;
82 	region.extents.y1 += c->y;
83 	region.extents.x2 += c->x;
84 	region.extents.y2 += c->y;
85 
86 	region.rects = &region.extents;
87 	region.numRects = region.size = 1;
88 
89 	damageScreenRegion (c->screen, &region);
90     }
91 }
92 
93 void
addCursorDamage(CompCursor * c)94 addCursorDamage (CompCursor *c)
95 {
96     BoxRec box;
97 
98     if (c->screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
99 	return;
100 
101     box.x1 = 0;
102     box.y1 = 0;
103     box.x2 = c->image->width;
104     box.y2 = c->image->height;
105 
106     addCursorDamageRect (c, &box);
107 }
108 
109 void
updateCursor(CompCursor * c,int x,int y,unsigned long serial)110 updateCursor (CompCursor    *c,
111 	      int	    x,
112 	      int	    y,
113 	      unsigned long serial)
114 {
115     /* new current cursor */
116     if (!c->image || c->image->serial != serial)
117     {
118 	CompCursorImage *cursorImage;
119 
120 	cursorImage = findCursorImageAtScreen (c->screen, serial);
121 	if (!cursorImage)
122 	{
123 	    Display	      *dpy = c->screen->display->display;
124 	    XFixesCursorImage *image;
125 
126 	    image = XFixesGetCursorImage (dpy);
127 	    if (!image)
128 		return;
129 
130 	    cursorImage = malloc (sizeof (CompCursorImage));
131 	    if (!cursorImage)
132 	    {
133 		XFree (image);
134 		return;
135 	    }
136 
137 	    x = image->x;
138 	    y = image->y;
139 
140 	    cursorImage->serial = image->cursor_serial;
141 	    cursorImage->xhot   = image->xhot;
142 	    cursorImage->yhot   = image->yhot;
143 	    cursorImage->width  = image->width;
144 	    cursorImage->height = image->height;
145 
146 	    initTexture (c->screen, &cursorImage->texture);
147 
148 	    if (!imageBufferToTexture (c->screen,
149 				       &cursorImage->texture,
150 				       (char *) image->pixels,
151 				       image->width,
152 				       image->height))
153 	    {
154 		free (cursorImage);
155 		XFree (image);
156 		return;
157 	    }
158 
159 	    XFree (image);
160 
161 	    cursorImage->next = c->screen->cursorImages;
162 	    c->screen->cursorImages = cursorImage;
163 	}
164 
165 	if (c->image)
166 	    addCursorDamage (c);
167 
168 	c->image = cursorImage;
169 
170 	c->x = x - c->image->xhot;
171 	c->y = y - c->image->yhot;
172 
173 	setCursorMatrix (c);
174 
175 	addCursorDamage (c);
176     }
177     else
178     {
179 	int newX, newY;
180 
181 	newX = x - c->image->xhot;
182 	newY = y - c->image->yhot;
183 
184 	if (c->x != newX || c->y != newY)
185 	{
186 	    addCursorDamage (c);
187 
188 	    c->x = newX;
189 	    c->y = newY;
190 
191 	    setCursorMatrix (c);
192 
193 	    addCursorDamage (c);
194 	}
195     }
196 }
197