File: | xlibclient.c |
Location: | line 182, column 16 |
Description: | Potential leak of memory pointed to by 'pPriv' |
1 | /* | |||||
2 | * Permission is hereby granted, free of charge, to any person obtaining a | |||||
3 | * copy of this software and associated documentation files (the "Software"), | |||||
4 | * to deal in the Software without restriction, including without limitation | |||||
5 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||||
6 | * and/or sell copies of the Software, and to permit persons to whom the | |||||
7 | * Software is furnished to do so, subject to the following conditions: | |||||
8 | * | |||||
9 | * The above copyright notice and this permission notice (including the next | |||||
10 | * paragraph) shall be included in all copies or substantial portions of the | |||||
11 | * Software. | |||||
12 | * | |||||
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||||
16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||||
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||||
19 | * DEALINGS IN THE SOFTWARE. | |||||
20 | * | |||||
21 | * Authors: | |||||
22 | * | |||||
23 | * Paulo Zanoni <pzanoni@mandriva.com> | |||||
24 | * Tuan Bui <tuanbui918@gmail.com> | |||||
25 | * Colin Cornaby <colin.cornaby@mac.com> | |||||
26 | * Timothy Fleck <tim.cs.pdx@gmail.com> | |||||
27 | * Colin Hill <colin.james.hill@gmail.com> | |||||
28 | * Weseung Hwang <weseung@gmail.com> | |||||
29 | * Nathaniel Way <nathanielcw@hotmail.com> | |||||
30 | */ | |||||
31 | ||||||
32 | #include <stdlib.h> | |||||
33 | ||||||
34 | #include <sys/ipc.h> | |||||
35 | #include <sys/shm.h> | |||||
36 | ||||||
37 | #include <X11/Xlib.h> | |||||
38 | #include <X11/Xutil.h> | |||||
39 | #include <X11/XKBlib.h> | |||||
40 | #include <X11/extensions/XShm.h> | |||||
41 | ||||||
42 | #include <xorg-server.h> | |||||
43 | #include <xf86.h> | |||||
44 | ||||||
45 | #ifdef HAVE_CONFIG_H1 | |||||
46 | #include "config.h" | |||||
47 | #endif | |||||
48 | ||||||
49 | #include "client.h" | |||||
50 | ||||||
51 | #include "nested_input.h" | |||||
52 | ||||||
53 | struct NestedClientPrivate { | |||||
54 | Display *display; | |||||
55 | int screenNumber; | |||||
56 | Screen *screen; | |||||
57 | Window rootWindow; | |||||
58 | Window window; | |||||
59 | XImage *img; | |||||
60 | GC gc; | |||||
61 | Boolint usingShm; | |||||
62 | XShmSegmentInfo shminfo; | |||||
63 | int scrnIndex; /* stored only for xf86DrvMsg usage */ | |||||
64 | Cursor mycursor; /* Test cursor */ | |||||
65 | Pixmap bitmapNoData; | |||||
66 | XColor color1; | |||||
67 | DeviceIntPtr dev; // The pointer to the input device. Passed back to the | |||||
68 | // input driver when posting input events. | |||||
69 | ||||||
70 | struct { | |||||
71 | int op; | |||||
72 | int event; | |||||
73 | int error; | |||||
74 | int major; | |||||
75 | int minor; | |||||
76 | } xkb; | |||||
77 | }; | |||||
78 | ||||||
79 | /* Checks if a display is open */ | |||||
80 | Boolint | |||||
81 | NestedClientCheckDisplay(char *displayName) { | |||||
82 | Display *d; | |||||
83 | ||||||
84 | d = XOpenDisplay(displayName); | |||||
85 | if (!d) { | |||||
86 | return FALSE0; | |||||
87 | } else { | |||||
88 | XCloseDisplay(d); | |||||
89 | return TRUE1; | |||||
90 | } | |||||
91 | } | |||||
92 | ||||||
93 | Boolint | |||||
94 | NestedClientValidDepth(int depth) { | |||||
95 | /* XXX: implement! */ | |||||
96 | return TRUE1; | |||||
97 | } | |||||
98 | ||||||
99 | static Boolint | |||||
100 | NestedClientTryXShm(NestedClientPrivatePtr pPriv, int scrnIndex, int width, int height, int depth) { | |||||
101 | int shmMajor, shmMinor; | |||||
102 | Boolint hasSharedPixmaps; | |||||
103 | ||||||
104 | if (!XShmQueryExtension(pPriv->display)) { | |||||
105 | xf86DrvMsg(scrnIndex, X_INFO, "XShmQueryExtension failed. Dropping XShm support.\n"); | |||||
106 | ||||||
107 | return FALSE0; | |||||
108 | } | |||||
109 | ||||||
110 | if (XShmQueryVersion(pPriv->display, &shmMajor, &shmMinor, | |||||
111 | &hasSharedPixmaps)) { | |||||
112 | xf86DrvMsg(scrnIndex, X_INFO, | |||||
113 | "XShm extension version %d.%d %s shared pixmaps\n", | |||||
114 | shmMajor, shmMinor, (hasSharedPixmaps) ? "with" : "without"); | |||||
115 | } | |||||
116 | ||||||
117 | pPriv->img = XShmCreateImage(pPriv->display, | |||||
118 | DefaultVisualOfScreen(pPriv->screen)((pPriv->screen)->root_visual), | |||||
119 | depth, | |||||
120 | ZPixmap2, | |||||
121 | NULL((void*)0), /* data */ | |||||
122 | &pPriv->shminfo, | |||||
123 | width, | |||||
124 | height); | |||||
125 | ||||||
126 | if (!pPriv->img) { | |||||
127 | xf86DrvMsg(scrnIndex, X_ERROR, "XShmCreateImage failed. Dropping XShm support.\n"); | |||||
128 | return FALSE0; | |||||
129 | } | |||||
130 | ||||||
131 | /* XXX: change the 0777 mask? */ | |||||
132 | pPriv->shminfo.shmid = shmget(IPC_PRIVATE((key_t)0), | |||||
133 | pPriv->img->bytes_per_line * | |||||
134 | pPriv->img->height, | |||||
135 | IPC_CREAT001000 | 0777); | |||||
136 | ||||||
137 | if (pPriv->shminfo.shmid == -1) { | |||||
138 | xf86DrvMsg(scrnIndex, X_ERROR, "shmget failed. Dropping XShm support.\n"); | |||||
139 | XDestroyImage(pPriv->img)((*((pPriv->img)->f.destroy_image))((pPriv->img))); | |||||
140 | return FALSE0; | |||||
141 | } | |||||
142 | ||||||
143 | pPriv->shminfo.shmaddr = (char *)shmat(pPriv->shminfo.shmid, NULL((void*)0), 0); | |||||
144 | ||||||
145 | if (pPriv->shminfo.shmaddr == (char *) -1) { | |||||
146 | xf86DrvMsg(scrnIndex, X_ERROR, "shmaddr failed. Dropping XShm support.\n"); | |||||
147 | XDestroyImage(pPriv->img)((*((pPriv->img)->f.destroy_image))((pPriv->img))); | |||||
148 | return FALSE0; | |||||
149 | } | |||||
150 | ||||||
151 | pPriv->img->data = pPriv->shminfo.shmaddr; | |||||
152 | pPriv->shminfo.readOnly = FALSE0; | |||||
153 | XShmAttach(pPriv->display, &pPriv->shminfo); | |||||
154 | pPriv->usingShm = TRUE1; | |||||
155 | ||||||
156 | return TRUE1; | |||||
157 | } | |||||
158 | ||||||
159 | ||||||
160 | NestedClientPrivatePtr | |||||
161 | NestedClientCreateScreen(int scrnIndex, | |||||
162 | char *displayName, | |||||
163 | int width, | |||||
164 | int height, | |||||
165 | int originX, | |||||
166 | int originY, | |||||
167 | int depth, | |||||
168 | int bitsPerPixel, | |||||
169 | Pixel *retRedMask, | |||||
170 | Pixel *retGreenMask, | |||||
171 | Pixel *retBlueMask) { | |||||
172 | NestedClientPrivatePtr pPriv; | |||||
173 | XSizeHints sizeHints; | |||||
174 | Boolint supported; | |||||
175 | char windowTitle[32]; | |||||
176 | ||||||
177 | pPriv = malloc(sizeof(struct NestedClientPrivate)); | |||||
| ||||||
178 | pPriv->scrnIndex = scrnIndex; | |||||
179 | ||||||
180 | pPriv->display = XOpenDisplay(displayName); | |||||
181 | if (!pPriv->display) | |||||
182 | return NULL((void*)0); | |||||
| ||||||
183 | ||||||
184 | supported = XkbQueryExtension(pPriv->display, &pPriv->xkb.op, &pPriv->xkb.event, | |||||
185 | &pPriv->xkb.error, &pPriv->xkb.major, &pPriv->xkb.minor); | |||||
186 | if (!supported) { | |||||
187 | xf86DrvMsg(pPriv->scrnIndex, X_ERROR, "The remote server does not support the XKEYBOARD extension.\n"); | |||||
188 | XCloseDisplay(pPriv->display); | |||||
189 | return NULL((void*)0); | |||||
190 | } | |||||
191 | ||||||
192 | pPriv->screenNumber = DefaultScreen(pPriv->display)(((_XPrivDisplay)(pPriv->display))->default_screen); | |||||
193 | pPriv->screen = ScreenOfDisplay(pPriv->display, pPriv->screenNumber)(&((_XPrivDisplay)(pPriv->display))->screens[pPriv-> screenNumber]); | |||||
194 | pPriv->rootWindow = RootWindow(pPriv->display, pPriv->screenNumber)((&((_XPrivDisplay)(pPriv->display))->screens[pPriv ->screenNumber])->root); | |||||
195 | pPriv->gc = DefaultGC(pPriv->display, pPriv->screenNumber)((&((_XPrivDisplay)(pPriv->display))->screens[pPriv ->screenNumber])->default_gc); | |||||
196 | ||||||
197 | pPriv->window = XCreateSimpleWindow(pPriv->display, pPriv->rootWindow, | |||||
198 | originX, originY, width, height, 0, 0, 0); | |||||
199 | ||||||
200 | sizeHints.flags = PPosition(1L << 2) | PSize(1L << 3) | PMinSize(1L << 4) | PMaxSize(1L << 5); | |||||
201 | sizeHints.min_width = width; | |||||
202 | sizeHints.max_width = width; | |||||
203 | sizeHints.min_height = height; | |||||
204 | sizeHints.max_height = height; | |||||
205 | XSetWMNormalHints(pPriv->display, pPriv->window, &sizeHints); | |||||
206 | ||||||
207 | snprintf(windowTitle, sizeof(windowTitle), "Screen %d", scrnIndex)__builtin___snprintf_chk (windowTitle, sizeof(windowTitle), 0 , __builtin_object_size (windowTitle, 2 > 1 ? 1 : 0), "Screen %d" , scrnIndex); | |||||
208 | ||||||
209 | XStoreName(pPriv->display, pPriv->window, windowTitle); | |||||
210 | ||||||
211 | XMapWindow(pPriv->display, pPriv->window); | |||||
212 | ||||||
213 | XSelectInput(pPriv->display, pPriv->window, ExposureMask(1L<<15) | | |||||
214 | PointerMotionMask(1L<<6) | EnterWindowMask(1L<<4) | LeaveWindowMask(1L<<5) | | |||||
215 | ButtonPressMask(1L<<2) | ButtonReleaseMask(1L<<3) | KeyPressMask(1L<<0) | | |||||
216 | KeyReleaseMask(1L<<1)); | |||||
217 | ||||||
218 | if (!NestedClientTryXShm(pPriv, scrnIndex, width, height, depth)) { | |||||
219 | pPriv->img = XCreateImage(pPriv->display, | |||||
220 | DefaultVisualOfScreen(pPriv->screen)((pPriv->screen)->root_visual), | |||||
221 | depth, | |||||
222 | ZPixmap2, | |||||
223 | 0, /* offset */ | |||||
224 | NULL((void*)0), /* data */ | |||||
225 | width, | |||||
226 | height, | |||||
227 | 32, /* XXX: bitmap_pad */ | |||||
228 | 0 /* XXX: bytes_per_line */); | |||||
229 | ||||||
230 | if (!pPriv->img) | |||||
231 | return NULL((void*)0); | |||||
232 | ||||||
233 | pPriv->img->data = malloc(pPriv->img->bytes_per_line * pPriv->img->height); | |||||
234 | pPriv->usingShm = FALSE0; | |||||
235 | } | |||||
236 | ||||||
237 | if (!pPriv->img->data) | |||||
238 | return NULL((void*)0); | |||||
239 | ||||||
240 | NestedClientHideCursor(pPriv); /* Hide cursor */ | |||||
241 | ||||||
242 | #if 0 | |||||
243 | xf86DrvMsg(scrnIndex, X_INFO, "width: %d\n", pPriv->img->width); | |||||
244 | xf86DrvMsg(scrnIndex, X_INFO, "height: %d\n", pPriv->img->height); | |||||
245 | xf86DrvMsg(scrnIndex, X_INFO, "xoffset: %d\n", pPriv->img->xoffset); | |||||
246 | xf86DrvMsg(scrnIndex, X_INFO, "depth: %d\n", pPriv->img->depth); | |||||
247 | xf86DrvMsg(scrnIndex, X_INFO, "bpp: %d\n", pPriv->img->bits_per_pixel); | |||||
248 | xf86DrvMsg(scrnIndex, X_INFO, "red_mask: 0x%lx\n", pPriv->img->red_mask); | |||||
249 | xf86DrvMsg(scrnIndex, X_INFO, "gre_mask: 0x%lx\n", pPriv->img->green_mask); | |||||
250 | xf86DrvMsg(scrnIndex, X_INFO, "blu_mask: 0x%lx\n", pPriv->img->blue_mask); | |||||
251 | #endif | |||||
252 | ||||||
253 | *retRedMask = pPriv->img->red_mask; | |||||
254 | *retGreenMask = pPriv->img->green_mask; | |||||
255 | *retBlueMask = pPriv->img->blue_mask; | |||||
256 | ||||||
257 | XEvent ev; | |||||
258 | while (1) { | |||||
259 | XNextEvent(pPriv->display, &ev); | |||||
260 | if (ev.type == Expose12) { | |||||
261 | break; | |||||
262 | } | |||||
263 | } | |||||
264 | ||||||
265 | pPriv->dev = (DeviceIntPtr)NULL((void*)0); | |||||
266 | ||||||
267 | return pPriv; | |||||
268 | } | |||||
269 | ||||||
270 | void NestedClientHideCursor(NestedClientPrivatePtr pPriv) { | |||||
271 | char noData[]= {0,0,0,0,0,0,0,0}; | |||||
272 | pPriv->color1.red = pPriv->color1.green = pPriv->color1.blue = 0; | |||||
273 | ||||||
274 | pPriv->bitmapNoData = XCreateBitmapFromData(pPriv->display, | |||||
275 | pPriv->window, noData, 7, 7); | |||||
276 | ||||||
277 | pPriv->mycursor = XCreatePixmapCursor(pPriv->display, | |||||
278 | pPriv->bitmapNoData, pPriv->bitmapNoData, | |||||
279 | &pPriv->color1, &pPriv->color1, 0, 0); | |||||
280 | ||||||
281 | XDefineCursor(pPriv->display, pPriv->window, pPriv->mycursor); | |||||
282 | XFreeCursor(pPriv->display, pPriv->mycursor); | |||||
283 | } | |||||
284 | ||||||
285 | char * | |||||
286 | NestedClientGetFrameBuffer(NestedClientPrivatePtr pPriv) { | |||||
287 | return pPriv->img->data; | |||||
288 | } | |||||
289 | ||||||
290 | void | |||||
291 | NestedClientUpdateScreen(NestedClientPrivatePtr pPriv, int16_t x1, | |||||
292 | int16_t y1, int16_t x2, int16_t y2) { | |||||
293 | if (pPriv->usingShm) { | |||||
294 | XShmPutImage(pPriv->display, pPriv->window, pPriv->gc, pPriv->img, | |||||
295 | x1, y1, x1, y1, x2 - x1, y2 - y1, FALSE0); | |||||
296 | /* Without this sync we get some freezes, probably due to some lock | |||||
297 | * in the shm usage */ | |||||
298 | XSync(pPriv->display, FALSE0); | |||||
299 | } else { | |||||
300 | XPutImage(pPriv->display, pPriv->window, pPriv->gc, pPriv->img, | |||||
301 | x1, y1, x1, y1, x2 - x1, y2 - y1); | |||||
302 | } | |||||
303 | } | |||||
304 | ||||||
305 | void | |||||
306 | NestedClientCheckEvents(NestedClientPrivatePtr pPriv) { | |||||
307 | XEvent ev; | |||||
308 | ||||||
309 | while(XCheckMaskEvent(pPriv->display, ~0, &ev)) { | |||||
310 | switch (ev.type) { | |||||
311 | case Expose12: | |||||
312 | NestedClientUpdateScreen(pPriv, | |||||
313 | ((XExposeEvent*)&ev)->x, | |||||
314 | ((XExposeEvent*)&ev)->y, | |||||
315 | ((XExposeEvent*)&ev)->x + | |||||
316 | ((XExposeEvent*)&ev)->width, | |||||
317 | ((XExposeEvent*)&ev)->y + | |||||
318 | ((XExposeEvent*)&ev)->height); | |||||
319 | break; | |||||
320 | ||||||
321 | case MotionNotify6: | |||||
322 | if (!pPriv->dev) { | |||||
323 | xf86DrvMsg(pPriv->scrnIndex, X_INFO, "Input device is not yet initialized, ignoring input.\n"); | |||||
324 | break; | |||||
325 | } | |||||
326 | ||||||
327 | NestedInputPostMouseMotionEvent(pPriv->dev, | |||||
328 | ((XMotionEvent*)&ev)->x, | |||||
329 | ((XMotionEvent*)&ev)->y); | |||||
330 | break; | |||||
331 | ||||||
332 | case ButtonPress4: | |||||
333 | case ButtonRelease5: | |||||
334 | if (!pPriv->dev) { | |||||
335 | xf86DrvMsg(pPriv->scrnIndex, X_INFO, "Input device is not yet initialized, ignoring input.\n"); | |||||
336 | break; | |||||
337 | } | |||||
338 | ||||||
339 | NestedInputPostButtonEvent(pPriv->dev, ev.xbutton.button, ev.type == ButtonPress4); | |||||
340 | break; | |||||
341 | ||||||
342 | case KeyPress2: | |||||
343 | case KeyRelease3: | |||||
344 | if (!pPriv->dev) { | |||||
345 | xf86DrvMsg(pPriv->scrnIndex, X_INFO, "Input device is not yet initialized, ignoring input.\n"); | |||||
346 | break; | |||||
347 | } | |||||
348 | ||||||
349 | NestedInputPostKeyboardEvent(pPriv->dev, ev.xkey.keycode, ev.type == KeyPress2); | |||||
350 | break; | |||||
351 | } | |||||
352 | } | |||||
353 | } | |||||
354 | ||||||
355 | void | |||||
356 | NestedClientCloseScreen(NestedClientPrivatePtr pPriv) { | |||||
357 | if (pPriv->usingShm) { | |||||
358 | XShmDetach(pPriv->display, &pPriv->shminfo); | |||||
359 | shmdt(pPriv->shminfo.shmaddr); | |||||
360 | } | |||||
361 | ||||||
362 | XDestroyImage(pPriv->img)((*((pPriv->img)->f.destroy_image))((pPriv->img))); | |||||
363 | XCloseDisplay(pPriv->display); | |||||
364 | } | |||||
365 | ||||||
366 | void | |||||
367 | NestedClientSetDevicePtr(NestedClientPrivatePtr pPriv, DeviceIntPtr dev) { | |||||
368 | pPriv->dev = dev; | |||||
369 | } | |||||
370 | ||||||
371 | int | |||||
372 | NestedClientGetFileDescriptor(NestedClientPrivatePtr pPriv) { | |||||
373 | return ConnectionNumber(pPriv->display)(((_XPrivDisplay)(pPriv->display))->fd); | |||||
374 | } | |||||
375 | ||||||
376 | Boolint NestedClientGetKeyboardMappings(NestedClientPrivatePtr pPriv, KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr ctrls) { | |||||
377 | XModifierKeymap *modifier_keymap; | |||||
378 | KeySym *keymap; | |||||
379 | int mapWidth; | |||||
380 | int min_keycode, max_keycode; | |||||
381 | int i, j; | |||||
382 | XkbDescPtr xkb; | |||||
383 | ||||||
384 | XDisplayKeycodes(pPriv->display, &min_keycode, &max_keycode); | |||||
385 | keymap = XGetKeyboardMapping(pPriv->display, | |||||
386 | min_keycode, | |||||
387 | max_keycode - min_keycode + 1, | |||||
388 | &mapWidth); | |||||
389 | ||||||
390 | memset(modmap, 0, sizeof(CARD8) * MAP_LENGTH)__builtin___memset_chk (modmap, 0, sizeof(CARD8) * 256, __builtin_object_size (modmap, 0)); | |||||
391 | modifier_keymap = XGetModifierMapping(pPriv->display); | |||||
392 | for (j = 0; j < 8; j++) | |||||
393 | for(i = 0; i < modifier_keymap->max_keypermod; i++) { | |||||
394 | CARD8 keycode; | |||||
395 | if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i])) | |||||
396 | modmap[keycode] |= 1<<j; | |||||
397 | } | |||||
398 | XFreeModifiermap(modifier_keymap); | |||||
399 | ||||||
400 | keySyms->minKeyCode = min_keycode; | |||||
401 | keySyms->maxKeyCode = max_keycode; | |||||
402 | keySyms->mapWidth = mapWidth; | |||||
403 | keySyms->map = keymap; | |||||
404 | ||||||
405 | xkb = XkbGetKeyboard(pPriv->display, XkbGBN_AllComponentsMask(0xff), XkbUseCoreKbd0x0100); | |||||
406 | if (xkb == NULL((void*)0) || xkb->geom == NULL((void*)0)) { | |||||
407 | xf86DrvMsg(pPriv->scrnIndex, X_ERROR, "Couldn't get XKB keyboard.\n"); | |||||
408 | free(keymap); | |||||
409 | return FALSE0; | |||||
410 | } | |||||
411 | ||||||
412 | if(XkbGetControls(pPriv->display, XkbAllControlsMask(0xF8001FFF), xkb) != Success0) { | |||||
413 | xf86DrvMsg(pPriv->scrnIndex, X_ERROR, "Couldn't get XKB keyboard controls.\n"); | |||||
414 | free(keymap); | |||||
415 | return FALSE0; | |||||
416 | } | |||||
417 | ||||||
418 | memcpy(ctrls, xkb->ctrls, sizeof(XkbControlsRec))__builtin___memcpy_chk (ctrls, xkb->ctrls, sizeof(XkbControlsRec ), __builtin_object_size (ctrls, 0)); | |||||
419 | XkbFreeKeyboard(xkb, 0, False0); | |||||
420 | return TRUE1; | |||||
421 | } |