Esempio n. 1
0
void Workspace::damageNotifyEvent( const XDamageNotifyEvent *event )
{
	Client *client = find( event->drawable );

	// ### should never happen
	if ( !client )
		return;

	XserverRegion parts;

	if ( !client->isPainted() ) {
		// If the window has been painted for the first time, mark the whole
		// window as damaged.
		parts = client->createRegion( WindowAndBorder );
		XDamageSubtract( dpy, client->damageHandle(), None, None );
		client->setPainted( true );
	} else {
		// Create a new empty region
		parts = XFixesCreateRegion( dpy, 0, 0 );

		// Copy the damage region to parts, subtracting it from the widgets damage
		XDamageSubtract( dpy, client->damageHandle(), None, parts );

		// Offset parts with the widgets position
		XFixesTranslateRegion( dpy, parts, client->x(), client->y() );
	}

	// Add the damaged region to the total damage for the workspace
	// (destroys parts)
	addDamage( parts );
}
GdkFilterReturn
nsPluginNativeWindowGtk2::plugin_composite_filter_func (GdkXEvent *xevent,
    GdkEvent *event,
    gpointer data)
{
  nsPluginNativeWindowGtk2 *native_window = (nsPluginNativeWindowGtk2*)data;
  XDamageNotifyEvent *ev;
  ev = (XDamageNotifyEvent *) xevent;
  if (ev->type != xdamage_event_base + XDamageNotify)
    return GDK_FILTER_CONTINUE;

  //printf("Damage event %d %d %d %d\n",ev->area.x, ev->area.y, ev->area.width, ev->area.height);
  XDamageSubtract (GDK_DISPLAY(), native_window->mDamage, None, None);

  /* We try to do our area invalidation here */
  nsPluginRect rect;
  rect.top = ev->area.x;
  rect.left = ev->area.y;
  rect.right = ev->area.x + ev->area.width;
  rect.bottom = ev->area.y + ev->area.height;

  if (native_window->mPluginInstance)
    native_window->mPluginInstance->InvalidateRect(&rect);

  return GDK_FILTER_REMOVE;
}
static ClutterX11FilterReturn
on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data)
{
  ClutterX11TexturePixmap        *texture;
  ClutterX11TexturePixmapPrivate *priv;
  Display                        *dpy;

  texture = CLUTTER_X11_TEXTURE_PIXMAP (data);

  g_return_val_if_fail (CLUTTER_X11_IS_TEXTURE_PIXMAP (texture), \
                        CLUTTER_X11_FILTER_CONTINUE);

  dpy = clutter_x11_get_default_display();
  priv = texture->priv;

  if (xev->type == _damage_event_base + XDamageNotify)
    {
      XserverRegion  parts;
      gint           i, r_count;
      XRectangle    *r_damage;
      XRectangle     r_bounds;
      XDamageNotifyEvent *dev = (XDamageNotifyEvent*)xev;

      if (dev->drawable != priv->damage_drawable)
        return CLUTTER_X11_FILTER_CONTINUE;


      clutter_x11_trap_x_errors ();
      /*
       * Retrieve the damaged region and break it down into individual
       * rectangles so we do not have to update the whole shebang.
       */
      parts = XFixesCreateRegion (dpy, 0, 0);
      XDamageSubtract (dpy, priv->damage, None, parts);

      r_damage = XFixesFetchRegionAndBounds (dpy,
                                             parts,
                                             &r_count,
                                             &r_bounds);

      clutter_x11_untrap_x_errors ();

      if (r_damage)
        {
          for (i = 0; i < r_count; ++i)
            clutter_x11_texture_pixmap_update_area (texture,
                                                    r_damage[i].x,
                                                    r_damage[i].y,
                                                    r_damage[i].width,
                                                    r_damage[i].height);
          XFree (r_damage);
        }

      XFixesDestroyRegion (dpy, parts);
    }

  return  CLUTTER_X11_FILTER_CONTINUE;
}
Esempio n. 4
0
EAPI void
ecore_x_damage_subtract(Ecore_X_Damage damage,
                        Ecore_X_Region repair,
                        Ecore_X_Region parts)
{
#ifdef ECORE_XDAMAGE
   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   XDamageSubtract(_ecore_x_disp, damage, repair, parts);
#endif /* ifdef ECORE_XDAMAGE */
}
Esempio n. 5
0
    GdkFilterReturn filterXEvent(XEvent* event) const
    {
        if (event->type != s_damageEventBase + XDamageNotify)
            return GDK_FILTER_CONTINUE;

        XDamageNotifyEvent* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(event);
        if (const auto& notifyFunction = m_notifyFunctions.get(damageEvent->drawable)) {
            notifyFunction();
            XDamageSubtract(event->xany.display, damageEvent->damage, None, None);
            return GDK_FILTER_REMOVE;
        }

        return GDK_FILTER_CONTINUE;
    }
static GdkFilterReturn filterXDamageEvent(GdkXEvent* gdkXEvent, GdkEvent* event, void*)
{
    XEvent* xEvent = static_cast<XEvent*>(gdkXEvent);
    if (xEvent->type != gDamageEventBase + XDamageNotify)
        return GDK_FILTER_CONTINUE;

    XDamageNotifyEvent* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(xEvent);
    WindowHashMap& windowHashMap = getWindowHashMap();
    WindowHashMap::iterator i = windowHashMap.find(damageEvent->drawable);
    if (i == windowHashMap.end())
        return GDK_FILTER_CONTINUE;

    i->value->callDamageNotifyCallback();
    XDamageSubtract(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), damageEvent->damage, None, None);
    return GDK_FILTER_REMOVE;
}
Esempio n. 7
0
void clear_xdamage_mark_region(sraRegionPtr markregion, int flush) {
#if HAVE_LIBXDAMAGE
	XEvent ev;
	sraRegionPtr tmpregion;
	int count = 0;

	RAWFB_RET_VOID

	if (! xdamage_present || ! use_xdamage) {
		return;
	}
	if (! xdamage) {
		return;
	}
	if (! xdamage_base_event_type) {
		return;
	}
	if (unixpw_in_progress) return;

	X_LOCK;
	if (flush) {
		XFlush_wr(dpy);
	}
	while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) {
		count++;
	}
	/* clear the whole damage region */
	XDamageSubtract(dpy, xdamage, None, None);
	X_UNLOCK;

	if (debug_tiles || debug_xdamage) {
		fprintf(stderr, "clear_xdamage_mark_region: %d\n", count);
	}

	if (! markregion) {
		/* NULL means mark the whole display */
		tmpregion = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
		add_region_xdamage(tmpregion);
		sraRgnDestroy(tmpregion);
	} else {
		add_region_xdamage(markregion);
	}
#else
	if (0) flush++;        /* compiler warnings */
	if (0) markregion = NULL;   
#endif
}
Esempio n. 8
0
void X11Support::onX11Event(XEvent* event)
{
	if(event->type == m_damageEventBase + XDamageNotify)
	{
		// Repair damaged area.
		XDamageNotifyEvent* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(event);
		XDamageSubtract(QX11Info::display(), damageEvent->damage, None, None);

		emit windowDamaged(event->xany.window);
	}
	if(event->type == DestroyNotify)
		emit windowClosed(event->xdestroywindow.window);
	if(event->type == PropertyNotify)
		emit windowPropertyChanged(event->xproperty.window, event->xproperty.atom);
	if(event->type == ClientMessage)
		emit clientMessageReceived(event->xclient.window, event->xclient.message_type, event->xclient.data.b);
}
Esempio n. 9
0
void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
{
	XRectangle region;

	if (!subsystem->use_xfixes || !subsystem->use_xdamage)
		return;

	region.x = x;
	region.y = y;
	region.width = width;
	region.height = height;

#ifdef WITH_XFIXES
	XFixesSetRegion(subsystem->display, subsystem->xdamage_region, &region, 1);
	XDamageSubtract(subsystem->display, subsystem->xdamage, subsystem->xdamage_region, None);
#endif
}
Esempio n. 10
0
void xf_xdamage_subtract_region(xfPeerContext* xfp, int x, int y, int width, int height)
{
	XRectangle region;
	xfInfo* xfi = xfp->info;

	region.x = x;
	region.y = y;
	region.width = width;
	region.height = height;

#ifdef WITH_XFIXES
	pthread_mutex_lock(&(xfp->mutex));
	XFixesSetRegion(xfi->display, xfi->xdamage_region, &region, 1);
	XDamageSubtract(xfi->display, xfi->xdamage, xfi->xdamage_region, None);
	pthread_mutex_unlock(&(xfp->mutex));
#endif
}
static void
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
{
  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = priv->display;
  Display *xdisplay = meta_display_get_xdisplay (display);

  if (priv->received_damage)
    {
      meta_error_trap_push (display);
      XDamageSubtract (xdisplay, priv->damage, None, None);
      meta_error_trap_pop (display);

      priv->received_damage = FALSE;
    }

  update_pixmap (self);
}
Esempio n. 12
0
void
clientwin_repair(ClientWin *cw)
{
	int nrects, i;
	XRectangle *rects;
	XserverRegion rgn = XFixesCreateRegion(cw->mainwin->dpy, 0, 0);
	
	XDamageSubtract(cw->mainwin->dpy, cw->damage, None, rgn);
	
	rects = XFixesFetchRegion(cw->mainwin->dpy, rgn, &nrects);
	XFixesDestroyRegion(cw->mainwin->dpy, rgn);
	
	for(i = 0; i < nrects; i++)
		clientwin_repaint(cw, &rects[i]);
	
	if(rects)
		XFree(rects);
	
	cw->damaged = False;
}
Esempio n. 13
0
void Thumbnail::onClientEvent(XEvent *event)
{
    if (event->type == XTools::damageEventBase() + XDamageNotify)
    {
        _previewValid = false;
        if (_teleWindow->shown())
        {
            drawPreview();
            _teleWindow->onThumbRedrawed(this);
        }

        XDamageSubtract(_dpy, ((XDamageNotifyEvent*)event)->damage, None, None);
    }
    else if (event->type == ConfigureNotify)
    {
        onClientResize(event);
    }
//    else if (event->type == UnmapNotify)
//    {
//        _teleWindow->updateThumbnailsList();
//    }
    else if (event->type == PropertyNotify)
    {
        if (event->xproperty.atom == XTools::_NET_WM_NAME ||
                event->xproperty.atom == XTools::WM_NAME)
        {
            free(_title);
            _title = XTools::windowTitle_alloc(_clientWindow);

            redraw();
            if (_teleWindow->shown())
                _teleWindow->onThumbRedrawed(this);
        }
        else if (event->xproperty.atom == XTools::WM_STATE);
        {
            _minimized = XTools::checkIfWindowMinimized(_clientWindow);
        }
    }
//    else
//        printf("Thumbnail: unknown client event (%d)\n", event->type);
}
// Global event filter for intercepting damage events
static bool x11EventFilter(void *message, long int *result)
{
    XEvent *event = reinterpret_cast<XEvent*>(message);
    if (event->type == damageEventBase + XDamageNotify) {
        XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event);
        if (DamageWatch *damageWatch = damageWatches.value(e->drawable)) {
            // Create a new region and empty the damage region into it.
            // The window is small enough that we don't really care about the region;
            // we'll just throw it away and schedule a full repaint of the container.
            XserverRegion region = XFixesCreateRegion(e->display, 0, 0);
            XDamageSubtract(e->display, e->damage, None, region);
            XFixesDestroyRegion(e->display, region);
            damageWatch->container->update();
        }
    }

    if (oldEventFilter && oldEventFilter != x11EventFilter) {
        return oldEventFilter(message, result);
    } else {
        return false;
    }
}
Esempio n. 15
0
guint32
ccm_display_register_damage (CCMDisplay* self, CCMDrawable* drawable, CCMDamageCallbackFunc func)
{
    Damage damage = XDamageCreate (CCM_DISPLAY_XDISPLAY (self),
                                   ccm_drawable_get_xid (drawable),
                                   XDamageReportDeltaRectangles);
    if (damage)
    {
        GSList* item;
        gboolean found = FALSE;
        CCMDamageCallback* callback;

        callback = (CCMDamageCallback*)ccm_set_search (self->priv->registered_damage,
                                                       G_TYPE_UINT, NULL, NULL,
                                                       (gpointer)damage,
                                                       (CCMSetValueCompareFunc)ccm_damage_callback_compare_with_damage);
        if (callback == NULL)
        {
            callback = ccm_damage_callback_new ();
            XDamageSubtract (CCM_DISPLAY_XDISPLAY (self), damage, None, None);
            callback->damage = damage;
            callback->func = func;
            callback->drawable = drawable;

            ccm_set_insert (self->priv->registered_damage, callback);
        }
        else
        {
            callback->func = func;
            callback->drawable = drawable;
        }
    }
    else
        damage = None;

    return (guint32)damage;
}
Esempio n. 16
0
void systray_render_icon_composited(void *t)
{
	// we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0
	// we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here
	TrayWindow *traywin = t;

	if (systray_profile)
		fprintf(stderr,
		        "[%f] %s:%d win = %lu (%s)\n",
		        profiling_get_time(),
		        __FUNCTION__,
		        __LINE__,
		        traywin->win,
		        traywin->name);

	// wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms
	struct timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);
	struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, min_refresh_period);
	if (compare_timespecs(&earliest_render, &now) > 0) {
		traywin->num_fast_renders++;
		if (traywin->num_fast_renders > max_fast_refreshes) {
			traywin->render_timeout =
			    add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
			if (systray_profile)
				fprintf(stderr,
				        YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
				        profiling_get_time(),
				        __FUNCTION__,
				        __LINE__,
				        traywin->win,
				        traywin->name);
			return;
		}
	} else {
		traywin->time_last_render.tv_sec = now.tv_sec;
		traywin->time_last_render.tv_nsec = now.tv_nsec;
		traywin->num_fast_renders = 0;
	}

	if (traywin->width == 0 || traywin->height == 0) {
		// reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu)
		traywin->render_timeout =
		    add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout);
		if (systray_profile)
			fprintf(stderr,
			        YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n",
			        profiling_get_time(),
			        __FUNCTION__,
			        __LINE__,
			        traywin->win,
			        traywin->name);
		return;
	}

	if (traywin->render_timeout) {
		stop_timeout(traywin->render_timeout);
		traywin->render_timeout = NULL;
	}

	// good systray icons support 32 bit depth, but some icons are still 24 bit.
	// We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and
	// mask out all pixel with the same rgb value

	// Very ugly hack, but somehow imlib2 is not able to get the image from the traywindow itself,
	// so we first render the tray window onto a pixmap, and then we tell imlib2 to use this pixmap as
	// drawable. If someone knows why it does not work with the traywindow itself, please tell me ;)
	Pixmap tmp_pmap = XCreatePixmap(server.display, traywin->win, traywin->width, traywin->height, 32);
	if (!tmp_pmap) {
		goto on_systray_error;
	}
	XRenderPictFormat *f;
	if (traywin->depth == 24) {
		f = XRenderFindStandardFormat(server.display, PictStandardRGB24);
	} else if (traywin->depth == 32) {
		f = XRenderFindStandardFormat(server.display, PictStandardARGB32);
	} else {
		fprintf(stderr, RED "Strange tray icon found with depth: %d" RESET "\n", traywin->depth);
		XFreePixmap(server.display, tmp_pmap);
		return;
	}
	XRenderPictFormat *f32 = XRenderFindVisualFormat(server.display, server.visual32);
	if (!f || !f32) {
		XFreePixmap(server.display, tmp_pmap);
		goto on_systray_error;
	}

	XSync(server.display, False);
	error = FALSE;
	XErrorHandler old = XSetErrorHandler(window_error_handler);

	// if (server.real_transparency)
	// Picture pict_image = XRenderCreatePicture(server.display, traywin->parent, f, 0, 0);
	// reverted Rev 407 because here it's breaking alls icon with systray + xcompmgr
	Picture pict_image = XRenderCreatePicture(server.display, traywin->win, f, 0, 0);
	if (!pict_image) {
		XFreePixmap(server.display, tmp_pmap);
		XSetErrorHandler(old);
		goto on_error;
	}
	Picture pict_drawable =
		XRenderCreatePicture(server.display, tmp_pmap, XRenderFindVisualFormat(server.display, server.visual32), 0, 0);
	if (!pict_drawable) {
		XRenderFreePicture(server.display, pict_image);
		XFreePixmap(server.display, tmp_pmap);
		XSetErrorHandler(old);
		goto on_error;
	}
	XRenderComposite(server.display,
	                 PictOpSrc,
	                 pict_image,
	                 None,
	                 pict_drawable,
	                 0,
	                 0,
	                 0,
	                 0,
	                 0,
	                 0,
	                 traywin->width,
	                 traywin->height);
	XRenderFreePicture(server.display, pict_image);
	XRenderFreePicture(server.display, pict_drawable);
	// end of the ugly hack and we can continue as before

	imlib_context_set_visual(server.visual32);
	imlib_context_set_colormap(server.colormap32);
	imlib_context_set_drawable(tmp_pmap);
	Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 1);
	imlib_context_set_visual(server.visual);
	imlib_context_set_colormap(server.colormap);
	XFreePixmap(server.display, tmp_pmap);
	if (!image) {
		imlib_context_set_visual(server.visual);
		imlib_context_set_colormap(server.colormap);
		XSetErrorHandler(old);
		goto on_error;
	} else {
		if (traywin->image) {
			imlib_context_set_image(traywin->image);
			imlib_free_image_and_decache();
		}
		traywin->image = image;
	}

	imlib_context_set_image(traywin->image);
	// if (traywin->depth == 24)
	// imlib_save_image("/home/thil77/test.jpg");
	imlib_image_set_has_alpha(1);
	DATA32 *data = imlib_image_get_data();
	if (traywin->depth == 24) {
		create_heuristic_mask(data, traywin->width, traywin->height);
	}

	if (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0)
		adjust_asb(data,
		           traywin->width,
		           traywin->height,
		           systray.alpha,
		           (float)systray.saturation / 100,
		           (float)systray.brightness / 100);
	imlib_image_put_back_data(data);

	systray_render_icon_from_image(traywin);

	if (traywin->damage)
		XDamageSubtract(server.display, traywin->damage, None, None);
	XSync(server.display, False);
	XSetErrorHandler(old);

	if (error)
		goto on_error;

	panel_refresh = TRUE;

	if (systray_profile)
		fprintf(stderr,
		        "[%f] %s:%d win = %lu (%s)\n",
		        profiling_get_time(),
		        __FUNCTION__,
		        __LINE__,
		        traywin->win,
		        traywin->name);

	return;

on_error:
	fprintf(stderr,
	        RED "systray %d: rendering error for icon %lu (%s) pid %d" RESET "\n",
	        __LINE__,
	        traywin->win,
	        traywin->name,
	        traywin->pid);
	return;

on_systray_error:
	fprintf(stderr,
	        RED "systray %d: rendering error for icon %lu (%s) pid %d. "
	            "Disabling compositing and restarting systray..." RESET "\n",
	        __LINE__,
	        traywin->win,
	        traywin->name,
	        traywin->pid);
	systray_composited = 0;
	stop_net();
	start_net();
	return;
}
Esempio n. 17
0
static void
process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
                      XDamageNotifyEvent *damage_event)
{
  CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
  Display *display;
  enum
{ DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode;
  const CoglWinsysVtable *winsys;

  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

  display = cogl_xlib_renderer_get_display (ctxt->display->renderer);

  COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap);

  switch (tex_pixmap->damage_report_level)
    {
    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES:
      /* For raw rectangles we don't need do look at the damage region
         at all because the damage area is directly given in the event
         struct and the reporting of events is not affected by
         clearing the damage region */
      handle_mode = DO_NOTHING;
      break;

    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES:
    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY:
      /* For delta rectangles and non empty we'll query the damage
         region for the bounding box */
      handle_mode = NEED_BOUNDING_BOX;
      break;

    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX:
      /* For bounding box we need to clear the damage region but we
         don't actually care what it was because the damage event
         itself contains the bounding box of the region */
      handle_mode = NEEDS_SUBTRACT;
      break;

    default:
      g_assert_not_reached ();
    }

  /* If the damage already covers the whole rectangle then we don't
     need to request the bounding box of the region because we're
     going to update the whole texture anyway. */
  if (cogl_damage_rectangle_is_whole (&tex_pixmap->damage_rect,
                                      tex->width,
                                      tex->height))
    {
      if (handle_mode != DO_NOTHING)
        XDamageSubtract (display, tex_pixmap->damage, None, None);
    }
  else if (handle_mode == NEED_BOUNDING_BOX)
    {
      XserverRegion parts;
      int r_count;
      XRectangle r_bounds;
      XRectangle *r_damage;

      /* We need to extract the damage region so we can get the
         bounding box */

      parts = XFixesCreateRegion (display, 0, 0);
      XDamageSubtract (display, tex_pixmap->damage, None, parts);
      r_damage = XFixesFetchRegionAndBounds (display,
                                             parts,
                                             &r_count,
                                             &r_bounds);
      cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                                   r_bounds.x,
                                   r_bounds.y,
                                   r_bounds.width,
                                   r_bounds.height);
      if (r_damage)
        XFree (r_damage);

      XFixesDestroyRegion (display, parts);
    }
  else
    {
      if (handle_mode == NEEDS_SUBTRACT)
        /* We still need to subtract from the damage region but we
           don't care what the region actually was */
        XDamageSubtract (display, tex_pixmap->damage, None, None);

      cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                                   damage_event->area.x,
                                   damage_event->area.y,
                                   damage_event->area.width,
                                   damage_event->area.height);
    }

  if (tex_pixmap->winsys)
    {
      /* If we're using the texture from pixmap extension then there's no
         point in getting the region and we can just mark that the texture
         needs updating */
      winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
      winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
    }
}
Esempio n. 18
0
int collect_xdamage(int scancnt, int call) {
#if HAVE_LIBXDAMAGE
	XDamageNotifyEvent *dev;
	XEvent ev;
	sraRegionPtr tmpregion;
	sraRegionPtr reg;
	static int rect_count = 0;
	int nreg, ccount = 0, dcount = 0, ecount = 0;
	static time_t last_rpt = 0;
	time_t now;
	int x, y, w, h, x2, y2;
	int i, dup, next = 0, dup_max = 0;
#define DUPSZ 32
	int dup_x[DUPSZ], dup_y[DUPSZ], dup_w[DUPSZ], dup_h[DUPSZ];
	double tm, dt;
	int mark_all = 0, retries = 0, too_many = 1000, tot_ev = 0;

	RAWFB_RET(0)

	if (scancnt) {} /* unused vars warning: */

	if (! xdamage_present || ! use_xdamage) {
		return 0;
	}
	if (! xdamage) {
		return 0;
	}
	if (! xdamage_base_event_type) {
		return 0;
	}
	if (! xdamage_regions) {
		return 0;
	}

	dtime0(&tm);

	nreg = (xdamage_memory * NSCAN) + 1;

	if (call == 0) {
		xdamage_ticker = (xdamage_ticker+1) % nreg;
		xdamage_direct_count = 0;
		reg = xdamage_regions[xdamage_ticker];  
		if (reg != NULL) {
			sraRgnMakeEmpty(reg);
		}
	} else {
		if (xdamage_ticker < 0) {
			xdamage_ticker = 0;
		}
		reg = xdamage_regions[xdamage_ticker];  
	}
	if (reg == NULL) {
		return 0;
	}


	X_LOCK;
if (0)	XFlush_wr(dpy);
if (0)	XEventsQueued(dpy, QueuedAfterFlush);

	come_back_for_more:

	while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) {
		/*
		 * TODO max cut off time in this loop?
		 * Could check QLength and if huge just mark the whole
		 * screen.
		 */
		ecount++;
		tot_ev++;

		if (mark_all) {
			continue;
		}
		if (ecount == too_many) {
			int nqa = XEventsQueued(dpy, QueuedAlready);
			if (nqa >= too_many) {
				static double last_msg = 0.0;
				tmpregion = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
				sraRgnOr(reg, tmpregion);
				sraRgnDestroy(tmpregion);
				if (dnow() > last_msg + xdamage_crazy_delay) {
					rfbLog("collect_xdamage: too many xdamage events %d+%d\n", ecount, nqa);
					last_msg = dnow();
				}
				mark_all = 1;
			}
		}

		if (ev.type != xdamage_base_event_type + XDamageNotify) {
			break;
		}
		dev = (XDamageNotifyEvent *) &ev;
		if (dev->damage != xdamage) {
			continue;	/* not ours! */
		}

		x = dev->area.x;
		y = dev->area.y;
		w = dev->area.width;
		h = dev->area.height;

		/*
		 * we try to manually remove some duplicates because
		 * certain activities can lead to many 10's of dups
		 * in a row.  The region work can be costly and reg is
		 * later used in xdamage_hint_skip loops, so it is good
		 * to skip them if possible.
		 */
		dup = 0;
		for (i=0; i < dup_max; i++) {
			if (dup_x[i] == x && dup_y[i] == y && dup_w[i] == w &&
			    dup_h[i] == h) {
				dup = 1;
				break;
			}
		}
		if (dup) {
			dcount++;
			continue;
		}
		if (dup_max < DUPSZ) {
			next = dup_max;
			dup_max++;
		} else {
			next = (next+1) % DUPSZ;
		}
		dup_x[next] = x;
		dup_y[next] = y;
		dup_w[next] = w;
		dup_h[next] = h;

		/* translate if needed */
		if (clipshift) {
			/* set coords relative to fb origin */
			if (0 && rootshift) {
				/*
				 * Note: not needed because damage is
				 * relative to subwin, not rootwin.
				 */
				x = x - off_x;
				y = y - off_y;
			}
			if (clipshift) {
				x = x - coff_x;
				y = y - coff_y;
			}

			x2 = x + w;		/* upper point */
			x  = nfix(x,  dpy_x);	/* place both in fb area */
			x2 = nfix(x2, dpy_x+1);
			w = x2 - x;		/* recompute w */
			
			y2 = y + h;
			y  = nfix(y,  dpy_y);
			y2 = nfix(y2, dpy_y+1);
			h = y2 - y;

			if (w <= 0 || h <= 0) {
				continue;
			}
		}
		if (debug_xdamage > 2) {
			fprintf(stderr, "xdamage: -> event %dx%d+%d+%d area:"
			    " %d  dups: %d  %s\n", w, h, x, y, w*h, dcount,
			    (w*h > xdamage_max_area) ? "TOO_BIG" : "");
		}

		record_desired_xdamage_rect(x, y, w, h);

		tmpregion = sraRgnCreateRect(x, y, x + w, y + h); 
		sraRgnOr(reg, tmpregion);
		sraRgnDestroy(tmpregion);
		rect_count++;
		ccount++;
	}

	if (mark_all) {
		if (ecount + XEventsQueued(dpy, QueuedAlready) >= 3 * too_many && retries < 3) {
			retries++;
			XFlush_wr(dpy);
			usleep(20 * 1000);
			XFlush_wr(dpy);
			ecount = 0;
			goto come_back_for_more;
		}
	}

	/* clear the whole damage region for next time. XXX check */
	if (call == 1) {
		XDamageSubtract(dpy, xdamage, None, None);
	}
	X_UNLOCK;

	if (tot_ev > 20 * too_many) {
		rfbLog("collect_xdamage: xdamage has gone crazy (screensaver or game?) ev: %d ret: %d\n", tot_ev, retries);
		rfbLog("collect_xdamage: disabling xdamage for %d seconds.\n", (int) xdamage_crazy_delay);
		destroy_xdamage_if_needed();
		X_LOCK;
		XSync(dpy, False);
		while (XCheckTypedEvent(dpy, xdamage_base_event_type+XDamageNotify, &ev)) {
			;
		}
		X_UNLOCK;
		xdamage_crazy_time = dnow();
	}

	if (0 && xdamage_direct_count) {
		fb_push();
	}

	dt = dtime(&tm);
	if ((debug_tiles > 1 && ecount) || (debug_tiles && ecount > 200)
	    || debug_xdamage > 1) {
		fprintf(stderr, "collect_xdamage(%d): %.4f t: %.4f ev/dup/accept"
		    "/direct %d/%d/%d/%d\n", call, dt, tm - x11vnc_start, ecount,
		    dcount, ccount, xdamage_direct_count); 
	}
	now = time(NULL);
	if (! last_rpt) {
		last_rpt = now;
	}
	if (now > last_rpt + 15) {
		double rat = -1.0;

		if (XD_tot) {
			rat = ((double) XD_skip)/XD_tot;
		}
		if (debug_tiles || debug_xdamage) {
			fprintf(stderr, "xdamage: == scanline skip/tot: "
			    "%04d/%04d =%.3f  rects: %d  desired: %d\n",
			    XD_skip, XD_tot, rat, rect_count, XD_des);
		}
			
		XD_skip = 0;
		XD_tot  = 0;
		XD_des  = 0;
		rect_count = 0;
		last_rpt = now;
	}
#else
	if (0) scancnt++;	/* compiler warnings */
	if (0) call++;
	if (0) record_desired_xdamage_rect(0, 0, 0, 0);
#endif
	return 0;
}
Esempio n. 19
0
/**
 * Retrieves and processes single X event.
 */
static int process_event(int slice)
{
	xevent_t e;
	struct timeval tv = { 0, slice * 1000 };

	if (!options.abort_wait && xhandler_get_xevent_timed(&e.ev, &tv)) {
		if (e.ev.type == xhandler.damage_event_num + XDamageNotify) {
			XDamageNotifyEvent *dev = &e.dev;
			int xpos = dev->area.x + dev->geometry.x;
			int ypos = dev->area.y + dev->geometry.y;
			/* check if the damage are is in the monitoring area */
			if (xpos + dev->area.width >= options.interested_damage_rect.x && xpos <= (options.interested_damage_rect.x
					+ options.interested_damage_rect.width) && ypos + dev->area.height >= options.interested_damage_rect.y &&
					ypos <= (options.interested_damage_rect.y + options.interested_damage_rect.height)) {
				if (!match_exclude_rules(dev)) {
					window_t* win = window_find(dev->drawable);
					report_add_message(dev->timestamp, "Got damage event %dx%d+%d+%d from 0x%lx (%s)\n", dev->area.width,
							dev->area.height, xpos, ypos, dev->drawable,
							win && win->application ? win->application->name : "unknown");

					if (response.last_action_time) {
						window_t* win = window_find(dev->drawable);
						if (win && win->application) {
							application_register_damage(win->application, dev);
						}
					}
				}
			}
			XDamageSubtract(xhandler.display, dev->damage, None, None);
		} else if (e.ev.type == CreateNotify) {
			/* check new windows if we have to monitor them */
			XCreateWindowEvent* ev = &e.cev;
			/* TODO: Check if we really must monitor only main windows.
			 Probably done to avoid double reporting. We could avoid that by
			 going through monitored window list, checking if this window
			 is in the parent chain of any monitored window. If so, remove the child.
			 Might be expensive though, but worth a try.
			 */
			if (ev->parent == DefaultRootWindow(xhandler.display)) {
				window_t* win = window_try_monitor(ev->window);
				if (win) {
					Time start = xhandler_get_server_time();
					report_add_message(start, "Created window 0x%lx (%s)\n", ev->window,
							win->application ? win->application->name : "unknown");
				}
			}
		} else if (e.ev.type == UnmapNotify) {
			XUnmapEvent* ev = &e.uev;
			window_t* win = window_find(ev->window);
			if (win) {
				Time start = xhandler_get_server_time();
				report_add_message(start, "Unmapped window 0x%lx (%s)\n", ev->window,
						win->application ? win->application->name : "unknown");
			}
		} else if (e.ev.type == MapNotify) {
			XMapEvent* ev = &e.mev;
			window_t* win = window_find(ev->window);
			if (win) {
				Time start = xhandler_get_server_time();
				report_add_message(start, "Mapped window 0x%lx (%s)\n", ev->window,
						win->application ? win->application->name : "unknown");
			}
		} else if (e.ev.type == DestroyNotify) {
			XDestroyWindowEvent* ev = (XDestroyWindowEvent*) &e.dstev;
			window_t* win = window_find(ev->window);
			if (win) {
				Time start = xhandler_get_server_time();
				report_add_message(start, "Destroyed window 0x%lx (%s)\n", ev->window,
						win->application ? win->application->name : "unknown");
				window_remove(win);
			}
		} else {
			/* remove to avoid reporting unwanted even types ?
			 with window creation monitoring there are more unhandled event types */
			/* fprintf(stderr, "Got unwanted event type %d\n", e.type); */
		}
		return e.ev.type;
	}
	return 0;
}
Esempio n. 20
0
/* The main function */
int main(int argc, char const *argv[])
{
	Display *dpy;
	GString *line;
	unsigned xeventmask;
	int error_base, shape_event, damage_event;
	struct
	{
		Bool children, creation, mapping, configure, shape;
		Bool properties, clientmsg;
		Bool visibility, exposure, damages;
		Bool pointer, keyboard;
	} track;

	dpy = XOpenDisplay(NULL);
	XSetErrorHandler(xerror_handler);
	XA_utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
	XA_wm_state    = XInternAtom(dpy, "WM_STATE", False);

	if (argv[1] && !strcmp(argv[1], "-t"))
	{
		Opt_timestamp = 1;
		optind++;
	}

	/* Choose which events we're interested in. */
	memset(&track, 0, sizeof(track));
	track.children		= True;
	track.creation		= True;
	track.mapping		= True;
	track.configure		= True;
	track.shape		= True;
	track.properties	= True;
	track.clientmsg		= True;
	track.visibility	= True;
	track.keyboard		= True;
	for (; argv[optind]; optind++)
	{
		char const *opt;
		Bool add, del, *which;

		opt = argv[optind];
		add = opt[0] == '+';
		del = opt[0] == '-';
		if (add || del)
			opt++;

		if (!strcmp(opt, "children"))
			which = &track.children;
		else if (!strcmp(opt, "create"))
			which = &track.creation;
		else if (!strcmp(opt, "map"))
			which = &track.mapping;
		else if (!strcmp(opt, "config"))
			which = &track.configure;
		else if (!strcmp(opt, "shape"))
			which = &track.shape;
		else if (!strcmp(opt, "prop"))
			which = &track.properties;
		else if (!strcmp(opt, "ipc"))
			which = &track.clientmsg;
		else if (!strcmp(opt, "visibility"))
			which = &track.visibility;
		else if (!strcmp(opt, "expose"))
			which = &track.exposure;
		else if (!strcmp(opt, "damage"))
			which = &track.damages;
		else if (!strcmp(opt, "ptr"))
			which = &track.pointer;
		else if (!strcmp(opt, "kbd"))
			which = &track.keyboard;
		else
			break;

		if (!add && !del)
			memset(&track, 0, sizeof(track));
		*which = !del;
	} /* for */

	xeventmask = 0;
	if (track.creation || track.mapping || track.configure
			|| track.clientmsg)
		xeventmask |= track.children
			? SubstructureNotifyMask
			: StructureNotifyMask;
	if (track.shape)
		XShapeQueryExtension(dpy, &shape_event, &error_base);
	if (track.properties)
		xeventmask |= PropertyChangeMask;
	if (track.visibility)
		xeventmask |= VisibilityChangeMask;
	if (track.exposure)
		xeventmask |= ExposureMask;
	if (track.damages)
		XDamageQueryExtension(dpy, &damage_event, &error_base);
	if (track.pointer);
		xeventmask |= EnterWindowMask|LeaveWindowMask;
	if (track.keyboard)
		xeventmask |= KeyPressMask|KeyReleaseMask;

	/* XSelectInput() the windows we're interested in
	 * or the root window. */
	if (argv[optind])
		do
		{
			Window win;
			char const *errp;

			win = strtoul(argv[optind], (char **)&errp, 0);
			if (errp == argv[optind] || *errp)
			{
				fprintf(stderr, "%s: what is `%s'?\n",
					argv[0], argv[optind]);
				exit(1);
			}

			XSelectInput(dpy, win, xeventmask);
			if (track.shape)
				XShapeSelectInput(dpy, win, ShapeNotifyMask);
			if (track.damages)
				XDamageCreate(dpy, win,
					XDamageReportRawRectangles);
		} while (argv[++optind]);
	else
		XSelectInput(dpy, DefaultRootWindow(dpy), xeventmask);

	/* The main loop */
	line = g_string_new("");
	for (;;)
	{
		XEvent ev;

		/* Wait for, get and process the next event. */
		XNextEvent(dpy, &ev);
		if (ev.type == CreateNotify)
		{
			XCreateWindowEvent const *create = &ev.xcreatewindow;

			if (!track.creation)
				continue;
			fmtxid(line, create->parent);
			g_string_append_printf(line,
				"Create(0x%lx)", create->window);
			output(line, ev.xany.send_event);
		} else if (ev.type == DestroyNotify)
		{
			XDestroyWindowEvent const *destroy = &ev.xdestroywindow;

			if (!track.creation)
				continue;
			fmtxid(line, destroy->event);
			g_string_append_printf(line,
				"Destroy(0x%lx)", destroy->window);
			output(line, ev.xany.send_event);
		} else if (ev.type == MapNotify)
		{
			XMapEvent const *map = &ev.xmap;

			if (!track.mapping)
				continue;
			fmtxid(line, map->event);
			g_string_append_printf(line, "Map(0x%lx%s)",
				map->window, map->override_redirect
					? ", override_redirected" : "");
			output(line, ev.xany.send_event);
		} else if (ev.type == UnmapNotify)
		{
			XUnmapEvent const *unmap = &ev.xunmap;

			if (!track.mapping)
				continue;
			fmtxid(line, unmap->event);
			g_string_append_printf(line, "Unmap(0x%lx%s)",
				unmap->window, unmap->from_configure
					? ", from_configure" : "");
			output(line, ev.xany.send_event);
		} else if (ev.type == ReparentNotify)
		{
			XReparentEvent const *reparent  = &ev.xreparent;

			if (!track.configure)
				continue;
			fmtxid(line, reparent->event);
			g_string_append_printf(line,
				"Reparent(0x%lx => 0x%lx)",
				reparent->window, reparent->parent);
			output(line, ev.xany.send_event);
		} else if (ev.type == ConfigureNotify)
		{
			XConfigureEvent const *cfg = &ev.xconfigure;

			if (!track.configure)
				continue;
			fmtxid(line, cfg->event);
			g_string_append_printf(line,
				"Configure(0x%lx => %dx%d%+d%+d, "
				"above=0x%lx%s)", cfg->window,
				cfg->width, cfg->height, cfg->x, cfg->y,
				cfg->above, cfg->override_redirect
					? ", override_redirected" : "");
			output(line, ev.xany.send_event);
		} else if (track.shape && ev.type == shape_event + ShapeNotify)
		{
			static char const *shapes[] =
				{ "Bounding", "Clip", "Input" };
			XShapeEvent sev;

			memcpy(&sev, &ev, sizeof(sev));
			fmtxid(line, sev.window);
			g_string_append_printf(line,
				"Shape(%s => %dx%d%+d%+d)",
				shapes[sev.kind],
				sev.width, sev.height, sev.x, sev.y);
			output(line, ev.xany.send_event);
		} else if (ev.type == PropertyNotify)
		{
			assert(track.properties);
			property_event(dpy, &ev.xproperty, line);
		} else if (ev.type == ClientMessage)
		{
			if (!track.clientmsg)
				continue;
			client_message(dpy, &ev.xclient, line);
		} else if (ev.type == VisibilityNotify)
		{
			static char const *visibilities[] =
			{
				"unobscured",
				"partially obscured",
				"fully obscured",
			};
			XVisibilityEvent const *vis = &ev.xvisibility;

			assert(track.visibility);
			fmtxid(line, vis->window);
			g_string_append_printf(line, "Visibility=%s",
				visibilities[vis->state]);
			output(line, ev.xany.send_event);
		} else if (ev.type == Expose)
		{
			XExposeEvent const *ex = &ev.xexpose;

			assert(track.exposure);
			fmtxid(line, ex->window);
			g_string_append_printf(line,
				"Expose(%dx%d%+d%+d)",
				ex->width, ex->height,
				ex->x, ex->y);
			output(line, ev.xany.send_event);
		} else if (track.damages && ev.type == damage_event)
		{
			XDamageNotifyEvent dev;

			memcpy(&dev, &ev, sizeof(dev));
			fmtxid(line, dev.drawable);
			g_string_append_printf(line,
				"Damage(%dx%d%+d%+d)",
				dev.area.width, dev.area.height,
				dev.area.x, dev.area.y);
			output(line, ev.xany.send_event);
			XDamageSubtract(dpy, dev.damage, None, None);
		} else if (ev.type == EnterNotify || ev.type == LeaveNotify)
		{
			XCrossingEvent const *cross = &ev.xcrossing;

			if (!track.pointer)
				continue;
			fmtxid(line, cross->window);
			g_string_append_printf(line,
				"%s(%dx%d",
				cross->type == EnterNotify
					? "Enter" : "Leave",
				cross->x, cross->y);
			if (cross->mode == NotifyGrab)
				g_string_append(line, ", grab");
			else if (cross->mode == NotifyUngrab)
				g_string_append(line, ", ungrab");
			g_string_append_c(line, ')');
			output(line, ev.xany.send_event);
		} else if (ev.type == KeyPress || ev.type == KeyRelease)
		{
			static struct { int mask; char const *name; } states[] =
			{
				{ ShiftMask,	"Shift"	},
				{ LockMask,	"Lock"	},
				{ ControlMask,	"Ctrl"	},
				{ Mod1Mask,	"Mod1"	},
				{ Mod2Mask,	"Mod2"	},
				{ Mod3Mask,	"Mod3"	},
				{ Mod4Mask,	"Mod4"	},
				{ Mod5Mask,	"Mod5"	},
			};
			unsigned i;
			int has_modifiers;
			XKeyEvent const *key;

			assert(track.keyboard);
			key = &ev.xkey;
			fmtxid(line, key->window);

			/* Prepend with the list of modifiers. */
			has_modifiers = 0;
			for (i = 0; i < G_N_ELEMENTS(states); i++)
				if (key->state & states[i].mask)
				{
					if (!has_modifiers)
					{
						g_string_append_c(line, ' ');
						has_modifiers = 1;
					} else
						g_string_append_c(line, '-');
					g_string_append(line, states[i].name);
				}
                        if (has_modifiers)
				g_string_append_c(line, '-');
			g_string_append_printf(line, "%s %s",
				XKeysymToString(XKeycodeToKeysym(dpy,
						      key->keycode, 0)),
				ev.type == KeyPress
					? "pressed" : "released");
			output(line, ev.xany.send_event);
		} /* if */
	} /* for ever */

	return 0;
} /* main */