int s = 2; int x1 = nfix(x - s, dpy_x); int y1 = nfix(y - s, dpy_y); int x2 = nfix(x + w + s, dpy_x+1); int y2 = nfix(y + h + s, dpy_y+1); scale_and_mark_rect(x1, y1, x2, y2);
scale_mark(x, y, x+w, y+h);
int check_wireframe(void) {	Window frame, orig_frame;	XWindowAttributes attr;	int dx, dy;	int orig_px, orig_py, orig_x, orig_y, orig_w, orig_h;	int px, py, x, y, w, h;	int box_x, box_y, box_w, box_h;	int orig_cursor_x, orig_cursor_y, g;	int already_down = 0, win_gone = 0, win_unmapped = 0;	double spin = 0.0, tm, last_ptr, last_draw;	int frame_changed = 0, drew_box = 0, got_2nd_pointer = 0;	int special_t1 = 0, break_reason = 0;	static double first_dt_ave = 0.0;	static int first_dt_cnt = 0;	static time_t last_save_stacklist = 0;		/* heuristics: */	double first_event_spin   = wireframe_t1;	double frame_changed_spin = wireframe_t2;	double max_spin = wireframe_t3;	double min_draw = wireframe_t4;	int near_edge;	DB_SET	if (nofb) {		return 0;	}	if (subwin) {		return 0;	/* don't even bother for -id case */	}	if (! button_mask) {		return 0;	/* no button pressed down */	}	if (!use_threads && !got_pointer_input) {		return 0;	/* need ptr input, e.g. button down, motion */	}if (db) fprintf(stderr, "\n*** button down!!  x: %d  y: %d\n", cursor_x, cursor_y);	/*	 * Query where the pointer is and which child of the root	 * window.  We will assume this is the frame the window manager	 * makes when it reparents the toplevel window.	 */	X_LOCK;	if (! get_wm_frame_pos(&px, &py, &x, &y, &w, &h, &frame, NULL)) {if (db) fprintf(stderr, "NO get_wm_frame_pos: 0x%lx\n", frame);		X_UNLOCK;		return 0;	}	X_UNLOCK;if (db) fprintf(stderr, "a: %d  wf: %.3f  A: %d\n", w*h, wireframe_frac, (dpy_x*dpy_y));	/*	 * apply the percentage size criterion (allow opaque moves for	 * small windows)	 */	if ((double) w*h < wireframe_frac * (dpy_x * dpy_y)) {if (db) fprintf(stderr, "small window %.3f\n", ((double) w*h)/(dpy_x * dpy_y));		return 0;	}if (db) fprintf(stderr, "  frame: x: %d  y: %d  w: %d  h: %d  px: %d  py: %d  fr: 0x%lx\n", x, y, w, h, px, py, orig_frame);		/*	 * see if the pointer is within range of the assumed wm frame	 * decorations on the edge of the window.	 */	near_edge = near_wm_edge(x, y, w, h, px, py);	if (! near_edge) {if (db) fprintf(stderr, "INTERIOR\n");		return 0;	}	wireframe_in_progress = 1;	if (button_mask_prev) {		already_down = 1;	}		if (! wireframe_str || !strcmp(wireframe_str, WIREFRAME_PARMS)) {		int link, latency, netrate;		static int didmsg = 0;		link = link_rate(&latency, &netrate);		if (link == LR_DIALUP || link == LR_BROADBAND) {			/* slow link, e.g. dialup, increase timeouts: */			first_event_spin   *= 2.0;			frame_changed_spin *= 2.0;			max_spin *= 2.0;			min_draw *= 1.5;			if (! didmsg) {				rfbLog("increased wireframe timeouts for "				    "slow network connection.\n");				rfbLog("netrate: %d KB/sec, latency: %d ms\n",				    netrate, latency);				didmsg = 1;			}		}	}	/*	 * pointer() should have snapped the stacking list for us, if	 * not, do it now (if the XFakeButtonEvent has been flushed by	 * now the stacking order may be incorrect).	 */	if (strcmp(wireframe_copyrect, "never")) {		if (already_down) {			double age = 0.0;			/*			 * see if we can reuse the stack list (pause			 * with button down)			 */			if (stack_list_num) {				int k, got_me = 0;				for (k = stack_list_num -1; k >=0; k--) {					if (frame == stack_list[k].win) {						got_me = 1;						break;					}				}				if (got_me) {					age = 1.0;				}				snapshot_stack_list(0, age);			}		}		if (! stack_list_num) {			snapshot_stack_list(0, 0.0);		}	}	/* store initial parameters, we look for changes in them */	orig_frame = frame;	orig_px = px;		/* pointer position */	orig_py = py;	orig_x = x;		/* frame position */	orig_y = y;	orig_w = w;		/* frame size */	orig_h = h;	orig_cursor_x = cursor_x;	orig_cursor_y = cursor_y;	/* this is the box frame we would draw */	box_x = x;	box_y = y; 	box_w = w;	box_h = h; 	dtime0(&tm);	last_draw = spin;	/* -threads support for check_wireframe() is rough... crash? */	if (use_threads) {		/* purge any stored up pointer events: */		pointer(-1, 0, 0, NULL);	}	g = got_pointer_input;	while (1) {		X_LOCK;		XFlush(dpy);		X_UNLOCK;		/* try do induce/waitfor some more user input */		if (use_threads) {			usleep(1000);		} else if (drew_box) {			rfbPE(1000);		} else {			rfbCFD(1000);		}		spin += dtime(&tm);		/* check for any timeouts: */		if (frame_changed) {			double delay;			/* max time we play this game: */			if (spin > max_spin) {if (db || db2) fprintf(stderr, " SPIN-OUT-MAX: %.3f\n", spin);				break_reason = 1;				break;			}			/* watch for pointer events slowing down: */			if (special_t1) {				delay = max_spin;			} else {				delay = 2.0* frame_changed_spin;				if (spin > 3.0 * frame_changed_spin) {					delay = 1.5 * delay;				}			}			if (spin > last_ptr + delay) {if (db || db2) fprintf(stderr, " SPIN-OUT-NOT-FAST: %.3f\n", spin);				break_reason = 2;				break;			}		} else if (got_2nd_pointer) {			/*			 * pointer is moving, max time we wait for wm			 * move or resize to be detected			 */			if (spin > frame_changed_spin) {if (db || db2) fprintf(stderr, " SPIN-OUT-NOFRAME-SPIN: %.3f\n", spin);				break_reason = 3;				break;			}		} else {			/* max time we wait for any pointer input */			if (spin > first_event_spin) {if (db || db2) fprintf(stderr, " SPIN-OUT-NO2ND_PTR: %.3f\n", spin);				break_reason = 4;				break;			}		}		/* see if some pointer input occurred: */		if (got_pointer_input > g) {if (db) fprintf(stderr, "  ++pointer event!! [%02d]  dt: %.3f  x: %d  y: %d  mask: %d\n", got_2nd_pointer+1, spin, cursor_x, cursor_y, button_mask);				g = got_pointer_input;			X_LOCK;			XFlush(dpy);			X_UNLOCK;			/* periodically try to let the wm get moving: */			if (!frame_changed && got_2nd_pointer % 4 == 0) {				if (got_2nd_pointer == 0) {					usleep(50 * 1000);				} else {					usleep(25 * 1000);				}			}			got_2nd_pointer++;			last_ptr = spin;			/*			 * see where the pointer currently is.  It may			 * not be our starting frame (i.e. mouse now			 * outside of the moving window).			 */			frame = 0x0;			X_LOCK;			if (! get_wm_frame_pos(&px, &py, &x, &y, &w, &h,			    &frame, NULL)) {				frame = 0x0;if (db) fprintf(stderr, "NO get_wm_frame_pos: 0x%lx\n", frame);			}			if (frame != orig_frame) {				/* see if our original frame is still there */				if (!valid_window(orig_frame, &attr, 1)) {					X_UNLOCK;					/* our window frame went away! */					win_gone = 1;if (db) fprintf(stderr, "FRAME-GONE: 0x%lx\n", orig_frame);					break_reason = 5;					break;				}				if (attr.map_state == IsUnmapped) {					X_UNLOCK;					/* our window frame is now unmapped! */					win_unmapped = 1;if (db) fprintf(stderr, "FRAME-UNMAPPED: 0x%lx\n", orig_frame);					break_reason = 5;					break;				}if (db) fprintf(stderr, "OUT-OF-FRAME: old: x: %d  y: %d  px: %d py: %d 0x%lx\n", x, y, px, py, frame);				/* new parameters for our frame */				x = attr.x;	/* n.b. rootwin is parent */				y = attr.y;				w = attr.width;				h = attr.height;			}			X_UNLOCK;			/* debugging output, to be removed: */if (db) fprintf(stderr, "  frame: x: %d  y: %d  w: %d  h: %d  px: %d  py: %d  fr: 0x%lx\n", x, y, w, h, px, py, frame);	if (db) fprintf(stderr, "        MO,PT,FR: %d/%d %d/%d %d/%d\n", cursor_x - orig_cursor_x, cursor_y - orig_cursor_y, px - orig_px, py - orig_py, x - orig_x, y - orig_y);				if (frame_changed && frame != orig_frame) {if (db) fprintf(stderr, "CHANGED and window switch: 0x%lx\n", frame);			}			if (frame_changed && px - orig_px != x - orig_x) {if (db) fprintf(stderr, "MOVED and diff DX\n");			}			if (frame_changed && py - orig_py != y - orig_y) {if (db) fprintf(stderr, "MOVED and diff DY\n");			}			/* check and see if our frame has been resized: */			if (!frame_changed && (w != orig_w || h != orig_h)) {				int n;				if (!already_down) {					first_dt_ave += spin;					first_dt_cnt++;				}				n = first_dt_cnt ? first_dt_cnt : 1;				frame_changed = 2;if (db) fprintf(stderr, "WIN RESIZE  1st-dt: %.3f\n", first_dt_ave/n);			}			/* check and see if our frame has been moved: */			if (!frame_changed && (x != orig_x || y != orig_y)) {				int n;				if (!already_down) {					first_dt_ave += spin;					first_dt_cnt++;				}				n = first_dt_cnt ? first_dt_cnt : 1;				frame_changed = 1;if (db) fprintf(stderr, "FRAME MOVE  1st-dt: %.3f\n", first_dt_ave/n);			}			/*			 * see if it is time to draw any or a new wireframe box			 */			if (frame_changed) {				int drawit = 0;				if (x != box_x || y != box_y) {					/* moved since last */					drawit = 1;				} else if (w != box_w || h != box_h) {					/* resize since last */					drawit = 1;				}				if (drawit) {					/*					 * check time (to avoid too much					 * animations on slow machines					 * or links).					 */					if (spin > last_draw + min_draw ||					    ! drew_box) {						draw_box(x, y, w, h, 0);						drew_box = 1;						rfbPE(1000);						last_draw = spin;					}				}				box_x = x;				box_y = y;				box_w = w;				box_h = h;			}		}		/* 		 * Now (not earlier) check if the button has come back up.		 * we check here to get a better location and size of		 * the final window.		 */		if (! button_mask) {if (db || db2) fprintf(stderr, "NO button_mask\n");			break_reason = 6;			break;			}	}	if (! drew_box) {		/* nice try, but no move or resize detected.  cleanup. */		if (stack_list_num) {			stack_list_num = 0;		}		wireframe_in_progress = 0;		return 0;	}	/* remove the wireframe */	draw_box(0, 0, 0, 0, 1);	dx = x - orig_x;	dy = y - orig_y;	/*	 * see if we can apply CopyRect or CopyRegion to the change:	 */	if (!strcmp(wireframe_copyrect, "never")) {		;	} else if (win_gone || win_unmapped) {		;	} else if (scaling && ! got_wirecopyrect) {		;	} else if (w != orig_w || h != orig_h) {		;	} else if (dx == 0 && dy == 0) {		;	} else {		int spin_ms = (int) (spin * 1000 * 1000);		int obscured, sent_copyrect = 0;		/*		 * set a timescale comparable to the spin time,		 * but not too short or too long.		 */		if (spin_ms < 30) {			spin_ms = 30;		} else if (spin_ms > 400) {			spin_ms = 400;		}		/* try to flush the wireframe removal: */		fb_push_wait(0.1, FB_COPY|FB_MOD);		/* try to send a clipped copyrect of translation: */		sent_copyrect = try_copyrect(frame, x, y, w, h, dx, dy,		    &obscured, NULL, 0.15);if (db) fprintf(stderr, "send_copyrect: %d\n", sent_copyrect);		if (sent_copyrect) {			/* try to push the changes to viewers: */			if (! obscured) {				fb_push_wait(0.1, FB_COPY);			} else {				fb_push_wait(0.1, FB_COPY);			}			if (scaling) {				static double last_time = 0.0;				double now = dnow(), delay = 0.35;				if (now > last_time + delay) {					int s = 2;					int x1 = nfix(x - s, dpy_x);					int y1 = nfix(y - s, dpy_y);					int x2 = nfix(x + w + s, dpy_x+1);					int y2 = nfix(y + h + s, dpy_y+1);					scale_and_mark_rect(x1, y1, x2, y2);					last_time = now;					last_copyrect_fix = now;				}			}		}	}	if (stack_list_num) {		/* clean up stack_list for next time: */		if (break_reason == 1 || break_reason == 2) {			/*			 * save the stack list, perhaps the user has			 * paused with button down.			 */			last_save_stacklist = time(0);		} else {			stack_list_num = 0;		}	}	/* final push (for -nowirecopyrect) */	rfbPE(1000);	wireframe_in_progress = 0;	urgent_update = 1;	if (use_xdamage) {		/* DAMAGE can queue ~1000 rectangles for a move */		clear_xdamage_mark_region(NULL, 1);		xdamage_scheduled_mark = dnow() + 2.0;	}	return 1;}