| /* |
| Copyright (C) 2002-2010 Karl J. Runge <[email protected]> |
| All rights reserved. |
| |
| This file is part of x11vnc. |
| |
| x11vnc is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or (at |
| your option) any later version. |
| |
| x11vnc is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with x11vnc; if not, write to the Free Software |
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA |
| or see <http://www.gnu.org/licenses/>. |
| |
| In addition, as a special exception, Karl J. Runge |
| gives permission to link the code of its release of x11vnc with the |
| OpenSSL project's "OpenSSL" library (or with modified versions of it |
| that use the same license as the "OpenSSL" library), and distribute |
| the linked executables. You must obey the GNU General Public License |
| in all respects for all of the code used other than "OpenSSL". If you |
| modify this file, you may extend this exception to your version of the |
| file, but you are not obligated to do so. If you do not wish to do |
| so, delete this exception statement from your version. |
| */ |
| |
| /* -- xwrappers.c -- */ |
| |
| #include "x11vnc.h" |
| #include "xrecord.h" |
| #include "keyboard.h" |
| #include "xevents.h" |
| #include "connections.h" |
| #include "cleanup.h" |
| #include "macosx.h" |
| |
| int xshm_present = 0; |
| int xshm_opcode = 0; |
| int xtest_present = 0; |
| int xtrap_present = 0; |
| int xrecord_present = 0; |
| int xkb_present = 0; |
| int xinerama_present = 0; |
| |
| int keycode_state[256]; |
| int rootshift = 0; |
| int clipshift = 0; |
| |
| |
| int guess_bits_per_color(int bits_per_pixel); |
| |
| int XFlush_wr(Display *disp); |
| |
| Status XShmGetImage_wr(Display *disp, Drawable d, XImage *image, int x, int y, |
| unsigned long mask); |
| XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth, |
| int format, char* data, XShmSegmentInfo* shminfo, unsigned int width, |
| unsigned int height); |
| Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo); |
| Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo); |
| Bool XShmQueryExtension_wr(Display *disp); |
| int XShmGetEventBase_wr(Display *disp); |
| |
| XImage *xreadscreen(Display *disp, Drawable d, int x, int y, |
| unsigned int width, unsigned int height, Bool show_cursor); |
| XImage *XGetSubImage_wr(Display *disp, Drawable d, int x, int y, |
| unsigned int width, unsigned int height, unsigned long plane_mask, |
| int format, XImage *dest_image, int dest_x, int dest_y); |
| XImage *XGetImage_wr(Display *disp, Drawable d, int x, int y, |
| unsigned int width, unsigned int height, unsigned long plane_mask, |
| int format); |
| XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth, |
| int format, int offset, char *data, unsigned int width, |
| unsigned int height, int bitmap_pad, int bytes_per_line); |
| void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h); |
| void init_track_keycode_state(void); |
| |
| void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, |
| unsigned long delay); |
| void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, |
| unsigned long delay); |
| void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, |
| unsigned long delay); |
| void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, |
| unsigned long delay); |
| void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y, |
| unsigned long delay); |
| void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y, |
| unsigned long delay); |
| |
| Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w); |
| Bool XTestCompareCursorWithWindow_wr(Display* dpy, Window w, Cursor cursor); |
| Bool XTestQueryExtension_wr(Display *dpy, int *ev, int *er, int *maj, |
| int *min); |
| void XTestDiscard_wr(Display *dpy); |
| Bool XETrapQueryExtension_wr(Display *dpy, int *ev, int *er, int *op); |
| int XTestGrabControl_wr(Display *dpy, Bool impervious); |
| int XTRAP_GrabControl_wr(Display *dpy, Bool impervious); |
| void disable_grabserver(Display *in_dpy, int change); |
| |
| Bool XRecordQueryVersion_wr(Display *dpy, int *maj, int *min); |
| |
| int xauth_raw(int on); |
| Display *XOpenDisplay_wr(char *display_name); |
| int XCloseDisplay_wr(Display *display); |
| |
| Bool XQueryPointer_wr(Display *display, Window w, Window *root_return, |
| Window *child_return, int *root_x_return, int *root_y_return, |
| int *win_x_return, int *win_y_return, unsigned int *mask_return); |
| |
| Status XQueryTree_wr(Display *display, Window w, Window *root_return, |
| Window *parent_return, Window **children_return, |
| unsigned int *nchildren_return); |
| |
| int XFree_wr(void *data); |
| int XSelectInput_wr(Display *display, Window w, long event_mask); |
| |
| void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h); |
| static void upup_downdown_warning(KeyCode key, Bool down); |
| |
| /* |
| * used in rfbGetScreen and rfbNewFramebuffer: and estimate to the number |
| * of bits per color, of course for some visuals, e.g. 565, the number |
| * is not the same for each color. This is just a sane default. |
| */ |
| int guess_bits_per_color(int bits_per_pixel) { |
| int bits_per_color; |
| |
| /* first guess, spread them "evenly" over R, G, and B */ |
| bits_per_color = bits_per_pixel/3; |
| if (bits_per_color < 1) { |
| bits_per_color = 1; /* 1bpp, 2bpp... */ |
| } |
| |
| /* choose safe values for usual cases: */ |
| if (bits_per_pixel == 8) { |
| bits_per_color = 2; |
| } else if (bits_per_pixel == 15 || bits_per_pixel == 16) { |
| bits_per_color = 5; |
| } else if (bits_per_pixel == 24 || bits_per_pixel == 32) { |
| bits_per_color = 8; |
| } |
| return bits_per_color; |
| } |
| |
| int XFlush_wr(Display *disp) { |
| #if NO_X11 |
| if (!disp) {} |
| return 1; |
| #else |
| if (disp) { |
| return XFlush(disp); |
| } else { |
| return 1; |
| } |
| #endif /* NO_X11 */ |
| } |
| |
| /* |
| * Kludge to interpose image gets and limit to a subset rectangle of |
| * the rootwin. This is the -sid option trying to work around invisible |
| * saveUnders menu, etc, windows. Also -clip option. |
| */ |
| |
| #define ADJUST_ROOTSHIFT \ |
| if (rootshift && subwin) { \ |
| d = rootwin; \ |
| x += off_x; \ |
| y += off_y; \ |
| } \ |
| if (clipshift) { \ |
| x += coff_x; \ |
| y += coff_y; \ |
| } |
| |
| /* |
| * Wrappers for Image related X calls |
| */ |
| Status XShmGetImage_wr(Display *disp, Drawable d, XImage *image, int x, int y, |
| unsigned long mask) { |
| |
| ADJUST_ROOTSHIFT |
| |
| /* Note: the Solaris overlay stuff is all non-shm (using_shm = 0) */ |
| |
| #if LIBVNCSERVER_HAVE_XSHM |
| return XShmGetImage(disp, d, image, x, y, mask); |
| #else |
| if (!disp || !d || !image || !x || !y || !mask) {} |
| return (Status) 0; |
| #endif |
| } |
| |
| XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth, |
| int format, char* data, XShmSegmentInfo* shminfo, unsigned int width, |
| unsigned int height) { |
| |
| #if LIBVNCSERVER_HAVE_XSHM |
| return XShmCreateImage(disp, vis, depth, format, data, shminfo, |
| width, height); |
| #else |
| if (!disp || !vis || !depth || !format || !data || !shminfo || !width || !height) {} |
| return (XImage *) 0; |
| #endif |
| } |
| |
| Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo) { |
| #if LIBVNCSERVER_HAVE_XSHM |
| return XShmAttach(disp, shminfo); |
| #else |
| if (!disp || !shminfo) {} |
| return (Status) 0; |
| #endif |
| } |
| |
| Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo) { |
| #if LIBVNCSERVER_HAVE_XSHM |
| if (getenv("X11VNC_SHM_DEBUG")) fprintf(stderr, "XShmDetach_wr: %p disp: %p\n", (void *)shminfo, (void *)disp); |
| return XShmDetach(disp, shminfo); |
| #else |
| if (!disp || !shminfo) {} |
| return (Status) 0; |
| #endif |
| } |
| |
| Bool XShmQueryExtension_wr(Display *disp) { |
| #if LIBVNCSERVER_HAVE_XSHM |
| return XShmQueryExtension(disp); |
| #else |
| if (!disp) {} |
| return False; |
| #endif |
| } |
| |
| int XShmGetEventBase_wr(Display *disp) { |
| #if LIBVNCSERVER_HAVE_XSHM |
| return XShmGetEventBase(disp); |
| #else |
| if (!disp) {} |
| return 0; |
| #endif |
| } |
| |
| /* wrapper for overlay screen reading: */ |
| |
| XImage *xreadscreen(Display *disp, Drawable d, int x, int y, |
| unsigned int width, unsigned int height, Bool show_cursor) { |
| #if NO_X11 |
| if (!disp || !d || !x || !y || !width || !height || !show_cursor) {} |
| return NULL; |
| #else |
| |
| #ifdef SOLARIS_OVERLAY |
| return XReadScreen(disp, d, x, y, width, height, |
| show_cursor); |
| #else |
| # ifdef IRIX_OVERLAY |
| { unsigned long hints = 0, hints_ret; |
| if (show_cursor) hints |= XRD_READ_POINTER; |
| return XReadDisplay(disp, d, x, y, width, height, |
| hints, &hints_ret); |
| } |
| # else |
| /* unused vars warning: */ |
| if (disp || d || x || y || width || height || show_cursor) {} |
| |
| return NULL; |
| # endif |
| #endif |
| |
| #endif /* NO_X11 */ |
| } |
| |
| XImage *XGetSubImage_wr(Display *disp, Drawable d, int x, int y, |
| unsigned int width, unsigned int height, unsigned long plane_mask, |
| int format, XImage *dest_image, int dest_x, int dest_y) { |
| #if NO_X11 |
| nox11_exit(1); |
| if (!disp || !d || !x || !y || !width || !height || !plane_mask || !format || !dest_image || !dest_x || !dest_y) {} |
| return NULL; |
| #else |
| ADJUST_ROOTSHIFT |
| |
| if (overlay && dest_x == 0 && dest_y == 0) { |
| size_t size = dest_image->height * dest_image->bytes_per_line; |
| XImage *xi; |
| |
| xi = xreadscreen(disp, d, x, y, width, height, |
| (Bool) overlay_cursor); |
| |
| if (! xi) return NULL; |
| |
| /* |
| * There is extra overhead from memcpy and free... |
| * this is not like the real XGetSubImage(). We hope |
| * this significant overhead is still small compared to |
| * the time to retrieve the fb data. |
| */ |
| memcpy(dest_image->data, xi->data, size); |
| |
| XDestroyImage(xi); |
| return (dest_image); |
| } |
| return XGetSubImage(disp, d, x, y, width, height, plane_mask, |
| format, dest_image, dest_x, dest_y); |
| #endif /* NO_X11 */ |
| } |
| |
| XImage *XGetImage_wr(Display *disp, Drawable d, int x, int y, |
| unsigned int width, unsigned int height, unsigned long plane_mask, |
| int format) { |
| #if NO_X11 |
| if (!disp || !d || !x || !y || !width || !height || !plane_mask || !format) {} |
| nox11_exit(1); |
| return NULL; |
| #else |
| |
| ADJUST_ROOTSHIFT |
| |
| if (overlay) { |
| return xreadscreen(disp, d, x, y, width, height, |
| (Bool) overlay_cursor); |
| } |
| return XGetImage(disp, d, x, y, width, height, plane_mask, format); |
| #endif /* NO_X11 */ |
| } |
| |
| XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth, |
| int format, int offset, char *data, unsigned int width, |
| unsigned int height, int bitmap_pad, int bytes_per_line) { |
| /* |
| * This is a kludge to get a created XImage to exactly match what |
| * XReadScreen returns: we noticed the rgb masks are different |
| * from XCreateImage with the high color visual (red mask <-> |
| * blue mask). Note we read from the root window(!) then free |
| * the data. |
| */ |
| |
| if (raw_fb) { /* raw_fb hack */ |
| XImage *xi; |
| xi = (XImage *) malloc(sizeof(XImage)); |
| memset(xi, 0, sizeof(XImage)); |
| xi->depth = depth; |
| if (depth >= 24) { |
| xi->bits_per_pixel = 32; |
| } else if (depth > 16) { |
| xi->bits_per_pixel = 24; |
| } else if (depth > 8) { |
| xi->bits_per_pixel = 16; |
| } else { |
| xi->bits_per_pixel = 8; |
| } |
| xi->format = format; |
| xi->xoffset = offset; |
| xi->data = data; |
| xi->width = width; |
| xi->height = height; |
| xi->bitmap_pad = bitmap_pad; |
| xi->bytes_per_line = bytes_per_line ? bytes_per_line : |
| xi->width * xi->bits_per_pixel / 8; |
| xi->bitmap_unit = -1; /* hint to not call XDestroyImage */ |
| return xi; |
| } |
| |
| #if NO_X11 |
| nox11_exit(1); |
| if (!disp || !visual || !depth || !format || !offset || !data || !width |
| || !height || !width || !bitmap_pad || !bytes_per_line) {} |
| return NULL; |
| #else |
| if (overlay) { |
| XImage *xi; |
| xi = xreadscreen(disp, window, 0, 0, width, height, False); |
| if (xi == NULL) { |
| return xi; |
| } |
| if (xi->data != NULL) { |
| free(xi->data); |
| } |
| xi->data = data; |
| return xi; |
| } |
| |
| return XCreateImage(disp, visual, depth, format, offset, data, |
| width, height, bitmap_pad, bytes_per_line); |
| #endif /* NO_X11 */ |
| } |
| |
| static void copy_raw_fb_low_bpp(XImage *dest, int x, int y, unsigned int w, |
| unsigned int h) { |
| char *src, *dst; |
| unsigned int line; |
| static char *buf = NULL; |
| static int buflen = -1; |
| int bpl = wdpy_x * raw_fb_native_bpp / 8; |
| int n, ix, len, del, sz = wdpy_x * raw_fb_expand_bytes; |
| |
| unsigned int rm_n = raw_fb_native_red_mask; |
| unsigned int gm_n = raw_fb_native_green_mask; |
| unsigned int bm_n = raw_fb_native_blue_mask; |
| unsigned int rm_f = main_red_mask; |
| unsigned int gm_f = main_green_mask; |
| unsigned int bm_f = main_blue_mask; |
| |
| unsigned int rs_n = raw_fb_native_red_shift; |
| unsigned int gs_n = raw_fb_native_green_shift; |
| unsigned int bs_n = raw_fb_native_blue_shift; |
| unsigned int rs_f = main_red_shift; |
| unsigned int gs_f = main_green_shift; |
| unsigned int bs_f = main_blue_shift; |
| |
| unsigned int rx_n = raw_fb_native_red_max; |
| unsigned int gx_n = raw_fb_native_green_max; |
| unsigned int bx_n = raw_fb_native_blue_max; |
| unsigned int rx_f = main_red_max; |
| unsigned int gx_f = main_green_max; |
| unsigned int bx_f = main_blue_max; |
| |
| static unsigned int msk[8]; |
| static int last_bpp = -1; |
| static int cga = -1; |
| |
| if (rm_f | gm_f | bm_f) {} |
| |
| if (cga < 0) { |
| if (getenv("RAWFB_CGA")) { |
| cga = 1; |
| } else { |
| cga = 0; |
| } |
| } |
| |
| if (sz > buflen || buf == NULL) { |
| if (buf) { |
| free(buf); |
| } |
| buflen = sz + 1000; |
| buf = (char *) malloc(buflen); |
| } |
| |
| if (clipshift && ! use_snapfb) { |
| x += coff_x; |
| y += coff_y; |
| } |
| |
| if (last_bpp != raw_fb_native_bpp) { |
| int br; |
| for (br = 0; br < 8; br++) { |
| unsigned int pbit, k, m = 0; |
| |
| for (k=0; k < (unsigned int) raw_fb_native_bpp; k++) { |
| pbit = 1 << (br+k); |
| m |= pbit; |
| } |
| msk[br] = m; |
| } |
| last_bpp = raw_fb_native_bpp; |
| } |
| |
| dst = dest->data; |
| if (0) fprintf(stderr, "x=%d y=%d w=%d h=%d bpl=%d d_bpl=%d-%dx%dx%d/%d %p\n", |
| x, y, w, h, bpl, dest->bytes_per_line, dest->width, dest->height, dest->bits_per_pixel, dest->depth, dst); |
| |
| for (line = 0; line < h; line++) { |
| |
| if (! raw_fb_seek) { |
| /* mmap */ |
| src = raw_fb_addr + raw_fb_offset + bpl*(y+line); |
| |
| memcpy(buf, src, bpl); |
| } else { |
| /* lseek */ |
| off_t off; |
| off = (off_t) (raw_fb_offset + bpl*(y+line)); |
| |
| lseek(raw_fb_fd, off, SEEK_SET); |
| |
| len = bpl; |
| del = 0; |
| while (len > 0) { |
| n = read(raw_fb_fd, buf + del, len); |
| |
| if (n > 0) { |
| del += n; |
| len -= n; |
| } else if (n == 0) { |
| break; |
| } else if (errno != EINTR && errno != EAGAIN) { |
| break; |
| } |
| } |
| } |
| for (ix = 0; ix < (int) w; ix++) { |
| int bx = (x + ix) * raw_fb_native_bpp; |
| int ib = bx / 8; |
| int br = bx - ib * 8; |
| unsigned char val; |
| |
| val = *((unsigned char*) (buf + ib)); |
| |
| val = msk[br] & val; |
| val = val >> br; |
| |
| if (cga) { |
| /* this is expt for CGA */ |
| double r, g, b; |
| int ir, ig, ib; |
| r = (2./3)*(val & 4) + (1./3)*(val & 8); |
| g = (2./3)*(val & 2) + (1./3)*(val & 8); |
| b = (2./3)*(val & 1) + (1./3)*(val & 8); |
| if (val == 6) { |
| g = g/2.; |
| } |
| ir = rx_f * r; |
| ig = gx_f * g; |
| ib = bx_f * b; |
| val = (ib << bs_f) | (ig << gs_f) | (ir << rs_f); |
| } else { |
| unsigned char rval, gval, bval; |
| |
| rval = (val & rm_n) >> rs_n; |
| gval = (val & gm_n) >> gs_n; |
| bval = (val & bm_n) >> bs_n; |
| |
| rval = (rx_f * rval) / rx_n; |
| gval = (gx_f * gval) / gx_n; |
| bval = (bx_f * bval) / bx_n; |
| |
| rval = rval << rs_f; |
| gval = gval << gs_f; |
| bval = bval << bs_f; |
| |
| val = rval | gval | bval; |
| } |
| |
| *(dst+ix) = (char) val; |
| } |
| |
| dst += dest->bytes_per_line; |
| } |
| } |
| |
| static void copy_raw_fb_24_to_32(XImage *dest, int x, int y, unsigned int w, |
| unsigned int h) { |
| /* |
| * kludge to read 1 byte at a time and dynamically transform |
| * 24bpp -> 32bpp by inserting a extra 0 byte into dst. |
| */ |
| char *src, *dst; |
| unsigned int line; |
| static char *buf = NULL; |
| static int buflen = -1; |
| int bpl = wdpy_x * 3; /* pixelsize == 3 */ |
| int LE, n, stp, len, del, sz = w * 3; |
| int insert_zeroes = 1; |
| |
| #define INSERT_ZEROES \ |
| len = sz; \ |
| del = 0; \ |
| stp = 0; \ |
| while (len > 0) { \ |
| if (insert_zeroes && (del - LE) % 4 == 0) { \ |
| *(dst + del) = 0; \ |
| del++; \ |
| } \ |
| *(dst + del) = *(buf + stp); \ |
| del++; \ |
| len--; \ |
| stp++; \ |
| } |
| |
| if (rfbEndianTest) { |
| LE = 3; /* little endian */ |
| } else { |
| LE = 0; /* big endian */ |
| } |
| |
| if (sz > buflen || buf == NULL) { |
| if (buf) { |
| free(buf); |
| } |
| buf = (char *) malloc(4*(sz + 1000)); |
| } |
| |
| if (clipshift && ! use_snapfb) { |
| x += coff_x; |
| y += coff_y; |
| } |
| |
| if (use_snapfb && dest != snap) { |
| /* snapfb src */ |
| src = snap->data + snap->bytes_per_line*y + 3*x; |
| dst = dest->data; |
| for (line = 0; line < h; line++) { |
| memcpy(buf, src, sz); |
| |
| INSERT_ZEROES |
| |
| src += snap->bytes_per_line; |
| dst += dest->bytes_per_line; |
| } |
| |
| } else if (! raw_fb_seek) { |
| /* mmap */ |
| bpl = raw_fb_bytes_per_line; |
| if (clipshift && wdpy_x != cdpy_x) { |
| bpl = wdpy_x * 3; |
| } |
| src = raw_fb_addr + raw_fb_offset + bpl*y + 3*x; |
| dst = dest->data; |
| |
| if (use_snapfb && dest == snap) { |
| /* |
| * writing *to* snap_fb: need the x,y offset, |
| * and also do not do inserts. |
| */ |
| dst += bpl*y + 3*x; |
| insert_zeroes = 0; |
| } |
| |
| for (line = 0; line < h; line++) { |
| memcpy(buf, src, sz); |
| |
| INSERT_ZEROES |
| |
| src += bpl; |
| dst += dest->bytes_per_line; |
| } |
| |
| } else { |
| /* lseek */ |
| off_t off; |
| bpl = raw_fb_bytes_per_line; |
| if (clipshift && wdpy_x != cdpy_x) { |
| bpl = wdpy_x * 3; |
| } |
| off = (off_t) (raw_fb_offset + bpl*y + 3*x); |
| |
| lseek(raw_fb_fd, off, SEEK_SET); |
| dst = dest->data; |
| |
| if (use_snapfb && dest == snap) { |
| /* |
| * writing *to* snap_fb: need the x,y offset, |
| * and also do not do inserts. |
| */ |
| dst += bpl*y + 3*x; |
| insert_zeroes = 0; |
| } |
| |
| for (line = 0; line < h; line++) { |
| len = sz; |
| del = 0; |
| while (len > 0) { |
| n = read(raw_fb_fd, buf + del, len); |
| |
| if (n > 0) { |
| del += n; |
| len -= n; |
| } else if (n == 0) { |
| break; |
| } else if (errno != EINTR && errno != EAGAIN) { |
| break; |
| } |
| } |
| |
| INSERT_ZEROES |
| |
| if (bpl > sz) { |
| off = (off_t) (bpl - sz); |
| lseek(raw_fb_fd, off, SEEK_CUR); |
| } |
| dst += dest->bytes_per_line; |
| } |
| } |
| } |
| |
| #ifdef MACOSX |
| void macosx_copy_opengl(char *, int, int, unsigned int, unsigned int); |
| #endif |
| |
| void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h) { |
| char *src, *dst; |
| unsigned int line; |
| int pixelsize = bpp/8; |
| static int db = -1; |
| |
| #ifdef MACOSX |
| if (macosx_console && macosx_read_opengl) { |
| macosx_copy_opengl(dest->data, x, y, w, h); |
| return; |
| } |
| #endif |
| |
| if (xform24to32) { |
| copy_raw_fb_24_to_32(dest, x, y, w, h); |
| return; |
| } |
| if (raw_fb_native_bpp < 8) { |
| copy_raw_fb_low_bpp(dest, x, y, w, h); |
| return; |
| } |
| if (db < 0) { |
| if (getenv("DEBUG_COPY_RAW_FB")) { |
| db = atoi(getenv("DEBUG_COPY_RAW_FB")); |
| } else { |
| db = 0; |
| } |
| } |
| |
| if (clipshift && ! use_snapfb) { |
| x += coff_x; |
| y += coff_y; |
| } |
| |
| |
| if (use_snapfb && dest != snap) { |
| /* snapfb src */ |
| src = snap->data + snap->bytes_per_line*y + pixelsize*x; |
| dst = dest->data; |
| |
| if (db) fprintf(stderr, "snap->bytes_per_line: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d bpp: %d pixelsize: %d\n", snap->bytes_per_line, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x, bpp, pixelsize); |
| |
| for (line = 0; line < h; line++) { |
| memcpy(dst, src, w * pixelsize); |
| src += snap->bytes_per_line; |
| dst += dest->bytes_per_line; |
| } |
| |
| } else if (! raw_fb_seek) { |
| /* mmap */ |
| int bpl = raw_fb_bytes_per_line; |
| |
| if (clipshift && wdpy_x != cdpy_x) { |
| bpl = wdpy_x * pixelsize; |
| } |
| |
| src = raw_fb_addr + raw_fb_offset + bpl*y + pixelsize*x; |
| dst = dest->data; |
| |
| if (db) fprintf(stderr, "bpl: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d bpp: %d pixelsize: %d\n", bpl, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x, bpp, pixelsize); |
| |
| for (line = 0; line < h; line++) { |
| memcpy(dst, src, w * pixelsize); |
| src += bpl; |
| dst += dest->bytes_per_line; |
| } |
| |
| } else { |
| /* lseek */ |
| int n, len, del, sz = w * pixelsize; |
| off_t off; |
| int bpl = raw_fb_bytes_per_line; |
| |
| if (clipshift && wdpy_x != cdpy_x) { |
| bpl = wdpy_x * pixelsize; |
| } |
| |
| off = (off_t) (raw_fb_offset + bpl*y + pixelsize*x); |
| |
| lseek(raw_fb_fd, off, SEEK_SET); |
| dst = dest->data; |
| |
| if (db) fprintf(stderr, "lseek 0 ps: %d sz: %d off: %d bpl: %d\n", pixelsize, sz, (int) off, bpl); |
| |
| for (line = 0; line < h; line++) { |
| len = sz; |
| del = 0; |
| while (len > 0) { |
| n = read(raw_fb_fd, dst + del, len); |
| |
| if (n > 0) { |
| del += n; |
| len -= n; |
| } else if (n == 0) { |
| break; |
| } else if (errno != EINTR && errno != EAGAIN) { |
| break; |
| } |
| } |
| if (bpl > sz) { |
| off = (off_t) (bpl - sz); |
| lseek(raw_fb_fd, off, SEEK_CUR); |
| } |
| dst += dest->bytes_per_line; |
| } |
| } |
| } |
| |
| void copy_image(XImage *dest, int x, int y, unsigned int w, unsigned int h) { |
| /* default (w=0, h=0) is the fill the entire XImage */ |
| if (dest == NULL) { |
| return; |
| } |
| if (w < 1) { |
| w = dest->width; |
| } |
| if (h < 1) { |
| h = dest->height; |
| } |
| |
| if (raw_fb) { |
| copy_raw_fb(dest, x, y, w, h); |
| |
| } else if (use_snapfb && snap_fb && dest != snaprect) { |
| char *src, *dst; |
| unsigned int line; |
| int pixelsize = bpp/8; |
| |
| src = snap->data + snap->bytes_per_line*y + pixelsize*x; |
| dst = dest->data; |
| for (line = 0; line < h; line++) { |
| memcpy(dst, src, w * pixelsize); |
| src += snap->bytes_per_line; |
| dst += dest->bytes_per_line; |
| } |
| |
| } else if ((using_shm && ! xform24to32) && (int) w == dest->width && |
| (int) h == dest->height) { |
| XShmGetImage_wr(dpy, window, dest, x, y, AllPlanes); |
| |
| } else { |
| XGetSubImage_wr(dpy, window, x, y, w, h, AllPlanes, |
| ZPixmap, dest, 0, 0); |
| } |
| } |
| |
| #define DEBUG_SKIPPED_INPUT(dbg, str) \ |
| if (dbg) { \ |
| rfbLog("skipped input: %s\n", str); \ |
| } |
| |
| void init_track_keycode_state(void) { |
| int i; |
| for (i=0; i<256; i++) { |
| keycode_state[i] = 0; |
| } |
| get_keystate(keycode_state); |
| } |
| |
| static void upup_downdown_warning(KeyCode key, Bool down) { |
| RAWFB_RET_VOID |
| #if NO_X11 |
| if (!key || !down) {} |
| return; |
| #else |
| if ((down ? 1:0) == keycode_state[(int) key]) { |
| char *str = XKeysymToString(XKeycodeToKeysym(dpy, key, 0)); |
| rfbLog("XTestFakeKeyEvent: keycode=0x%x \"%s\" is *already* " |
| "%s\n", key, str ? str : "null", down ? "down":"up"); |
| } |
| #endif /* NO_X11 */ |
| } |
| |
| /* |
| * wrappers for XTestFakeKeyEvent, etc.. |
| * also for XTrap equivalents XESimulateXEventRequest |
| */ |
| |
| void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, |
| unsigned long delay) { |
| |
| RAWFB_RET_VOID |
| #if NO_X11 |
| nox11_exit(1); |
| if (!dpy || !key || !down || !delay) {} |
| return; |
| #else |
| |
| if (! xtrap_present) { |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "keyboard: no-XTRAP"); |
| return; |
| } |
| /* unused vars warning: */ |
| if (key || down || delay) {} |
| |
| # if LIBVNCSERVER_HAVE_LIBXTRAP |
| XESimulateXEventRequest(trap_ctx, down ? KeyPress : KeyRelease, |
| key, 0, 0, 0); |
| if (debug_keyboard) { |
| upup_downdown_warning(key, down); |
| } |
| keycode_state[(int) key] = down ? 1 : 0; |
| # else |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "keyboard: no-XTRAP-build"); |
| # endif |
| |
| #endif /* NO_X11 */ |
| } |
| |
| void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, |
| unsigned long delay) { |
| static int first = 1; |
| int regrab = 0; |
| |
| RAWFB_RET_VOID |
| |
| #if NO_X11 |
| nox11_exit(1); |
| if (!dpy || !key || !down || !delay || !first) {} |
| return; |
| #else |
| if (debug_keyboard) { |
| char *str = XKeysymToString(XKeycodeToKeysym(dpy, key, 0)); |
| rfbLog("XTestFakeKeyEvent(dpy, keycode=0x%x \"%s\", %s)\n", |
| key, str ? str : "null", down ? "down":"up"); |
| } |
| if (first) { |
| init_track_keycode_state(); |
| first = 0; |
| } |
| if (down) { |
| last_keyboard_keycode = -key; |
| } else { |
| last_keyboard_keycode = key; |
| } |
| |
| if (grab_kbd) { |
| XUngrabKeyboard(dpy, CurrentTime); |
| regrab = 1; |
| } |
| if (grab_ptr && ungrab_both) { |
| XUngrabPointer(dpy, CurrentTime); |
| regrab = 1; |
| } |
| |
| if (xtrap_input) { |
| XTRAP_FakeKeyEvent_wr(dpy, key, down, delay); |
| if (regrab) { |
| adjust_grabs(1, 1); |
| } |
| return; |
| } |
| |
| if (! xtest_present) { |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "keyboard: no-XTEST"); |
| return; |
| } |
| if (debug_keyboard) { |
| rfbLog("calling XTestFakeKeyEvent(%d, %d) %.4f\n", |
| key, down, dnowx()); |
| } |
| #if LIBVNCSERVER_HAVE_XTEST |
| XTestFakeKeyEvent(dpy, key, down, delay); |
| if (regrab) { |
| adjust_grabs(1, 1); |
| } |
| if (debug_keyboard) { |
| upup_downdown_warning(key, down); |
| } |
| keycode_state[(int) key] = down ? 1 : 0; |
| #endif |
| |
| #endif /* NO_X11 */ |
| } |
| |
| void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, |
| unsigned long delay) { |
| |
| RAWFB_RET_VOID |
| #if NO_X11 |
| nox11_exit(1); |
| if (!dpy || !button || !is_press || !delay) {} |
| return; |
| #else |
| |
| if (! xtrap_present) { |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "button: no-XTRAP"); |
| return; |
| } |
| /* unused vars warning: */ |
| if (button || is_press || delay) {} |
| |
| #if LIBVNCSERVER_HAVE_LIBXTRAP |
| XESimulateXEventRequest(trap_ctx, |
| is_press ? ButtonPress : ButtonRelease, button, 0, 0, 0); |
| #else |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "button: no-XTRAP-build"); |
| #endif |
| |
| #endif /* NO_X11 */ |
| } |
| |
| void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, |
| unsigned long delay) { |
| int regrab = 0; |
| |
| RAWFB_RET_VOID |
| #if NO_X11 |
| nox11_exit(1); |
| if (!dpy || !button || !is_press || !delay) {} |
| return; |
| #else |
| |
| if (grab_ptr) { |
| XUngrabPointer(dpy, CurrentTime); |
| regrab = 1; |
| } |
| if (grab_kbd && ungrab_both) { |
| XUngrabKeyboard(dpy, CurrentTime); |
| regrab = 1; |
| } |
| |
| if (xtrap_input) { |
| XTRAP_FakeButtonEvent_wr(dpy, button, is_press, delay); |
| if (regrab) { |
| adjust_grabs(1, 1); |
| } |
| return; |
| } |
| |
| if (! xtest_present) { |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "button: no-XTEST"); |
| return; |
| } |
| if (debug_pointer) { |
| rfbLog("calling XTestFakeButtonEvent(%d, %d) %.4f\n", |
| button, is_press, dnowx()); |
| } |
| #if LIBVNCSERVER_HAVE_XTEST |
| XTestFakeButtonEvent(dpy, button, is_press, delay); |
| #endif |
| if (regrab) { |
| adjust_grabs(1, 1); |
| } |
| #endif /* NO_X11 */ |
| } |
| |
| void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y, |
| unsigned long delay) { |
| |
| RAWFB_RET_VOID |
| |
| #if NO_X11 |
| nox11_exit(1); |
| if (!dpy || !screen || !x || !y || !delay) {} |
| return; |
| #else |
| if (! xtrap_present) { |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "motion: no-XTRAP"); |
| return; |
| } |
| /* unused vars warning: */ |
| if (dpy || screen || x || y || delay) {} |
| |
| #if LIBVNCSERVER_HAVE_LIBXTRAP |
| XESimulateXEventRequest(trap_ctx, MotionNotify, 0, x, y, 0); |
| #else |
| DEBUG_SKIPPED_INPUT(debug_keyboard, "motion: no-XTRAP-build"); |
| #endif |
| |
| #endif /* NO_X11 */ |
| } |
| |
| void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y, |
| unsigned long delay) { |
| int regrab = 0; |
| |
| RAWFB_RET_VOID |
| #if NO_X11 |
| nox11_exit(1); |
| if (!dpy || !screen || !x || !y || !delay) {} |
| return; |
| #else |
| |
| if (grab_ptr) { |
| XUngrabPointer(dpy, CurrentTime); |
| regrab = 1; |
| } |
| if (grab_kbd && ungrab_both) { |
| XUngrabKeyboard(dpy, CurrentTime); |
| regrab = 1; |
| } |
| |
| if (xtrap_input) { |
| XTRAP_FakeMotionEvent_wr(dpy, screen, x, y, delay); |
| if (regrab) { |
| adjust_grabs(1, 1); |
| } |
| return; |
| } |
| |
| if (debug_pointer) { |
| rfbLog("calling XTestFakeMotionEvent(%d, %d) %.4f\n", |
| x, y, dnowx()); |
| } |
| #if LIBVNCSERVER_HAVE_XTEST |
| XTestFakeMotionEvent(dpy, screen, x, y, delay); |
| #endif |
| if (regrab) { |
| adjust_grabs(1, 1); |
| } |
| #endif /* NO_X11 */ |
| } |
| |
| Bool XTestCompareCurrentCursorWithWindow_wr(Display* dpy, Window w) { |
| if (! xtest_present) { |
| return False; |
| } |
| RAWFB_RET(False) |
| |
| #if LIBVNCSERVER_HAVE_XTEST |
| return XTestCompareCurrentCursorWithWindow(dpy, w); |
| #else |
| if (!w) {} |
| return False; |
| #endif |
| } |
| |
| Bool XTestCompareCursorWithWindow_wr(Display* dpy, Window w, Cursor cursor) { |
| if (! xtest_present) { |
| return False; |
| } |
| RAWFB_RET(False) |
| #if LIBVNCSERVER_HAVE_XTEST |
| return XTestCompareCursorWithWindow(dpy, w, cursor); |
| #else |
| if (!dpy || !w || !cursor) {} |
| return False; |
| #endif |
| } |
| |
| Bool XTestQueryExtension_wr(Display *dpy, int *ev, int *er, int *maj, |
| int *min) { |
| RAWFB_RET(False) |
| #if LIBVNCSERVER_HAVE_XTEST |
| return XTestQueryExtension(dpy, ev, er, maj, min); |
| #else |
| if (!dpy || !ev || !er || !maj || !min) {} |
| return False; |
| #endif |
| } |
| |
| void XTestDiscard_wr(Display *dpy) { |
| if (! xtest_present) { |
| return; |
| } |
| RAWFB_RET_VOID |
| #if LIBVNCSERVER_HAVE_XTEST |
| XTestDiscard(dpy); |
| #else |
| if (!dpy) {} |
| #endif |
| } |
| |
| Bool XETrapQueryExtension_wr(Display *dpy, int *ev, int *er, int *op) { |
| RAWFB_RET(False) |
| #if LIBVNCSERVER_HAVE_LIBXTRAP |
| return XETrapQueryExtension(dpy, (INT32 *)ev, (INT32 *)er, |
| (INT32 *)op); |
| #else |
| /* unused vars warning: */ |
| if (ev || er || op) {} |
| return False; |
| #endif |
| } |
| |
| int XTestGrabControl_wr(Display *dpy, Bool impervious) { |
| if (! xtest_present) { |
| return 0; |
| } |
| RAWFB_RET(0) |
| #if LIBVNCSERVER_HAVE_XTEST && LIBVNCSERVER_HAVE_XTESTGRABCONTROL |
| XTestGrabControl(dpy, impervious); |
| return 1; |
| #else |
| if (!dpy || !impervious) {} |
| return 0; |
| #endif |
| } |
| |
| int XTRAP_GrabControl_wr(Display *dpy, Bool impervious) { |
| if (! xtrap_present) { |
| /* unused vars warning: */ |
| if (dpy || impervious) {} |
| return 0; |
| } |
| RAWFB_RET(0) |
| #if LIBVNCSERVER_HAVE_LIBXTRAP |
| else { |
| ReqFlags requests; |
| |
| if (! impervious) { |
| if (trap_ctx) { |
| XEFreeTC(trap_ctx); |
| } |
| trap_ctx = NULL; |
| return 1; |
| } |
| |
| if (! trap_ctx) { |
| trap_ctx = XECreateTC(dpy, 0, NULL); |
| if (! trap_ctx) { |
| rfbLog("DEC-XTRAP XECreateTC failed. Watch " |
| "out for XGrabServer from wm's\n"); |
| return 0; |
| } |
| XEStartTrapRequest(trap_ctx); |
| memset(requests, 0, sizeof(requests)); |
| BitTrue(requests, X_GrabServer); |
| BitTrue(requests, X_UngrabServer); |
| XETrapSetRequests(trap_ctx, True, requests); |
| XETrapSetGrabServer(trap_ctx, True); |
| } |
| return 1; |
| } |
| #endif |
| return 0; |
| } |
| |
| void disable_grabserver(Display *in_dpy, int change) { |
| int ok = 0; |
| static int didmsg = 0; |
| |
| if (debug_grabs) { |
| fprintf(stderr, "disable_grabserver/%d %.5f\n", |
| xserver_grabbed, dnowx()); |
| didmsg = 0; |
| } |
| |
| if (! xtrap_input) { |
| if (XTestGrabControl_wr(in_dpy, True)) { |
| if (change) { |
| XTRAP_GrabControl_wr(in_dpy, False); |
| } |
| if (! didmsg && ! raw_fb_str) { |
| rfbLog("GrabServer control via XTEST.\n"); |
| didmsg = 1; |
| } |
| ok = 1; |
| } else { |
| if (XTRAP_GrabControl_wr(in_dpy, True)) { |
| ok = 1; |
| if (! didmsg && ! raw_fb_str) { |
| rfbLog("Using DEC-XTRAP for protection" |
| " from XGrabServer.\n"); |
| didmsg = 1; |
| } |
| } |
| } |
| } else { |
| if (XTRAP_GrabControl_wr(in_dpy, True)) { |
| if (change) { |
| XTestGrabControl_wr(in_dpy, False); |
| } |
| if (! didmsg && ! raw_fb_str) { |
| rfbLog("GrabServer control via DEC-XTRAP.\n"); |
| didmsg = 1; |
| } |
| ok = 1; |
| } else { |
| if (XTestGrabControl_wr(in_dpy, True)) { |
| ok = 1; |
| if (! didmsg && ! raw_fb_str) { |
| rfbLog("DEC-XTRAP XGrabServer " |
| "protection not available, " |
| "using XTEST.\n"); |
| didmsg = 1; |
| } |
| } |
| } |
| } |
| if (! ok && ! didmsg) { |
| rfbLog("*********************************************************\n"); |
| rfbLog("* No XTEST or DEC-XTRAP protection from XGrabServer !!! *\n"); |
| rfbLog("* DEADLOCK if your window manager calls XGrabServer !!! *\n"); |
| rfbLog("*********************************************************\n"); |
| } |
| XFlush_wr(in_dpy); |
| } |
| |
| Bool XRecordQueryVersion_wr(Display *dpy, int *maj, int *min) { |
| RAWFB_RET(False) |
| #if LIBVNCSERVER_HAVE_RECORD |
| return XRecordQueryVersion(dpy, maj, min); |
| #else |
| if (!dpy || !maj || !min) {} |
| return False; |
| #endif |
| } |
| |
| int xauth_raw(int on) { |
| char tmp[] = "/tmp/x11vnc-xauth.XXXXXX"; |
| int tmp_fd = -1; |
| static char *old_xauthority = NULL; |
| static char *old_tmp = NULL; |
| int db = 0; |
| |
| if (on) { |
| if (old_xauthority) { |
| free(old_xauthority); |
| old_xauthority = NULL; |
| } |
| if (old_tmp) { |
| free(old_tmp); |
| old_tmp = NULL; |
| } |
| if (xauth_raw_data) { |
| tmp_fd = mkstemp(tmp); |
| if (tmp_fd < 0) { |
| rfbLog("could not create tmp xauth file: %s\n", tmp); |
| return 0; |
| } |
| if (db) fprintf(stderr, "XAUTHORITY tmp: %s\n", tmp); |
| write(tmp_fd, xauth_raw_data, xauth_raw_len); |
| close(tmp_fd); |
| if (getenv("XAUTHORITY")) { |
| old_xauthority = strdup(getenv("XAUTHORITY")); |
| } else { |
| old_xauthority = strdup(""); |
| } |
| set_env("XAUTHORITY", tmp); |
| old_tmp = strdup(tmp); |
| } |
| return 1; |
| } else { |
| if (old_xauthority) { |
| if (!strcmp(old_xauthority, "")) { |
| char *xauth = getenv("XAUTHORITY"); |
| if (xauth) { |
| *(xauth-2) = '_'; /* yow */ |
| } |
| } else { |
| set_env("XAUTHORITY", old_xauthority); |
| } |
| free(old_xauthority); |
| old_xauthority = NULL; |
| } |
| if (old_tmp) { |
| unlink(old_tmp); |
| free(old_tmp); |
| old_tmp = NULL; |
| } |
| return 1; |
| } |
| } |
| |
| Display *XOpenDisplay_wr(char *display_name) { |
| Display *d = NULL; |
| int db = 0; |
| |
| if (! xauth_raw(1)) { |
| return NULL; |
| } |
| #if NO_X11 |
| rfbLog("This x11vnc was built without X11 support (-rawfb only).\n"); |
| if (!display_name || !d || !db) {} |
| return NULL; |
| #else |
| |
| d = XOpenDisplay(display_name); |
| if (db) fprintf(stderr, "XOpenDisplay_wr: %s %p\n", display_name, (void *)d); |
| |
| if (d == NULL && !getenv("NO_XAUTHLOCALHOSTNAME")) { |
| char *xalhn = getenv("XAUTHLOCALHOSTNAME"); |
| if (1 || !xalhn) { |
| rfbLog("XOpenDisplay(\"%s\") failed.\n", |
| display_name ? display_name : ""); |
| rfbLog("Trying again with XAUTHLOCALHOSTNAME=localhost ...\n"); |
| set_env("XAUTHLOCALHOSTNAME", "localhost"); |
| d = XOpenDisplay(display_name); |
| if (d == NULL && xalhn) { |
| char *ptr = getenv("XAUTHLOCALHOSTNAME"); |
| if (ptr) { |
| *(ptr-2) = '_'; /* yow */ |
| rfbLog("XOpenDisplay(\"%s\") failed.\n", |
| display_name ? display_name : ""); |
| rfbLog("Trying again with unset XAUTHLOCALHOSTNAME ...\n"); |
| d = XOpenDisplay(display_name); |
| } |
| } |
| } |
| } |
| |
| xauth_raw(0); |
| |
| return d; |
| #endif /* NO_X11 */ |
| } |
| |
| int XCloseDisplay_wr(Display *display) { |
| int db = 0; |
| if (db) fprintf(stderr, "XCloseDisplay_wr: %p\n", (void *)display); |
| #if NO_X11 |
| return 0; |
| #else |
| return XCloseDisplay(display); |
| #endif /* NO_X11 */ |
| } |
| |
| static unsigned int Bmask = (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask); |
| static unsigned int Mmask = (ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask); |
| |
| static unsigned int last_local_button_mask = 0; |
| static unsigned int last_local_mod_mask = 0; |
| static int last_local_x = 0; |
| static int last_local_y = 0; |
| |
| Bool XQueryPointer_wr(Display *display, Window w, Window *root_return, |
| Window *child_return, int *root_x_return, int *root_y_return, |
| int *win_x_return, int *win_y_return, unsigned int *mask_return) { |
| #if NO_X11 |
| if (!display || !w || !root_return || !child_return || !root_x_return |
| || !root_y_return || !win_x_return || !win_y_return || !mask_return) {} |
| return False; |
| #else |
| Bool rc; |
| XErrorHandler old_handler; |
| |
| |
| if (! display) { |
| return False; |
| } |
| old_handler = XSetErrorHandler(trap_xerror); |
| trapped_xerror = 0; |
| |
| rc = XQueryPointer(display, w, root_return, child_return, |
| root_x_return, root_y_return, win_x_return, win_y_return, |
| mask_return); |
| |
| XSetErrorHandler(old_handler); |
| if (trapped_xerror) { |
| rc = 0; |
| } |
| if (rc) { |
| display_button_mask = (*mask_return) & Bmask; |
| display_mod_mask = (*mask_return) & Mmask; |
| if (last_local_button_mask != display_button_mask) { |
| got_local_pointer_input++; |
| } else if (*root_x_return != last_local_x || |
| *root_y_return != last_local_y) { |
| got_local_pointer_input++; |
| } |
| last_local_button_mask = display_button_mask; |
| last_local_mod_mask = display_mod_mask; |
| last_local_x = *root_x_return; |
| last_local_y = *root_y_return; |
| } |
| return rc; |
| #endif /* NO_X11 */ |
| } |
| |
| |
| Status XQueryTree_wr(Display *display, Window w, Window *root_return, |
| Window *parent_return, Window **children_return, |
| unsigned int *nchildren_return) { |
| |
| #ifdef MACOSX |
| if (macosx_console) { |
| return macosx_xquerytree(w, root_return, parent_return, |
| children_return, nchildren_return); |
| } |
| #endif |
| #if NO_X11 |
| if (!display || !w || !root_return || !parent_return |
| || !children_return || !nchildren_return) {} |
| return (Status) 0; |
| #else |
| if (! display) { |
| return (Status) 0; |
| } |
| return XQueryTree(display, w, root_return, parent_return, |
| children_return, nchildren_return); |
| #endif /* NO_X11 */ |
| |
| } |
| |
| int XFree_wr(void *data) { |
| if (data == NULL) { |
| return 1; |
| } |
| if (! dpy) { |
| return 1; |
| } |
| #if NO_X11 |
| return 1; |
| #else |
| return XFree(data); |
| #endif |
| } |
| |
| int XSelectInput_wr(Display *display, Window w, long event_mask) { |
| #if NO_X11 |
| if (!display || !w || !event_mask) {} |
| return 0; |
| #else |
| int rc; |
| XErrorHandler old_handler; |
| if (display == NULL || w == None) { |
| return 0; |
| } |
| old_handler = XSetErrorHandler(trap_xerror); |
| trapped_xerror = 0; |
| rc = XSelectInput(display, w, event_mask); |
| XSetErrorHandler(old_handler); |
| if (trapped_xerror) { |
| rc = 0; |
| } |
| return rc; |
| #endif |
| } |
| |
| void nox11_exit(int rc) { |
| #if NO_X11 |
| rfbLog("This x11vnc was not built with X11 support.\n"); |
| clean_up_exit(rc); |
| #else |
| if (0) {rc = 0;} |
| #endif |
| } |
| |
| |
| #if NO_X11 |
| #include "nox11_funcs.h" |
| #endif |
| |