Example #1
0
// We call this to see if we have a new cursor and should notify clients to do an update
// Or if cursor has moved
void rfbCheckForCursorChange() {
    CGPoint cursorLoc = currentCursorLoc();

    //rfbLog("Check For Cursor Change");
    // First Let's see if we have new info on the pasteboard - if so we'll send an update to each client
    if (lastCursorSeed != CGSCurrentCursorSeed() || !CGPointEqualToPoint(lastCursorPosition, cursorLoc)) {
        rfbClientIteratorPtr iterator = rfbGetClientIterator();
        rfbClientPtr cl;

        // Record first in case another change occurs after notifying clients
        lastCursorSeed = CGSCurrentCursorSeed();
        lastCursorPosition = cursorLoc;

        // Notify each client
        while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
            if (rfbShouldSendNewCursor(cl) || (rfbShouldSendNewPosition(cl)))
                pthread_cond_signal(&cl->updateCond);
        }
        rfbReleaseClientIterator(iterator);
    }
}
Example #2
0
File: mac.c Project: Mettbrot/vlc
int screen_DrawCursor( demux_sys_t *p_sys, CGPoint *cursor_pos )
{
    int size;
    int tmp1, tmp2, tmp3, tmp4;
    unsigned char *cursor_image;

    screen_data_t *p_data = p_sys->p_data;

    int seed = CGSCurrentCursorSeed();
    if( seed != p_data->cursor_seed )
    {
        p_data->cursor_need_update = 1;

        if( CGSGetGlobalCursorDataSize( p_data->connection, &size )
            != kCGErrorSuccess)
        {
            return VLC_EGENERIC;
        }

        cursor_image = ( unsigned char * )malloc( size );

        if( CGSGetGlobalCursorData( p_data->connection,
                                    cursor_image, &size,
                                    &tmp1,
                                    &p_data->cursor_rect, &p_data->cursor_hot,
                                    &tmp2, &tmp3, &tmp4 )
            != kCGErrorSuccess )
        {
            free( cursor_image );

            return VLC_EGENERIC;
        }

        long int pot_width, pot_height;

        POT( pot_width, p_data->cursor_rect.size.width );
        POT( pot_height, p_data->cursor_rect.size.height );

        p_data->cursor_texture_map_u =
            p_data->cursor_rect.size.width / ( double )pot_width;
        p_data->cursor_texture_map_v =
            p_data->cursor_rect.size.height / ( double )pot_height;

        /* We need transparent image larger than original,
         * use calloc to clear alpha value to 0. */
        char *pot_cursor_image = ( char * )calloc( pot_width * pot_height * 4, sizeof( char ) );
        int width, height;
        char *from, *to;

        width = p_data->cursor_rect.size.width;
        height = p_data->cursor_rect.size.height;

        from = ( char * )cursor_image;
        to = pot_cursor_image;

#ifdef __LITTLE_ENDIAN__
        int y, fromwidth, towidth;

        fromwidth = width * 4;
        towidth = pot_width * 4;

        for( y = height; y; y -- )
        {
            memcpy( to, from, fromwidth );
            to += towidth;
            from += fromwidth;
        }
#else
        int x, y, diff;
        diff = ( pot_width - width ) * 4;
        for( y = height; y; y -- )
        {
            for( x = width; x; x -- )
            {
                to[0] = from[3];
                to[1] = from[2];
                to[2] = from[1];
                to[3] = from[0];

                to += 4;
                from += 4;
            }

            to += diff;
        }
#endif

        glEnable( GL_TEXTURE_2D );
        glBindTexture( GL_TEXTURE_2D, p_data->cursor_texture );
        glTexImage2D( GL_TEXTURE_2D, 0,
                      GL_RGBA8,
                      pot_width, pot_height, 0,
                      GL_RGBA, GL_UNSIGNED_BYTE,
                      pot_cursor_image );

        p_data->cursor_need_update = 0;
        p_data->cursor_seed = seed;

        free( pot_cursor_image );
        free( cursor_image );
    }
    else if( p_data->cursor_need_update )
    {
        return VLC_EGENERIC;
    }

    double x, y;
    double x1, y1, x2, y2;

    x = cursor_pos->x - p_sys->i_left - p_data->cursor_hot.x;
    y = cursor_pos->y - p_sys->i_top - p_data->cursor_hot.y;

    x1 = 2.0 * x / p_data->width - 1.0;
    y1 = 2.0 * y / p_data->height - 1.0;
    x2 = 2.0 * ( x + p_data->cursor_rect.size.width ) / p_data->width - 1.0;
    y2 = 2.0 * ( y + p_data->cursor_rect.size.height ) / p_data->height - 1.0;

    glColor3f( 1.0f, 1.0f, 1.0f );
    glEnable( GL_TEXTURE_2D );
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glBindTexture( GL_TEXTURE_2D, p_data->cursor_texture );
    glBegin( GL_POLYGON );
    glTexCoord2f( 0.0, 0.0 );
    glVertex2f( x1, y1 );
    glTexCoord2f( p_data->cursor_texture_map_u, 0.0 );
    glVertex2f( x2, y1 );
    glTexCoord2f( p_data->cursor_texture_map_u, p_data->cursor_texture_map_v );
    glVertex2f( x2, y2 );
    glTexCoord2f( 0.0, p_data->cursor_texture_map_v );
    glVertex2f( x1, y2 );
    glEnd();
    glDisable( GL_BLEND );
    glDisable( GL_TEXTURE_2D );

    return VLC_SUCCESS;
}
Example #3
0
Bool rfbSendRichCursorUpdate(rfbClientPtr cl) {
    rfbFramebufferUpdateRectHeader rect;
    rfbPixelFormat cursorFormat;
    unsigned char *cursorData;
    int bufferMaskOffset;
    int cursorSize; // Size of cursor data from size
    int cursorRowBytes;
    int cursorDataSize; // Size to be sent to client
    int cursorMaskSize; // Mask Size to be sent to client
    int cursorDepth;
    int cursorBitsPerComponent;
    BOOL cursorIsDifferentFormat = FALSE;

    CGError err;
    CGSConnectionRef connection = getConnection();
    int components; // Cursor Components

    CGPoint hotspot;
    CGRect cursorRect;

    //rfbLog("Sending Cursor To Client");
    //GetCursorInfo();
    
	if (!connection) {
		if (!maxFailsRemaining)
			cl->useRichCursorEncoding = FALSE;		
		return FALSE;
	}
	
    if (CGSGetGlobalCursorDataSize(connection, &cursorDataSize) != kCGErrorSuccess) {
        rfbLog("Error obtaining cursor data - cursor not sent\n");
        return FALSE;
    }

    cursorData = (unsigned char*)malloc(sizeof(unsigned char) * cursorDataSize);
    err = CGSGetGlobalCursorData(connection,
                                 cursorData,
                                 &cursorDataSize,
                                 &cursorRowBytes,
                                 &cursorRect,
                                 &hotspot,
                                 &cursorDepth,
                                 &components,
                                 &cursorBitsPerComponent);

    //CGSReleaseConnection(connection);
    if (err != kCGErrorSuccess) {
        rfbLog("Error obtaining cursor data - cursor not sent\n");
        return FALSE;
    }

	
	if (cursorRect.size.height > 128 || cursorRect.size.width > 128) {
		// Wow That's one big cursor! We don't handle cursors this big 
		// (they are probably cursors with lots of states and that doesn't work so good for VNC.
		// For now just ignore them
		cl->currentCursorSeed = CGSCurrentCursorSeed();
		return FALSE;
	}
	
    // For This We Don't send location just the cursor shape (and Hot Spot)
    cursorFormat.depth = (cursorDepth == 32 ? 24 : cursorDepth);
    cursorFormat.bitsPerPixel = cursorDepth;
    cursorFormat.bigEndian = TRUE;
    cursorFormat.trueColour = TRUE;
    cursorFormat.redMax = cursorFormat.greenMax = cursorFormat.blueMax = (unsigned short) ((1<<cursorBitsPerComponent) - 1);
	cursorFormat.bigEndian = !littleEndian;
	cursorFormat.redShift   = (unsigned char) (cursorBitsPerComponent * 2);
	cursorFormat.greenShift = (unsigned char) (cursorBitsPerComponent * 1);
	cursorFormat.blueShift  = (unsigned char) (cursorBitsPerComponent * 0);
		
	//GetCursorInfo();
    //PrintPixelFormat(&cursorFormat);
    cursorIsDifferentFormat = !(PF_EQ(cursorFormat,rfbServerFormat));
    
    cursorSize = (cursorRect.size.width * cursorRect.size.height * (cl->format.bitsPerPixel / 8));
    cursorMaskSize = floor((cursorRect.size.width+7)/8) * cursorRect.size.height;

    // Make Sure we have space on the buffer (otherwise push the data out now)

    if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + cursorSize + cursorMaskSize > UPDATE_BUF_SIZE) {
        if (!rfbSendUpdateBuf(cl))
            return FALSE;
    }

    // Send The Header
    rect.r.x = Swap16IfLE((short) hotspot.x);
    rect.r.y = Swap16IfLE((short) hotspot.y);
    rect.r.w = Swap16IfLE((short) cursorRect.size.width);
    rect.r.h = Swap16IfLE((short) cursorRect.size.height);
    rect.encoding = Swap32IfLE(rfbEncodingRichCursor);

    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;

    // Apple Cursors can use a full Alpha channel.
    // Since we can only send a bit mask - to get closer we will compose the full color with a white
    // This requires us to jump ahead to write in the update buffer
    bufferMaskOffset = cl->ublen + cursorSize;

    // For starters we'll set mask to OFF (transparent) everywhere)
    memset(&cl->updateBuf[bufferMaskOffset], 0, cursorMaskSize);
    // This algorithm assumes the Alpha channel is the first component
    {
        unsigned char *cursorRowData = cursorData;
        unsigned char *cursorColumnData = cursorData;
        unsigned int cursorBytesPerPixel = (cursorDepth/8);
        unsigned char mask = 0;
		unsigned int alphaShift = (8 - cursorBitsPerComponent);
        unsigned char fullOn = (0xFF) >> alphaShift;
        unsigned char alphaThreshold = (0x60) >> alphaShift; // Only include the pixel if it's coverage is greater than this
        int dataX, dataY, componentIndex;

        for (dataY = 0; dataY < cursorRect.size.height; dataY++) {
            cursorColumnData = cursorRowData;
            for (dataX = 0; dataX < cursorRect.size.width; dataX++) {
				if (littleEndian)
					mask = (unsigned char)(*(cursorColumnData+(cursorBytesPerPixel-1))) >> alphaShift;
				else
					mask = (unsigned char)(*cursorColumnData) >> alphaShift;
                if (mask > alphaThreshold) {
                    // Write the Bit For The Mask to be ON (opaque)
                    cl->updateBuf[bufferMaskOffset+(dataX/8)] |= (0x0080 >> (dataX % 8));
                    // Composite Alpha into the cursors other channels - only for 32 bit
                    if (cursorDepth == 32 && mask != fullOn) {
                        for (componentIndex = 0; componentIndex < components; componentIndex++) {
                            *cursorColumnData = (unsigned char) (fullOn - mask + ((*cursorColumnData * mask)/fullOn)) & 0xFF;
                            cursorColumnData++;
                        }
                    }
                    else
                        cursorColumnData += cursorBytesPerPixel;
                }
                else
                    cursorColumnData += cursorBytesPerPixel;
            }
Example #4
0
Bool rfbShouldSendNewCursor(rfbClientPtr cl) {
    if (!cl->useRichCursorEncoding)
        return FALSE;
    else
        return (cl->currentCursorSeed != CGSCurrentCursorSeed());
}