private void putPixels(int[] pixels, int[] background) {
    final int cursorX = (int) cursorArea.getX();
    final int cursorY = (int) cursorArea.getY();
    final int maxY = Math.min(cursorY + cursorImage.getHeight(), graphics.getHeight());
    final int maxX = Math.min(cursorX + cursorImage.getWidth(), graphics.getWidth());
    final int width = cursorImage.getWidth();

    int index = 0;
    for (int y = cursorY; y < maxY; y++) {
      int lineIndex = index;
      for (int x = cursorX; x < maxX; x++) {
        int color;
        if (background == null) {
          color = pixels[lineIndex];
        } else {
          final int c = pixels[lineIndex];
          final boolean isTransparent = (c == 0);
          color = isTransparent ? background[lineIndex] : c;
        }

        graphics.drawPixels(x, y, 1, color, Surface.PAINT_MODE);
        lineIndex++;
      }

      index += width;
    }
  }
  public void setCursorPosition(int x, int y) {
    try {
      // x,y corresponds to the location of the cursor's hotspot on the
      // screen
      // it can be anywhere in the screen area (but some part of the
      // cursor might not be visible)
      x = Math.min(Math.max(x, 0), graphics.getWidth() - 1);
      y = Math.min(Math.max(y, 0), graphics.getHeight() - 1);

      if ((cursorArea.getX() != x) || (cursorArea.getY() != y)) {
        hideCursor();

        if (cursorImage != null) {
          int newX = (int) (x - cursorImage.getHotSpotX());
          int newY = (int) (y - cursorImage.getHotSpotY());
          cursorArea.setLocation(newX, newY);
        } else {
          cursorArea.setLocation(x, y);
        }

        showCursor();
      }
    } catch (Throwable t) {
      Unsafe.debugStackTrace("error in setCursorPosition", t);
    }
  }
  public void setCursorImage(HardwareCursor cursor) {
    if (cursor == null) {
      return;
    }

    try {
      final HardwareCursorImage cursImage = cursor.getImage(20, 20);

      if ((cursImage != null) && (this.cursorImage != cursImage)) {
        hideCursor();

        cursorArea.setSize(cursImage.getWidth(), cursImage.getHeight());
        if (cursorImage != null) {
          int newX =
              (int) (cursorArea.getX() + cursorImage.getHotSpotX() - cursImage.getHotSpotX());
          int newY =
              (int) (cursorArea.getY() + cursorImage.getHotSpotY() - cursImage.getHotSpotY());
          cursorArea.setLocation(newX, newY);
        }
        this.cursorImage = cursImage;

        showCursor();
      }
    } catch (Throwable t) {
      Unsafe.debugStackTrace("error in setCursorImage (" + t.getClass().getName() + ")", t);
    }
  }
  public void setBitmapGraphics(BitmapGraphics graphics) {
    if (this.graphics != graphics) {
      hideCursor();

      this.graphics = graphics;
      if (cursorImage != null) {
        int newHotspotX =
            (int) Math.min(graphics.getWidth() - 1, cursorArea.getX() + cursorImage.getHotSpotX());
        int newHotspotY =
            (int) Math.min(graphics.getHeight() - 1, cursorArea.getY() + cursorImage.getHotSpotY());
        cursorArea.setLocation(
            newHotspotX - cursorImage.getHotSpotX(), newHotspotY - cursorImage.getHotSpotY());
      }

      // TODO test when screen resolution is changing
      showCursor();
    }
  }
  private void showCursor() {
    if (cursorImage != null) {
      if (screenBackup == null) {
        screenBackup = new int[cursorImage.getWidth() * cursorImage.getHeight()];
      }

      // screenBackup = graphics.doGetPixels(cursorArea);
      final int cursorX = (int) cursorArea.getX();
      final int cursorY = (int) cursorArea.getY();
      final int maxY = Math.min(cursorY + cursorImage.getHeight(), graphics.getHeight());
      final int maxX = Math.min(cursorX + cursorImage.getWidth(), graphics.getWidth());
      final int width = cursorImage.getWidth();

      int index = 0;
      for (int y = cursorY; y < maxY; y++) {
        int lineIndex = index;
        for (int x = cursorX; x < maxX; x++) {
          screenBackup[lineIndex] = graphics.doGetPixel(x, y);
          lineIndex++;
        }

        index += width;
      }

      putPixels(cursorImage.getImage(), screenBackup);
    }
  }