summaryrefslogtreecommitdiffstats
path: root/x11vnc/xinerama.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/xinerama.c')
-rw-r--r--x11vnc/xinerama.c563
1 files changed, 0 insertions, 563 deletions
diff --git a/x11vnc/xinerama.c b/x11vnc/xinerama.c
deleted file mode 100644
index 0d2ca71..0000000
--- a/x11vnc/xinerama.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
- 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.
-*/
-
-/* -- xinerama.c -- */
-
-#include "x11vnc.h"
-#include "xwrappers.h"
-#include "blackout_t.h"
-#include "scan.h"
-
-/*
- * routines related to xinerama and blacking out rectangles
- */
-
-/* blacked-out region (-blackout, -xinerama) */
-
-#define BLACKR_MAX 100
-blackout_t blackr[BLACKR_MAX]; /* hardwired max blackouts */
-tile_blackout_t *tile_blackout;
-int blackouts = 0;
-
-void initialize_blackouts_and_xinerama(void);
-void push_sleep(int n);
-void push_black_screen(int n);
-void refresh_screen(int push);
-void zero_fb(int x1, int y1, int x2, int y2);
-
-
-static void initialize_blackouts(char *list);
-static void blackout_tiles(void);
-static void initialize_xinerama (void);
-
-
-/*
- * Take a comma separated list of geometries: WxH+X+Y and register them as
- * rectangles to black out from the screen.
- */
-static void initialize_blackouts(char *list) {
- char *p, *blist = strdup(list);
- int x, y, X, Y, h, w, t;
-
- p = strtok(blist, ", \t");
- while (p) {
- if (!strcmp("noptr", p)) {
- blackout_ptr = 1;
- rfbLog("pointer will be blocked from blackout "
- "regions\n");
- p = strtok(NULL, ", \t");
- continue;
- }
- if (! parse_geom(p, &w, &h, &x, &y, dpy_x, dpy_y)) {
- if (*p != '\0') {
- rfbLog("skipping invalid geometry: %s\n", p);
- }
- p = strtok(NULL, ", \t");
- continue;
- }
- w = nabs(w);
- h = nabs(h);
- x = nfix(x, dpy_x);
- y = nfix(y, dpy_y);
- X = x + w;
- Y = y + h;
- X = nfix(X, dpy_x+1);
- Y = nfix(Y, dpy_y+1);
- if (x > X) {
- t = X; X = x; x = t;
- }
- if (y > Y) {
- t = Y; Y = y; y = t;
- }
-
- /* take clipping region into account */
- x = nfix(x - coff_x, wdpy_x);
- X = nfix(X - coff_x, wdpy_x);
- y = nfix(y - coff_y, wdpy_y);
- Y = nfix(Y - coff_y, wdpy_y);
-
- if (x < 0 || x > dpy_x || y < 0 || y > dpy_y ||
- X < 0 || X > dpy_x || Y < 0 || Y > dpy_y ||
- x == X || y == Y) {
- rfbLog("skipping invalid blackout geometry: %s x="
- "%d-%d,y=%d-%d,w=%d,h=%d\n", p, x, X, y, Y, w, h);
- } else {
- rfbLog("blackout rect: %s: x=%d-%d y=%d-%d\n", p,
- x, X, y, Y);
-
- /*
- * note that the black out is x1 <= x but x < x2
- * for the region. i.e. the x2, y2 are outside
- * by 1 pixel.
- */
- blackr[blackouts].x1 = x;
- blackr[blackouts].y1 = y;
- blackr[blackouts].x2 = X;
- blackr[blackouts].y2 = Y;
- blackouts++;
- if (blackouts >= BLACKR_MAX) {
- rfbLog("too many blackouts: %d\n", blackouts);
- break;
- }
- }
- p = strtok(NULL, ", \t");
- }
- free(blist);
-}
-
-/*
- * Now that all blackout rectangles have been constructed, see what overlap
- * they have with the tiles in the system. If a tile is touched by a
- * blackout, record information.
- */
-static void blackout_tiles(void) {
- int tx, ty;
- int debug_bo = 0;
- if (! blackouts) {
- return;
- }
- if (getenv("DEBUG_BLACKOUT") != NULL) {
- debug_bo = 1;
- }
-
- /*
- * to simplify things drop down to single copy mode, etc...
- */
- single_copytile = 1;
- /* loop over all tiles. */
- for (ty=0; ty < ntiles_y; ty++) {
- for (tx=0; tx < ntiles_x; tx++) {
- sraRegionPtr tile_reg, black_reg;
- sraRect rect;
- sraRectangleIterator *iter;
- int n, b, x1, y1, x2, y2, cnt;
-
- /* tile number and coordinates: */
- n = tx + ty * ntiles_x;
- x1 = tx * tile_x;
- y1 = ty * tile_y;
- x2 = x1 + tile_x;
- y2 = y1 + tile_y;
- if (x2 > dpy_x) {
- x2 = dpy_x;
- }
- if (y2 > dpy_y) {
- y2 = dpy_y;
- }
-
- /* make regions for the tile and the blackouts: */
- black_reg = (sraRegionPtr) sraRgnCreate();
- tile_reg = (sraRegionPtr) sraRgnCreateRect(x1, y1,
- x2, y2);
-
- tile_blackout[n].cover = 0;
- tile_blackout[n].count = 0;
-
- /* union of blackouts */
- for (b=0; b < blackouts; b++) {
- sraRegionPtr tmp_reg = (sraRegionPtr)
- sraRgnCreateRect(blackr[b].x1,
- blackr[b].y1, blackr[b].x2, blackr[b].y2);
-
- sraRgnOr(black_reg, tmp_reg);
- sraRgnDestroy(tmp_reg);
- }
-
- if (! sraRgnAnd(black_reg, tile_reg)) {
- /*
- * no intersection for this tile, so we
- * are done.
- */
- sraRgnDestroy(black_reg);
- sraRgnDestroy(tile_reg);
- continue;
- }
-
- /*
- * loop over rectangles that make up the blackout
- * region:
- */
- cnt = 0;
- iter = sraRgnGetIterator(black_reg);
- while (sraRgnIteratorNext(iter, &rect)) {
-
- /* make sure x1 < x2 and y1 < y2 */
- if (rect.x1 > rect.x2) {
- int tmp = rect.x2;
- rect.x2 = rect.x1;
- rect.x1 = tmp;
- }
- if (rect.y1 > rect.y2) {
- int tmp = rect.y2;
- rect.y2 = rect.y1;
- rect.y1 = tmp;
- }
-
- /* store coordinates */
- tile_blackout[n].bo[cnt].x1 = rect.x1;
- tile_blackout[n].bo[cnt].y1 = rect.y1;
- tile_blackout[n].bo[cnt].x2 = rect.x2;
- tile_blackout[n].bo[cnt].y2 = rect.y2;
-
- /* note if the tile is completely obscured */
- if (rect.x1 == x1 && rect.y1 == y1 &&
- rect.x2 == x2 && rect.y2 == y2) {
- tile_blackout[n].cover = 2;
- if (debug_bo) {
- fprintf(stderr, "full: %d=%d,%d"
- " (%d-%d) (%d-%d)\n",
- n, tx, ty, x1, x2, y1, y2);
- }
- } else {
- tile_blackout[n].cover = 1;
- if (debug_bo) {
- fprintf(stderr, "part: %d=%d,%d"
- " (%d-%d) (%d-%d)\n",
- n, tx, ty, x1, x2, y1, y2);
- }
- }
-
- if (++cnt >= BO_MAX) {
- rfbLog("too many blackout rectangles "
- "for tile %d=%d,%d.\n", n, tx, ty);
- break;
- }
- }
- sraRgnReleaseIterator(iter);
-
- sraRgnDestroy(black_reg);
- sraRgnDestroy(tile_reg);
-
- tile_blackout[n].count = cnt;
- if (debug_bo && cnt > 1) {
- rfbLog("warning: multiple region overlaps[%d] "
- "for tile %d=%d,%d.\n", cnt, n, tx, ty);
- }
- }
- }
-}
-
-static int did_xinerama_clip = 0;
-
-void check_xinerama_clip(void) {
-#if LIBVNCSERVER_HAVE_LIBXINERAMA
- int n, k, i, ev, er, juse = -1;
- int score[32], is = 0;
- XineramaScreenInfo *x;
-
- if (!clip_str || !dpy) {
- return;
- }
- if (sscanf(clip_str, "xinerama%d", &k) == 1) {
- ;
- } else if (sscanf(clip_str, "screen%d", &k) == 1) {
- ;
- } else {
- return;
- }
-
- free(clip_str);
- clip_str = NULL;
-
- if (! XineramaQueryExtension(dpy, &ev, &er)) {
- return;
- }
- if (! XineramaIsActive(dpy)) {
- return;
- }
- x = XineramaQueryScreens(dpy, &n);
- if (k < 0 || k >= n) {
- XFree_wr(x);
- return;
- }
- for (i=0; i < n; i++) {
- score[is++] = nabs(x[i].x_org) + nabs(x[i].y_org);
- if (is >= 32) {
- break;
- }
- }
- for (i=0; i <= k; i++) {
- int j, jmon = 0, mon = -1, mox = -1;
- for (j=0; j < is; j++) {
- if (mon < 0 || score[j] < mon) {
- mon = score[j];
- jmon = j;
- }
- if (mox < 0 || score[j] > mox) {
- mox = score[j];
- }
- }
- juse = jmon;
- score[juse] = mox+1+i;
- }
-
- if (juse >= 0 && juse < n) {
- char str[64];
- sprintf(str, "%dx%d+%d+%d", x[juse].width, x[juse].height,
- x[juse].x_org, x[juse].y_org);
- clip_str = strdup(str);
- did_xinerama_clip = 1;
- } else {
- clip_str = strdup("");
- }
- XFree_wr(x);
- if (!quiet) {
- rfbLog("set -clip to '%s' for xinerama%d\n", clip_str, k);
- }
-#endif
-}
-
-static void initialize_xinerama (void) {
-#if !LIBVNCSERVER_HAVE_LIBXINERAMA
- if (!raw_fb_str) {
- rfbLog("Xinerama: Library libXinerama is not available to determine\n");
- rfbLog("Xinerama: the head geometries, consider using -blackout\n");
- rfbLog("Xinerama: if the screen is non-rectangular.\n");
- }
-#else
- XineramaScreenInfo *sc, *xineramas;
- sraRegionPtr black_region, tmp_region;
- sraRectangleIterator *iter;
- sraRect rect;
- char *bstr, *tstr;
- int ev, er, i, n, rcnt;
-
- RAWFB_RET_VOID
-
- X_LOCK;
- if (! XineramaQueryExtension(dpy, &ev, &er)) {
- if (verbose) {
- rfbLog("Xinerama: disabling: display does not support it.\n");
- }
- xinerama = 0;
- xinerama_present = 0;
- X_UNLOCK;
- return;
- }
- if (! XineramaIsActive(dpy)) {
- /* n.b. change to XineramaActive(dpy, window) someday */
- if (verbose) {
- rfbLog("Xinerama: disabling: not active on display.\n");
- }
- xinerama = 0;
- xinerama_present = 0;
- X_UNLOCK;
- return;
- }
- xinerama_present = 1;
- rfbLog("\n");
- rfbLog("Xinerama is present and active (e.g. multi-head).\n");
-
- /* n.b. change to XineramaGetData() someday */
- xineramas = XineramaQueryScreens(dpy, &n);
- rfbLog("Xinerama: number of sub-screens: %d\n", n);
-
- if (! use_xwarppointer && ! got_noxwarppointer && n > 1) {
- rfbLog("Xinerama: enabling -xwarppointer mode to try to correct\n");
- rfbLog("Xinerama: mouse pointer motion. XTEST+XINERAMA bug.\n");
- rfbLog("Xinerama: Use -noxwarppointer to force XTEST.\n");
- use_xwarppointer = 1;
- }
-
- if (n == 1) {
- rfbLog("Xinerama: no blackouts needed (only one sub-screen)\n");
- rfbLog("\n");
- XFree_wr(xineramas);
- X_UNLOCK;
- return; /* must be OK w/o change */
- }
-
- black_region = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
-
- sc = xineramas;
- for (i=0; i<n; i++) {
- int x, y, w, h;
-
- x = sc->x_org;
- y = sc->y_org;
- w = sc->width;
- h = sc->height;
-
- rfbLog("Xinerama: sub-screen[%d] %dx%d+%d+%d\n", i, w, h, x, y);
-
- tmp_region = sraRgnCreateRect(x, y, x + w, y + h);
-
- sraRgnSubtract(black_region, tmp_region);
- sraRgnDestroy(tmp_region);
- sc++;
- }
- XFree_wr(xineramas);
- X_UNLOCK;
-
-
- if (sraRgnEmpty(black_region)) {
- rfbLog("Xinerama: no blackouts needed (screen fills"
- " rectangle)\n");
- rfbLog("\n");
- sraRgnDestroy(black_region);
- return;
- }
- if (did_xinerama_clip) {
- rfbLog("Xinerama: no blackouts due to -clip xinerama.\n");
- return;
- }
-
- /* max len is 10000x10000+10000+10000 (23 chars) per geometry */
- rcnt = (int) sraRgnCountRects(black_region);
- bstr = (char *) malloc(30 * (rcnt+1));
- tstr = (char *) malloc(30);
- bstr[0] = '\0';
-
- iter = sraRgnGetIterator(black_region);
- while (sraRgnIteratorNext(iter, &rect)) {
- int x, y, w, h;
-
- /* make sure x1 < x2 and y1 < y2 */
- if (rect.x1 > rect.x2) {
- int tmp = rect.x2;
- rect.x2 = rect.x1;
- rect.x1 = tmp;
- }
- if (rect.y1 > rect.y2) {
- int tmp = rect.y2;
- rect.y2 = rect.y1;
- rect.y1 = tmp;
- }
- x = rect.x1;
- y = rect.y1;
- w = rect.x2 - x;
- h = rect.y2 - y;
- sprintf(tstr, "%dx%d+%d+%d,", w, h, x, y);
- strcat(bstr, tstr);
- }
- sraRgnReleaseIterator(iter);
- initialize_blackouts(bstr);
- rfbLog("\n");
-
- free(bstr);
- free(tstr);
-#endif
-}
-
-void initialize_blackouts_and_xinerama(void) {
-
- blackouts = 0;
- blackout_ptr = 0;
-
- if (blackout_str != NULL) {
- initialize_blackouts(blackout_str);
- }
- if (xinerama) {
- initialize_xinerama();
- }
- if (blackouts) {
- blackout_tiles();
- /* schedule a copy_screen(), now is too early. */
- do_copy_screen = 1;
- }
-}
-
-void push_sleep(int n) {
- int i;
- for (i=0; i<n; i++) {
- rfbPE(-1);
- if (i != n-1 && defer_update) {
- usleep(defer_update * 1000);
- }
- }
-}
-
-/*
- * try to forcefully push a black screen to all connected clients
- */
-void push_black_screen(int n) {
- int Lx = dpy_x, Ly = dpy_y;
- if (!screen) {
- return;
- }
-#ifndef NO_NCACHE
- if (ncache > 0) {
- Ly = dpy_y * (1+ncache);
- }
-#endif
- zero_fb(0, 0, Lx, Ly);
- mark_rect_as_modified(0, 0, Lx, Ly, 0);
- push_sleep(n);
-}
-
-void refresh_screen(int push) {
- int i;
- if (!screen) {
- return;
- }
- mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
- for (i=0; i<push; i++) {
- rfbPE(-1);
- }
-}
-
-/*
- * Fill the framebuffer with zero for the prescribed rectangle
- */
-void zero_fb(int x1, int y1, int x2, int y2) {
- int pixelsize = bpp/8;
- int line, fill = 0, yfac = 1;
- char *dst;
-
-#ifndef NO_NCACHE
- if (ncache > 0) {
- yfac = 1+ncache;
- if (ncache_xrootpmap) {
- yfac++;
- }
- }
-#endif
-
- if (x1 < 0 || x2 <= x1 || x2 > dpy_x) {
- return;
- }
- if (y1 < 0 || y2 <= y1 || y2 > yfac * dpy_y) {
- return;
- }
- if (! main_fb) {
- return;
- }
-
- dst = main_fb + y1 * main_bytes_per_line + x1 * pixelsize;
- line = y1;
- while (line++ < y2) {
- memset(dst, fill, (size_t) (x2 - x1) * pixelsize);
- dst += main_bytes_per_line;
- }
-}
-
-
OpenPOWER on IntegriCloud