Almost implement XVnc

This commit is contained in:
khanhduytran0
2020-05-03 20:27:54 +07:00
parent 626f273f8d
commit f72660fa5a
117 changed files with 16007 additions and 22 deletions

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -55,6 +55,12 @@
android:screenOrientation="sensorLandscape"
android:name=".prefs.LauncherPreferenceActivity"
android:configChanges="keyboardHidden|orientation|screenSize"/>
<!-- VNC Activity -->
<activity
android:screenOrientation="sensorLandscape"
android:name="android.androidVNC.VncCanvasActivity"
android:configChanges="keyboardHidden|orientation|screenSize"/>
</application>
</manifest>

View File

@@ -0,0 +1,171 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import java.io.IOException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.widget.ImageView;
/**
* Abstract interface between the VncCanvas and the bitmap and pixel data buffers that actually contain
* the data.
* This allows for implementations that use smaller bitmaps or buffers to save memory.
* @author Michael A. MacDonald
*
*/
abstract class AbstractBitmapData {
int framebufferwidth;
int framebufferheight;
int bitmapwidth;
int bitmapheight;
RfbProto rfb;
Bitmap mbitmap;
int bitmapPixels[];
Canvas memGraphics;
boolean waitingForInput;
VncCanvas vncCanvas;
private AbstractBitmapDrawable drawable;
AbstractBitmapData( RfbProto p, VncCanvas c)
{
rfb=p;
vncCanvas = c;
framebufferwidth=rfb.framebufferWidth;
framebufferheight=rfb.framebufferHeight;
}
synchronized void doneWaiting()
{
waitingForInput=false;
}
final void invalidateMousePosition()
{
if (vncCanvas.connection.getUseLocalCursor())
{
if (drawable==null)
drawable = createDrawable();
drawable.setCursorRect(vncCanvas.mouseX,vncCanvas.mouseY);
vncCanvas.invalidate(drawable.cursorRect);
}
}
/**
*
* @return The smallest scale supported by the implementation; the scale at which
* the bitmap would be smaller than the screen
*/
float getMinimumScale()
{
double scale = 0.75;
int displayWidth = vncCanvas.getWidth();
int displayHeight = vncCanvas.getHeight();
for (; scale >= 0; scale -= 0.25)
{
if (scale * bitmapwidth < displayWidth || scale * bitmapheight < displayHeight)
break;
}
return (float)(scale + 0.25);
}
/**
* Send a request through the protocol to get the data for the currently held bitmap
* @param incremental True if we want incremental update; false for full update
*/
abstract void writeFullUpdateRequest( boolean incremental) throws IOException;
/**
* Determine if a rectangle in full-frame coordinates can be drawn in the existing buffer
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
* @return True if entire rectangle fits into current screen buffer, false otherwise
*/
abstract boolean validDraw( int x, int y, int w, int h);
/**
* Return an offset in the bitmapPixels array of a point in full-frame coordinates
* @param x
* @param y
* @return Offset in bitmapPixels array of color data for that point
*/
abstract int offset( int x, int y);
/**
* Update pixels in the bitmap with data from the bitmapPixels array, positioned
* in full-frame coordinates
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
*/
abstract void updateBitmap( int x, int y, int w, int h);
/**
* Create drawable appropriate for this data
* @return drawable
*/
abstract AbstractBitmapDrawable createDrawable();
/**
* Call in UI thread; tell ImageView we've changed
* @param v ImageView displaying bitmap data
*/
void updateView(ImageView v)
{
if (drawable==null)
drawable = createDrawable();
v.setImageDrawable(drawable);
v.invalidate();
}
/**
* Copy a rectangle from one part of the bitmap to another
* @param src Rectangle in full-frame coordinates to be copied
* @param dest Destination rectangle in full-frame coordinates
* @param paint Paint specifier
*/
abstract void copyRect( Rect src, Rect dest, Paint paint);
/**
* Draw a rectangle in the bitmap with coordinates given in full frame
* @param x Top left x
* @param y Top left y
* @param w width (pixels)
* @param h height (pixels)
* @param paint How to draw
*/
abstract void drawRect( int x, int y, int w, int h, Paint paint);
/**
* Scroll position has changed.
* <p>
* This method is called in the UI thread-- it updates internal status, but does
* not change the bitmap data or send a network request until syncScroll is called
* @param newx Position of left edge of visible part in full-frame coordinates
* @param newy Position of top edge of visible part in full-frame coordinates
*/
abstract void scrollChanged( int newx, int newy);
/**
* Sync scroll -- called from network thread; copies scroll changes from UI to network state
*/
abstract void syncScroll();
/**
* Release resources
*/
void dispose()
{
if ( mbitmap!=null )
mbitmap.recycle();
memGraphics = null;
bitmapPixels = null;
}
}

View File

@@ -0,0 +1,100 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.DrawableContainer;
/**
* @author Michael A. MacDonald
*
*/
public class AbstractBitmapDrawable extends DrawableContainer {
Rect cursorRect;
Rect clipRect;
AbstractBitmapData data;
static final Paint _defaultPaint;
static final Paint _whitePaint;
static final Paint _blackPaint;
static {
_defaultPaint = new Paint();
_whitePaint = new Paint();
_whitePaint.setColor(0xffffffff);
_blackPaint = new Paint();
_blackPaint.setColor(0xff000000);
}
AbstractBitmapDrawable(AbstractBitmapData data)
{
this.data = data;
cursorRect = new Rect();
clipRect = new Rect();
}
void draw(Canvas canvas, int xoff, int yoff)
{
canvas.drawBitmap(data.mbitmap, xoff, yoff, _defaultPaint);
if(data.vncCanvas.connection.getUseLocalCursor())
{
setCursorRect(data.vncCanvas.mouseX, data.vncCanvas.mouseY);
clipRect.set(cursorRect);
if (canvas.clipRect(cursorRect))
{
drawCursor(canvas);
}
}
}
void drawCursor(Canvas canvas)
{
canvas.drawRect(cursorRect,_whitePaint);
canvas.drawRect((float)cursorRect.left + 1, (float)cursorRect.top + 1, (float)cursorRect.right - 1, (float)cursorRect.bottom - 1, _blackPaint);
}
void setCursorRect(int mouseX, int mouseY)
{
cursorRect.left = mouseX - 2;
cursorRect.right = cursorRect.left + 4;
cursorRect.top = mouseY - 2;
cursorRect.bottom = cursorRect.top + 4;
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#getIntrinsicHeight()
*/
@Override
public int getIntrinsicHeight() {
return data.framebufferheight;
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#getIntrinsicWidth()
*/
@Override
public int getIntrinsicWidth() {
return data.framebufferwidth;
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#getOpacity()
*/
@Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#isStateful()
*/
@Override
public boolean isStateful() {
return false;
}
}

View File

@@ -0,0 +1,305 @@
// This class was generated from android.androidVNC.IConnectionBean by a tool
// Do not edit this file directly! PLX THX
package android.androidVNC;
public abstract class AbstractConnectionBean extends com.antlersoft.android.dbimpl.IdImplementationBase implements IConnectionBean {
public static final String GEN_TABLE_NAME = "CONNECTION_BEAN";
public static final int GEN_COUNT = 21;
// Field constants
public static final String GEN_FIELD__ID = "_id";
public static final int GEN_ID__ID = 0;
public static final String GEN_FIELD_NICKNAME = "NICKNAME";
public static final int GEN_ID_NICKNAME = 1;
public static final String GEN_FIELD_ADDRESS = "ADDRESS";
public static final int GEN_ID_ADDRESS = 2;
public static final String GEN_FIELD_PORT = "PORT";
public static final int GEN_ID_PORT = 3;
public static final String GEN_FIELD_PASSWORD = "PASSWORD";
public static final int GEN_ID_PASSWORD = 4;
public static final String GEN_FIELD_COLORMODEL = "COLORMODEL";
public static final int GEN_ID_COLORMODEL = 5;
public static final String GEN_FIELD_FORCEFULL = "FORCEFULL";
public static final int GEN_ID_FORCEFULL = 6;
public static final String GEN_FIELD_REPEATERID = "REPEATERID";
public static final int GEN_ID_REPEATERID = 7;
public static final String GEN_FIELD_INPUTMODE = "INPUTMODE";
public static final int GEN_ID_INPUTMODE = 8;
public static final String GEN_FIELD_SCALEMODE = "SCALEMODE";
public static final int GEN_ID_SCALEMODE = 9;
public static final String GEN_FIELD_USELOCALCURSOR = "USELOCALCURSOR";
public static final int GEN_ID_USELOCALCURSOR = 10;
public static final String GEN_FIELD_KEEPPASSWORD = "KEEPPASSWORD";
public static final int GEN_ID_KEEPPASSWORD = 11;
public static final String GEN_FIELD_FOLLOWMOUSE = "FOLLOWMOUSE";
public static final int GEN_ID_FOLLOWMOUSE = 12;
public static final String GEN_FIELD_USEREPEATER = "USEREPEATER";
public static final int GEN_ID_USEREPEATER = 13;
public static final String GEN_FIELD_METALISTID = "METALISTID";
public static final int GEN_ID_METALISTID = 14;
public static final String GEN_FIELD_LAST_META_KEY_ID = "LAST_META_KEY_ID";
public static final int GEN_ID_LAST_META_KEY_ID = 15;
public static final String GEN_FIELD_FOLLOWPAN = "FOLLOWPAN";
public static final int GEN_ID_FOLLOWPAN = 16;
public static final String GEN_FIELD_USERNAME = "USERNAME";
public static final int GEN_ID_USERNAME = 17;
public static final String GEN_FIELD_SECURECONNECTIONTYPE = "SECURECONNECTIONTYPE";
public static final int GEN_ID_SECURECONNECTIONTYPE = 18;
public static final String GEN_FIELD_SHOWZOOMBUTTONS = "SHOWZOOMBUTTONS";
public static final int GEN_ID_SHOWZOOMBUTTONS = 19;
public static final String GEN_FIELD_DOUBLE_TAP_ACTION = "DOUBLE_TAP_ACTION";
public static final int GEN_ID_DOUBLE_TAP_ACTION = 20;
// SQL Command for creating the table
public static String GEN_CREATE = "CREATE TABLE CONNECTION_BEAN (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"NICKNAME TEXT," +
"ADDRESS TEXT," +
"PORT INTEGER," +
"PASSWORD TEXT," +
"COLORMODEL TEXT," +
"FORCEFULL INTEGER," +
"REPEATERID TEXT," +
"INPUTMODE TEXT," +
"SCALEMODE TEXT," +
"USELOCALCURSOR INTEGER," +
"KEEPPASSWORD INTEGER," +
"FOLLOWMOUSE INTEGER," +
"USEREPEATER INTEGER," +
"METALISTID INTEGER," +
"LAST_META_KEY_ID INTEGER," +
"FOLLOWPAN INTEGER DEFAULT 0," +
"USERNAME TEXT," +
"SECURECONNECTIONTYPE TEXT," +
"SHOWZOOMBUTTONS INTEGER DEFAULT 1," +
"DOUBLE_TAP_ACTION TEXT" +
")";
// Members corresponding to defined fields
private long gen__Id;
private java.lang.String gen_nickname;
private java.lang.String gen_address;
private int gen_port;
private java.lang.String gen_password;
private java.lang.String gen_colorModel;
private long gen_forceFull;
private java.lang.String gen_repeaterId;
private java.lang.String gen_inputMode;
private java.lang.String gen_SCALEMODE;
private boolean gen_useLocalCursor;
private boolean gen_keepPassword;
private boolean gen_followMouse;
private boolean gen_useRepeater;
private long gen_metaListId;
private long gen_LAST_META_KEY_ID;
private boolean gen_followPan;
private java.lang.String gen_userName;
private java.lang.String gen_secureConnectionType;
private boolean gen_showZoomButtons;
private java.lang.String gen_DOUBLE_TAP_ACTION;
public String Gen_tableName() { return GEN_TABLE_NAME; }
// Field accessors
public long get_Id() { return gen__Id; }
public void set_Id(long arg__Id) { gen__Id = arg__Id; }
public java.lang.String getNickname() { return gen_nickname; }
public void setNickname(java.lang.String arg_nickname) { gen_nickname = arg_nickname; }
public java.lang.String getAddress() { return gen_address; }
public void setAddress(java.lang.String arg_address) { gen_address = arg_address; }
public int getPort() { return gen_port; }
public void setPort(int arg_port) { gen_port = arg_port; }
public java.lang.String getPassword() { return gen_password; }
public void setPassword(java.lang.String arg_password) { gen_password = arg_password; }
public java.lang.String getColorModel() { return gen_colorModel; }
public void setColorModel(java.lang.String arg_colorModel) { gen_colorModel = arg_colorModel; }
public long getForceFull() { return gen_forceFull; }
public void setForceFull(long arg_forceFull) { gen_forceFull = arg_forceFull; }
public java.lang.String getRepeaterId() { return gen_repeaterId; }
public void setRepeaterId(java.lang.String arg_repeaterId) { gen_repeaterId = arg_repeaterId; }
public java.lang.String getInputMode() { return gen_inputMode; }
public void setInputMode(java.lang.String arg_inputMode) { gen_inputMode = arg_inputMode; }
public java.lang.String getScaleModeAsString() { return gen_SCALEMODE; }
public void setScaleModeAsString(java.lang.String arg_SCALEMODE) { gen_SCALEMODE = arg_SCALEMODE; }
public boolean getUseLocalCursor() { return gen_useLocalCursor; }
public void setUseLocalCursor(boolean arg_useLocalCursor) { gen_useLocalCursor = arg_useLocalCursor; }
public boolean getKeepPassword() { return gen_keepPassword; }
public void setKeepPassword(boolean arg_keepPassword) { gen_keepPassword = arg_keepPassword; }
public boolean getFollowMouse() { return gen_followMouse; }
public void setFollowMouse(boolean arg_followMouse) { gen_followMouse = arg_followMouse; }
public boolean getUseRepeater() { return gen_useRepeater; }
public void setUseRepeater(boolean arg_useRepeater) { gen_useRepeater = arg_useRepeater; }
public long getMetaListId() { return gen_metaListId; }
public void setMetaListId(long arg_metaListId) { gen_metaListId = arg_metaListId; }
public long getLastMetaKeyId() { return gen_LAST_META_KEY_ID; }
public void setLastMetaKeyId(long arg_LAST_META_KEY_ID) { gen_LAST_META_KEY_ID = arg_LAST_META_KEY_ID; }
public boolean getFollowPan() { return gen_followPan; }
public void setFollowPan(boolean arg_followPan) { gen_followPan = arg_followPan; }
public java.lang.String getUserName() { return gen_userName; }
public void setUserName(java.lang.String arg_userName) { gen_userName = arg_userName; }
public java.lang.String getSecureConnectionType() { return gen_secureConnectionType; }
public void setSecureConnectionType(java.lang.String arg_secureConnectionType) { gen_secureConnectionType = arg_secureConnectionType; }
public boolean getShowZoomButtons() { return gen_showZoomButtons; }
public void setShowZoomButtons(boolean arg_showZoomButtons) { gen_showZoomButtons = arg_showZoomButtons; }
public java.lang.String getDoubleTapActionAsString() { return gen_DOUBLE_TAP_ACTION; }
public void setDoubleTapActionAsString(java.lang.String arg_DOUBLE_TAP_ACTION) { gen_DOUBLE_TAP_ACTION = arg_DOUBLE_TAP_ACTION; }
public android.content.ContentValues Gen_getValues() {
android.content.ContentValues values=new android.content.ContentValues();
values.put(GEN_FIELD__ID,Long.toString(this.gen__Id));
values.put(GEN_FIELD_NICKNAME,this.gen_nickname);
values.put(GEN_FIELD_ADDRESS,this.gen_address);
values.put(GEN_FIELD_PORT,Integer.toString(this.gen_port));
values.put(GEN_FIELD_PASSWORD,this.gen_password);
values.put(GEN_FIELD_COLORMODEL,this.gen_colorModel);
values.put(GEN_FIELD_FORCEFULL,Long.toString(this.gen_forceFull));
values.put(GEN_FIELD_REPEATERID,this.gen_repeaterId);
values.put(GEN_FIELD_INPUTMODE,this.gen_inputMode);
values.put(GEN_FIELD_SCALEMODE,this.gen_SCALEMODE);
values.put(GEN_FIELD_USELOCALCURSOR,(this.gen_useLocalCursor ? "1" : "0"));
values.put(GEN_FIELD_KEEPPASSWORD,(this.gen_keepPassword ? "1" : "0"));
values.put(GEN_FIELD_FOLLOWMOUSE,(this.gen_followMouse ? "1" : "0"));
values.put(GEN_FIELD_USEREPEATER,(this.gen_useRepeater ? "1" : "0"));
values.put(GEN_FIELD_METALISTID,Long.toString(this.gen_metaListId));
values.put(GEN_FIELD_LAST_META_KEY_ID,Long.toString(this.gen_LAST_META_KEY_ID));
values.put(GEN_FIELD_FOLLOWPAN,(this.gen_followPan ? "1" : "0"));
values.put(GEN_FIELD_USERNAME,this.gen_userName);
values.put(GEN_FIELD_SECURECONNECTIONTYPE,this.gen_secureConnectionType);
values.put(GEN_FIELD_SHOWZOOMBUTTONS,(this.gen_showZoomButtons ? "1" : "0"));
values.put(GEN_FIELD_DOUBLE_TAP_ACTION,this.gen_DOUBLE_TAP_ACTION);
return values;
}
/**
* Return an array that gives the column index in the cursor for each field defined
* @param cursor Database cursor over some columns, possibly including this table
* @return array of column indices; -1 if the column with that id is not in cursor
*/
public int[] Gen_columnIndices(android.database.Cursor cursor) {
int[] result=new int[GEN_COUNT];
result[0] = cursor.getColumnIndex(GEN_FIELD__ID);
// Make compatible with database generated by older version of plugin with uppercase column name
if (result[0] == -1) {
result[0] = cursor.getColumnIndex("_ID");
}
result[1] = cursor.getColumnIndex(GEN_FIELD_NICKNAME);
result[2] = cursor.getColumnIndex(GEN_FIELD_ADDRESS);
result[3] = cursor.getColumnIndex(GEN_FIELD_PORT);
result[4] = cursor.getColumnIndex(GEN_FIELD_PASSWORD);
result[5] = cursor.getColumnIndex(GEN_FIELD_COLORMODEL);
result[6] = cursor.getColumnIndex(GEN_FIELD_FORCEFULL);
result[7] = cursor.getColumnIndex(GEN_FIELD_REPEATERID);
result[8] = cursor.getColumnIndex(GEN_FIELD_INPUTMODE);
result[9] = cursor.getColumnIndex(GEN_FIELD_SCALEMODE);
result[10] = cursor.getColumnIndex(GEN_FIELD_USELOCALCURSOR);
result[11] = cursor.getColumnIndex(GEN_FIELD_KEEPPASSWORD);
result[12] = cursor.getColumnIndex(GEN_FIELD_FOLLOWMOUSE);
result[13] = cursor.getColumnIndex(GEN_FIELD_USEREPEATER);
result[14] = cursor.getColumnIndex(GEN_FIELD_METALISTID);
result[15] = cursor.getColumnIndex(GEN_FIELD_LAST_META_KEY_ID);
result[16] = cursor.getColumnIndex(GEN_FIELD_FOLLOWPAN);
result[17] = cursor.getColumnIndex(GEN_FIELD_USERNAME);
result[18] = cursor.getColumnIndex(GEN_FIELD_SECURECONNECTIONTYPE);
result[19] = cursor.getColumnIndex(GEN_FIELD_SHOWZOOMBUTTONS);
result[20] = cursor.getColumnIndex(GEN_FIELD_DOUBLE_TAP_ACTION);
return result;
}
/**
* Populate one instance from a cursor
*/
public void Gen_populate(android.database.Cursor cursor,int[] columnIndices) {
if ( columnIndices[GEN_ID__ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID__ID])) {
gen__Id = cursor.getLong(columnIndices[GEN_ID__ID]);
}
if ( columnIndices[GEN_ID_NICKNAME] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_NICKNAME])) {
gen_nickname = cursor.getString(columnIndices[GEN_ID_NICKNAME]);
}
if ( columnIndices[GEN_ID_ADDRESS] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_ADDRESS])) {
gen_address = cursor.getString(columnIndices[GEN_ID_ADDRESS]);
}
if ( columnIndices[GEN_ID_PORT] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_PORT])) {
gen_port = (int)cursor.getInt(columnIndices[GEN_ID_PORT]);
}
if ( columnIndices[GEN_ID_PASSWORD] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_PASSWORD])) {
gen_password = cursor.getString(columnIndices[GEN_ID_PASSWORD]);
}
if ( columnIndices[GEN_ID_COLORMODEL] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_COLORMODEL])) {
gen_colorModel = cursor.getString(columnIndices[GEN_ID_COLORMODEL]);
}
if ( columnIndices[GEN_ID_FORCEFULL] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_FORCEFULL])) {
gen_forceFull = cursor.getLong(columnIndices[GEN_ID_FORCEFULL]);
}
if ( columnIndices[GEN_ID_REPEATERID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_REPEATERID])) {
gen_repeaterId = cursor.getString(columnIndices[GEN_ID_REPEATERID]);
}
if ( columnIndices[GEN_ID_INPUTMODE] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_INPUTMODE])) {
gen_inputMode = cursor.getString(columnIndices[GEN_ID_INPUTMODE]);
}
if ( columnIndices[GEN_ID_SCALEMODE] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_SCALEMODE])) {
gen_SCALEMODE = cursor.getString(columnIndices[GEN_ID_SCALEMODE]);
}
if ( columnIndices[GEN_ID_USELOCALCURSOR] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_USELOCALCURSOR])) {
gen_useLocalCursor = (cursor.getInt(columnIndices[GEN_ID_USELOCALCURSOR]) != 0);
}
if ( columnIndices[GEN_ID_KEEPPASSWORD] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_KEEPPASSWORD])) {
gen_keepPassword = (cursor.getInt(columnIndices[GEN_ID_KEEPPASSWORD]) != 0);
}
if ( columnIndices[GEN_ID_FOLLOWMOUSE] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_FOLLOWMOUSE])) {
gen_followMouse = (cursor.getInt(columnIndices[GEN_ID_FOLLOWMOUSE]) != 0);
}
if ( columnIndices[GEN_ID_USEREPEATER] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_USEREPEATER])) {
gen_useRepeater = (cursor.getInt(columnIndices[GEN_ID_USEREPEATER]) != 0);
}
if ( columnIndices[GEN_ID_METALISTID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_METALISTID])) {
gen_metaListId = cursor.getLong(columnIndices[GEN_ID_METALISTID]);
}
if ( columnIndices[GEN_ID_LAST_META_KEY_ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_LAST_META_KEY_ID])) {
gen_LAST_META_KEY_ID = cursor.getLong(columnIndices[GEN_ID_LAST_META_KEY_ID]);
}
if ( columnIndices[GEN_ID_FOLLOWPAN] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_FOLLOWPAN])) {
gen_followPan = (cursor.getInt(columnIndices[GEN_ID_FOLLOWPAN]) != 0);
}
if ( columnIndices[GEN_ID_USERNAME] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_USERNAME])) {
gen_userName = cursor.getString(columnIndices[GEN_ID_USERNAME]);
}
if ( columnIndices[GEN_ID_SECURECONNECTIONTYPE] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_SECURECONNECTIONTYPE])) {
gen_secureConnectionType = cursor.getString(columnIndices[GEN_ID_SECURECONNECTIONTYPE]);
}
if ( columnIndices[GEN_ID_SHOWZOOMBUTTONS] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_SHOWZOOMBUTTONS])) {
gen_showZoomButtons = (cursor.getInt(columnIndices[GEN_ID_SHOWZOOMBUTTONS]) != 0);
}
if ( columnIndices[GEN_ID_DOUBLE_TAP_ACTION] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_DOUBLE_TAP_ACTION])) {
gen_DOUBLE_TAP_ACTION = cursor.getString(columnIndices[GEN_ID_DOUBLE_TAP_ACTION]);
}
}
/**
* Populate one instance from a ContentValues
*/
public void Gen_populate(android.content.ContentValues values) {
gen__Id = values.getAsLong(GEN_FIELD__ID);
gen_nickname = values.getAsString(GEN_FIELD_NICKNAME);
gen_address = values.getAsString(GEN_FIELD_ADDRESS);
gen_port = (int)values.getAsInteger(GEN_FIELD_PORT);
gen_password = values.getAsString(GEN_FIELD_PASSWORD);
gen_colorModel = values.getAsString(GEN_FIELD_COLORMODEL);
gen_forceFull = values.getAsLong(GEN_FIELD_FORCEFULL);
gen_repeaterId = values.getAsString(GEN_FIELD_REPEATERID);
gen_inputMode = values.getAsString(GEN_FIELD_INPUTMODE);
gen_SCALEMODE = values.getAsString(GEN_FIELD_SCALEMODE);
gen_useLocalCursor = (values.getAsInteger(GEN_FIELD_USELOCALCURSOR) != 0);
gen_keepPassword = (values.getAsInteger(GEN_FIELD_KEEPPASSWORD) != 0);
gen_followMouse = (values.getAsInteger(GEN_FIELD_FOLLOWMOUSE) != 0);
gen_useRepeater = (values.getAsInteger(GEN_FIELD_USEREPEATER) != 0);
gen_metaListId = values.getAsLong(GEN_FIELD_METALISTID);
gen_LAST_META_KEY_ID = values.getAsLong(GEN_FIELD_LAST_META_KEY_ID);
gen_followPan = (values.getAsInteger(GEN_FIELD_FOLLOWPAN) != 0);
gen_userName = values.getAsString(GEN_FIELD_USERNAME);
gen_secureConnectionType = values.getAsString(GEN_FIELD_SECURECONNECTIONTYPE);
gen_showZoomButtons = (values.getAsInteger(GEN_FIELD_SHOWZOOMBUTTONS) != 0);
gen_DOUBLE_TAP_ACTION = values.getAsString(GEN_FIELD_DOUBLE_TAP_ACTION);
}
}

View File

@@ -0,0 +1,92 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.view.GestureDetector;
import android.view.MotionEvent;
import com.antlersoft.android.bc.BCFactory;
import com.antlersoft.android.bc.IBCScaleGestureDetector;
import com.antlersoft.android.bc.OnScaleGestureListener;
/**
* An AbstractInputHandler that uses GestureDetector to detect standard gestures in touch events
*
* @author Michael A. MacDonald
*/
abstract class AbstractGestureInputHandler extends GestureDetector.SimpleOnGestureListener implements AbstractInputHandler, OnScaleGestureListener {
protected GestureDetector gestures;
protected IBCScaleGestureDetector scaleGestures;
private VncCanvasActivity activity;
float xInitialFocus;
float yInitialFocus;
boolean inScaling;
private static final String TAG = "AbstractGestureInputHandler";
AbstractGestureInputHandler(VncCanvasActivity c)
{
activity = c;
gestures=BCFactory.getInstance().getBCGestureDetector().createGestureDetector(c, this);
gestures.setOnDoubleTapListener(this);
scaleGestures=BCFactory.getInstance().getScaleGestureDetector(c, this);
}
@Override
public boolean onTouchEvent(MotionEvent evt) {
scaleGestures.onTouchEvent(evt);
return gestures.onTouchEvent(evt);
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.OnScaleGestureListener#onScale(com.antlersoft.android.bc.IBCScaleGestureDetector)
*/
@Override
public boolean onScale(IBCScaleGestureDetector detector) {
boolean consumed = true;
//if (detector.)
//Log.i(TAG,"Focus("+detector.getFocusX()+","+detector.getFocusY()+") scaleFactor = "+detector.getScaleFactor());
// Calculate focus shift
float fx = detector.getFocusX();
float fy = detector.getFocusY();
double xfs = fx - xInitialFocus;
double yfs = fy - yInitialFocus;
double fs = Math.sqrt(xfs * xfs + yfs * yfs);
if (Math.abs(1.0 - detector.getScaleFactor())<0.02)
consumed = false;
if (fs * 2< Math.abs(detector.getCurrentSpan() - detector.getPreviousSpan()))
{
inScaling = true;
if (consumed)
{
//Log.i(TAG,"Adjust scaling "+detector.getScaleFactor());
if (activity.vncCanvas != null && activity.vncCanvas.scaling != null)
activity.vncCanvas.scaling.adjust(activity, detector.getScaleFactor(), fx, fy);
}
}
return consumed;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.OnScaleGestureListener#onScaleBegin(com.antlersoft.android.bc.IBCScaleGestureDetector)
*/
@Override
public boolean onScaleBegin(IBCScaleGestureDetector detector) {
xInitialFocus = detector.getFocusX();
yInitialFocus = detector.getFocusY();
inScaling = false;
//Log.i(TAG,"scale begin ("+xInitialFocus+","+yInitialFocus+")");
return true;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.OnScaleGestureListener#onScaleEnd(com.antlersoft.android.bc.IBCScaleGestureDetector)
*/
@Override
public void onScaleEnd(IBCScaleGestureDetector detector) {
//Log.i(TAG,"scale end");
inScaling = false;
}
}

View File

@@ -0,0 +1,54 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.view.KeyEvent;
import android.view.MotionEvent;
/**
* The VncCanvasActivity has several different ways of handling input from the touchscreen,
* keyboard, buttons and trackball. These will be represented by different implementations
* of this interface. Putting the different modes in different classes
* will keep the logic clean. The relevant Activity callbacks in VncCanvasActivity
* are forwarded to methods in AbstractInputHandler.
* <p>
* It is expected that the implementations will be contained within
* VncCanvasActivity, so they can do things like super.VncCanvasActivity.onXXX to invoke
* default behavior.
* @author Michael A. MacDonald
*
*/
interface AbstractInputHandler {
/**
* Note: Menu key code is handled before this is called
* @see android.app.Activity#onKeyDown(int keyCode, KeyEvent evt)
*/
boolean onKeyDown(int keyCode, KeyEvent evt);
/**
* Note: Menu key code is handled before this is called
* @see android.app.Activity#onKeyUp(int keyCode, KeyEvent evt)
*/
boolean onKeyUp(int keyCode, KeyEvent evt);
/* (non-Javadoc)
* @see android.app.Activity#onTrackballEvent(android.view.MotionEvent)
*/
boolean onTrackballEvent( MotionEvent evt);
/* (non-Javadoc)
* @see android.app.Activity#onTrackballEvent(android.view.MotionEvent)
*/
boolean onTouchEvent( MotionEvent evt);
/**
* Return a user-friendly description for this mode; it will be displayed in a toaster
* when changing modes.
* @return
*/
CharSequence getHandlerDescription();
/**
* Return an internal name for this handler; this name will be stable across language
* and version changes
*/
String getName();
}

View File

@@ -0,0 +1,149 @@
// This class was generated from android.androidVNC.IMetaKey by a tool
// Do not edit this file directly! PLX THX
package android.androidVNC;
public abstract class AbstractMetaKeyBean extends com.antlersoft.android.dbimpl.IdImplementationBase implements IMetaKey {
public static final String GEN_TABLE_NAME = "META_KEY";
public static final int GEN_COUNT = 8;
// Field constants
public static final String GEN_FIELD__ID = "_id";
public static final int GEN_ID__ID = 0;
public static final String GEN_FIELD_METALISTID = "METALISTID";
public static final int GEN_ID_METALISTID = 1;
public static final String GEN_FIELD_KEYDESC = "KEYDESC";
public static final int GEN_ID_KEYDESC = 2;
public static final String GEN_FIELD_METAFLAGS = "METAFLAGS";
public static final int GEN_ID_METAFLAGS = 3;
public static final String GEN_FIELD_MOUSECLICK = "MOUSECLICK";
public static final int GEN_ID_MOUSECLICK = 4;
public static final String GEN_FIELD_MOUSEBUTTONS = "MOUSEBUTTONS";
public static final int GEN_ID_MOUSEBUTTONS = 5;
public static final String GEN_FIELD_KEYSYM = "KEYSYM";
public static final int GEN_ID_KEYSYM = 6;
public static final String GEN_FIELD_SHORTCUT = "SHORTCUT";
public static final int GEN_ID_SHORTCUT = 7;
// SQL Command for creating the table
public static String GEN_CREATE = "CREATE TABLE META_KEY (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"METALISTID INTEGER," +
"KEYDESC TEXT," +
"METAFLAGS INTEGER," +
"MOUSECLICK INTEGER," +
"MOUSEBUTTONS INTEGER," +
"KEYSYM INTEGER," +
"SHORTCUT TEXT" +
")";
// Members corresponding to defined fields
private long gen__Id;
private long gen_metaListId;
private java.lang.String gen_keyDesc;
private int gen_metaFlags;
private boolean gen_mouseClick;
private int gen_mouseButtons;
private int gen_keySym;
private java.lang.String gen_shortcut;
public String Gen_tableName() { return GEN_TABLE_NAME; }
// Field accessors
public long get_Id() { return gen__Id; }
public void set_Id(long arg__Id) { gen__Id = arg__Id; }
public long getMetaListId() { return gen_metaListId; }
public void setMetaListId(long arg_metaListId) { gen_metaListId = arg_metaListId; }
public java.lang.String getKeyDesc() { return gen_keyDesc; }
public void setKeyDesc(java.lang.String arg_keyDesc) { gen_keyDesc = arg_keyDesc; }
public int getMetaFlags() { return gen_metaFlags; }
public void setMetaFlags(int arg_metaFlags) { gen_metaFlags = arg_metaFlags; }
public boolean isMouseClick() { return gen_mouseClick; }
public void setMouseClick(boolean arg_mouseClick) { gen_mouseClick = arg_mouseClick; }
public int getMouseButtons() { return gen_mouseButtons; }
public void setMouseButtons(int arg_mouseButtons) { gen_mouseButtons = arg_mouseButtons; }
public int getKeySym() { return gen_keySym; }
public void setKeySym(int arg_keySym) { gen_keySym = arg_keySym; }
public java.lang.String getShortcut() { return gen_shortcut; }
public void setShortcut(java.lang.String arg_shortcut) { gen_shortcut = arg_shortcut; }
public android.content.ContentValues Gen_getValues() {
android.content.ContentValues values=new android.content.ContentValues();
values.put(GEN_FIELD__ID,Long.toString(this.gen__Id));
values.put(GEN_FIELD_METALISTID,Long.toString(this.gen_metaListId));
values.put(GEN_FIELD_KEYDESC,this.gen_keyDesc);
values.put(GEN_FIELD_METAFLAGS,Integer.toString(this.gen_metaFlags));
values.put(GEN_FIELD_MOUSECLICK,(this.gen_mouseClick ? "1" : "0"));
values.put(GEN_FIELD_MOUSEBUTTONS,Integer.toString(this.gen_mouseButtons));
values.put(GEN_FIELD_KEYSYM,Integer.toString(this.gen_keySym));
values.put(GEN_FIELD_SHORTCUT,this.gen_shortcut);
return values;
}
/**
* Return an array that gives the column index in the cursor for each field defined
* @param cursor Database cursor over some columns, possibly including this table
* @return array of column indices; -1 if the column with that id is not in cursor
*/
public int[] Gen_columnIndices(android.database.Cursor cursor) {
int[] result=new int[GEN_COUNT];
result[0] = cursor.getColumnIndex(GEN_FIELD__ID);
// Make compatible with database generated by older version of plugin with uppercase column name
if (result[0] == -1) {
result[0] = cursor.getColumnIndex("_ID");
}
result[1] = cursor.getColumnIndex(GEN_FIELD_METALISTID);
result[2] = cursor.getColumnIndex(GEN_FIELD_KEYDESC);
result[3] = cursor.getColumnIndex(GEN_FIELD_METAFLAGS);
result[4] = cursor.getColumnIndex(GEN_FIELD_MOUSECLICK);
result[5] = cursor.getColumnIndex(GEN_FIELD_MOUSEBUTTONS);
result[6] = cursor.getColumnIndex(GEN_FIELD_KEYSYM);
result[7] = cursor.getColumnIndex(GEN_FIELD_SHORTCUT);
return result;
}
/**
* Populate one instance from a cursor
*/
public void Gen_populate(android.database.Cursor cursor,int[] columnIndices) {
if ( columnIndices[GEN_ID__ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID__ID])) {
gen__Id = cursor.getLong(columnIndices[GEN_ID__ID]);
}
if ( columnIndices[GEN_ID_METALISTID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_METALISTID])) {
gen_metaListId = cursor.getLong(columnIndices[GEN_ID_METALISTID]);
}
if ( columnIndices[GEN_ID_KEYDESC] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_KEYDESC])) {
gen_keyDesc = cursor.getString(columnIndices[GEN_ID_KEYDESC]);
}
if ( columnIndices[GEN_ID_METAFLAGS] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_METAFLAGS])) {
gen_metaFlags = (int)cursor.getInt(columnIndices[GEN_ID_METAFLAGS]);
}
if ( columnIndices[GEN_ID_MOUSECLICK] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_MOUSECLICK])) {
gen_mouseClick = (cursor.getInt(columnIndices[GEN_ID_MOUSECLICK]) != 0);
}
if ( columnIndices[GEN_ID_MOUSEBUTTONS] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_MOUSEBUTTONS])) {
gen_mouseButtons = (int)cursor.getInt(columnIndices[GEN_ID_MOUSEBUTTONS]);
}
if ( columnIndices[GEN_ID_KEYSYM] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_KEYSYM])) {
gen_keySym = (int)cursor.getInt(columnIndices[GEN_ID_KEYSYM]);
}
if ( columnIndices[GEN_ID_SHORTCUT] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_SHORTCUT])) {
gen_shortcut = cursor.getString(columnIndices[GEN_ID_SHORTCUT]);
}
}
/**
* Populate one instance from a ContentValues
*/
public void Gen_populate(android.content.ContentValues values) {
gen__Id = values.getAsLong(GEN_FIELD__ID);
gen_metaListId = values.getAsLong(GEN_FIELD_METALISTID);
gen_keyDesc = values.getAsString(GEN_FIELD_KEYDESC);
gen_metaFlags = (int)values.getAsInteger(GEN_FIELD_METAFLAGS);
gen_mouseClick = (values.getAsInteger(GEN_FIELD_MOUSECLICK) != 0);
gen_mouseButtons = (int)values.getAsInteger(GEN_FIELD_MOUSEBUTTONS);
gen_keySym = (int)values.getAsInteger(GEN_FIELD_KEYSYM);
gen_shortcut = values.getAsString(GEN_FIELD_SHORTCUT);
}
}

View File

@@ -0,0 +1,129 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.widget.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*
* A scaling mode for the VncCanvas; based on ImageView.ScaleType
*/
abstract class AbstractScaling {
private static final int scaleModeIds[] = { R.id.itemFitToScreen, R.id.itemOneToOne, R.id.itemZoomable };
private static AbstractScaling[] scalings;
static AbstractScaling getById(int id)
{
if ( scalings==null)
{
scalings=new AbstractScaling[scaleModeIds.length];
}
for ( int i=0; i<scaleModeIds.length; ++i)
{
if ( scaleModeIds[i]==id)
{
if ( scalings[i]==null)
{
switch ( id )
{
case R.id.itemFitToScreen :
scalings[i]=new FitToScreenScaling();
break;
case R.id.itemOneToOne :
scalings[i]=new OneToOneScaling();
break;
case R.id.itemZoomable :
scalings[i]=new ZoomScaling();
break;
}
}
return scalings[i];
}
}
throw new IllegalArgumentException("Unknown scaling id " + id);
}
float getScale() { return 1; }
void zoomIn(VncCanvasActivity activity) {}
void zoomOut(VncCanvasActivity activity) {}
static AbstractScaling getByScaleType(ImageView.ScaleType scaleType)
{
for (int i : scaleModeIds)
{
AbstractScaling s = getById(i);
if (s.scaleType==scaleType)
return s;
}
throw new IllegalArgumentException("Unsupported scale type: "+ scaleType.toString());
}
private int id;
protected ImageView.ScaleType scaleType;
protected AbstractScaling(int id, ImageView.ScaleType scaleType)
{
this.id = id;
this.scaleType = scaleType;
}
/**
*
* @return Id corresponding to menu item that sets this scale type
*/
int getId()
{
return id;
}
/**
* Sets the activity's scale type to the scaling
* @param activity
*/
void setScaleTypeForActivity(VncCanvasActivity activity)
{
activity.zoomer.hide();
activity.vncCanvas.scaling = this;
activity.vncCanvas.setScaleType(scaleType);
activity.getConnection().setScaleMode(scaleType);
if (activity.inputHandler == null || ! isValidInputMode(activity.getModeIdFromHandler(activity.inputHandler))) {
activity.inputHandler=activity.getInputHandlerById(getDefaultHandlerId());
activity.getConnection().setInputMode(activity.inputHandler.getName());
}
activity.getConnection().Gen_update(activity.database.getWritableDatabase());
activity.updateInputMenu();
}
abstract int getDefaultHandlerId();
/**
* True if this scale type allows panning of the image
* @return
*/
abstract boolean isAbleToPan();
/**
* True if the listed input mode is valid for this scaling mode
* @param mode Id of the input mode
* @return True if the input mode is compatible with the scaling mode
*/
abstract boolean isValidInputMode(int mode);
/**
* Change the scaling and focus dynamically, as from a detected scale gesture
* @param activity Activity containing to canvas to scale
* @param scaleFactor Factor by which to adjust scaling
* @param fx Focus X of center of scale change
* @param fy Focus Y of center of scale change
*/
void adjust(VncCanvasActivity activity, float scaleFactor, float fx, float fy)
{
}
}

View File

@@ -0,0 +1,7 @@
package android.androidVNC;
class BitmapImplHint {
static final long AUTO = 0L;
static final long FULL = 1L;
static final long TILE = 2L;
}

View File

@@ -0,0 +1,89 @@
package android.androidVNC;
import java.io.IOException;
public enum COLORMODEL {
C24bit, C256, C64, C8, C4, C2;
public int bpp() {
switch (this) {
case C24bit:
return 4;
default:
return 1;
}
}
public int[] palette() {
switch (this) {
case C24bit:
return null;
case C256:
return ColorModel256.colors;
case C64:
return ColorModel64.colors;
case C8:
return ColorModel8.colors;
case C4:
return ColorModel64.colors;
case C2:
return ColorModel8.colors;
default:
return ColorModel256.colors;
}
}
public String nameString()
{
return super.toString();
}
public void setPixelFormat(RfbProto rfb) throws IOException {
switch (this) {
case C24bit:
// 24-bit color
rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0, false);
break;
case C256:
rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6, false);
break;
case C64:
rfb.writeSetPixelFormat(8, 6, false, true, 3, 3, 3, 4, 2, 0, false);
break;
case C8:
rfb.writeSetPixelFormat(8, 3, false, true, 1, 1, 1, 2, 1, 0, false);
break;
case C4:
// Greyscale
rfb.writeSetPixelFormat(8, 6, false, true, 3, 3, 3, 4, 2, 0, true);
break;
case C2:
// B&W
rfb.writeSetPixelFormat(8, 3, false, true, 1, 1, 1, 2, 1, 0, true);
break;
default:
// Default is 256 colors
rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6, false);
break;
}
}
public String toString() {
switch (this) {
case C24bit:
return "24-bit color (4 bpp)";
case C256:
return "256 colors (1 bpp)";
case C64:
return "64 colors (1 bpp)";
case C8:
return "8 colors (1 bpp)";
case C4:
return "Greyscale (1 bpp)";
case C2:
return "Black & White (1 bpp)";
default:
return "256 colors (1 bpp)";
}
}
}

View File

@@ -0,0 +1,88 @@
//
// Copyright (C) 2003 Constantin Kaplinsky. All Rights Reserved.
//
// This 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.
//
// This software 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 this software; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
//
// CapabilityInfo.java - A class to hold information about a
// particular capability as used in the RFB protocol 3.130.
//
package android.androidVNC;
class CapabilityInfo {
// Public methods
public CapabilityInfo(int code,
String vendorSignature,
String nameSignature,
String description) {
this.code = code;
this.vendorSignature = vendorSignature;
this.nameSignature = nameSignature;
this.description = description;
enabled = false;
}
public CapabilityInfo(int code,
byte[] vendorSignature,
byte[] nameSignature) {
this.code = code;
this.vendorSignature = new String(vendorSignature);
this.nameSignature = new String(nameSignature);
this.description = null;
enabled = false;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
public boolean isEnabled() {
return enabled;
}
public void enable() {
enabled = true;
}
public boolean equals(CapabilityInfo other) {
return (other != null && this.code == other.code &&
this.vendorSignature.equals(other.vendorSignature) &&
this.nameSignature.equals(other.nameSignature));
}
public boolean enableIfEquals(CapabilityInfo other) {
if (this.equals(other))
enable();
return isEnabled();
}
// Protected data
protected int code;
protected String vendorSignature;
protected String nameSignature;
protected String description;
protected boolean enabled;
}

View File

@@ -0,0 +1,104 @@
//
// Copyright (C) 2003 Constantin Kaplinsky. All Rights Reserved.
//
// This 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.
//
// This software 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 this software; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
//
// CapsContainer.java - A container of capabilities as used in the RFB
// protocol 3.130
//
package android.androidVNC;
import java.util.Vector;
import java.util.Hashtable;
class CapsContainer {
// Public methods
public CapsContainer() {
infoMap = new Hashtable<Integer, CapabilityInfo>(64, (float)0.25);
orderedList = new Vector<Integer>(32, 8);
}
public void add(CapabilityInfo capinfo) {
Integer key = new Integer(capinfo.getCode());
infoMap.put(key, capinfo);
}
public void add(int code, String vendor, String name, String desc) {
Integer key = new Integer(code);
infoMap.put(key, new CapabilityInfo(code, vendor, name, desc));
}
public boolean isKnown(int code) {
return infoMap.containsKey(new Integer(code));
}
public CapabilityInfo getInfo(int code) {
return (CapabilityInfo)infoMap.get(new Integer(code));
}
public String getDescription(int code) {
CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(new Integer(code));
if (capinfo == null)
return null;
return capinfo.getDescription();
}
public boolean enable(CapabilityInfo other) {
Integer key = new Integer(other.getCode());
CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(key);
if (capinfo == null)
return false;
boolean enabled = capinfo.enableIfEquals(other);
if (enabled)
orderedList.addElement(key);
return enabled;
}
public boolean isEnabled(int code) {
CapabilityInfo capinfo = (CapabilityInfo)infoMap.get(new Integer(code));
if (capinfo == null)
return false;
return capinfo.isEnabled();
}
public int numEnabled() {
return orderedList.size();
}
public int getByOrder(int idx) {
int code;
try {
code = ((Integer)orderedList.elementAt(idx)).intValue();
} catch (ArrayIndexOutOfBoundsException e) {
code = 0;
}
return code;
}
// Protected data
protected Hashtable<Integer, CapabilityInfo> infoMap;
protected Vector<Integer> orderedList;
}

View File

@@ -0,0 +1,266 @@
package android.androidVNC;
public class ColorModel256 {
public final static int [] colors;
static {
colors = new int[256];
colors[0]=0xff000000;
colors[1]=0xff240000;
colors[2]=0xff490000;
colors[3]=0xff6d0000;
colors[4]=0xff920000;
colors[5]=0xffb60000;
colors[6]=0xffdb0000;
colors[7]=0xffff0000;
colors[8]=0xff002400;
colors[9]=0xff242400;
colors[10]=0xff492400;
colors[11]=0xff6d2400;
colors[12]=0xff922400;
colors[13]=0xffb62400;
colors[14]=0xffdb2400;
colors[15]=0xffff2400;
colors[16]=0xff004900;
colors[17]=0xff244900;
colors[18]=0xff494900;
colors[19]=0xff6d4900;
colors[20]=0xff924900;
colors[21]=0xffb64900;
colors[22]=0xffdb4900;
colors[23]=0xffff4900;
colors[24]=0xff006d00;
colors[25]=0xff246d00;
colors[26]=0xff496d00;
colors[27]=0xff6d6d00;
colors[28]=0xff926d00;
colors[29]=0xffb66d00;
colors[30]=0xffdb6d00;
colors[31]=0xffff6d00;
colors[32]=0xff009200;
colors[33]=0xff249200;
colors[34]=0xff499200;
colors[35]=0xff6d9200;
colors[36]=0xff929200;
colors[37]=0xffb69200;
colors[38]=0xffdb9200;
colors[39]=0xffff9200;
colors[40]=0xff00b600;
colors[41]=0xff24b600;
colors[42]=0xff49b600;
colors[43]=0xff6db600;
colors[44]=0xff92b600;
colors[45]=0xffb6b600;
colors[46]=0xffdbb600;
colors[47]=0xffffb600;
colors[48]=0xff00db00;
colors[49]=0xff24db00;
colors[50]=0xff49db00;
colors[51]=0xff6ddb00;
colors[52]=0xff92db00;
colors[53]=0xffb6db00;
colors[54]=0xffdbdb00;
colors[55]=0xffffdb00;
colors[56]=0xff00ff00;
colors[57]=0xff24ff00;
colors[58]=0xff49ff00;
colors[59]=0xff6dff00;
colors[60]=0xff92ff00;
colors[61]=0xffb6ff00;
colors[62]=0xffdbff00;
colors[63]=0xffffff00;
colors[64]=0xff000055;
colors[65]=0xff240055;
colors[66]=0xff490055;
colors[67]=0xff6d0055;
colors[68]=0xff920055;
colors[69]=0xffb60055;
colors[70]=0xffdb0055;
colors[71]=0xffff0055;
colors[72]=0xff002455;
colors[73]=0xff242455;
colors[74]=0xff492455;
colors[75]=0xff6d2455;
colors[76]=0xff922455;
colors[77]=0xffb62455;
colors[78]=0xffdb2455;
colors[79]=0xffff2455;
colors[80]=0xff004955;
colors[81]=0xff244955;
colors[82]=0xff494955;
colors[83]=0xff6d4955;
colors[84]=0xff924955;
colors[85]=0xffb64955;
colors[86]=0xffdb4955;
colors[87]=0xffff4955;
colors[88]=0xff006d55;
colors[89]=0xff246d55;
colors[90]=0xff496d55;
colors[91]=0xff6d6d55;
colors[92]=0xff926d55;
colors[93]=0xffb66d55;
colors[94]=0xffdb6d55;
colors[95]=0xffff6d55;
colors[96]=0xff009255;
colors[97]=0xff249255;
colors[98]=0xff499255;
colors[99]=0xff6d9255;
colors[100]=0xff929255;
colors[101]=0xffb69255;
colors[102]=0xffdb9255;
colors[103]=0xffff9255;
colors[104]=0xff00b655;
colors[105]=0xff24b655;
colors[106]=0xff49b655;
colors[107]=0xff6db655;
colors[108]=0xff92b655;
colors[109]=0xffb6b655;
colors[110]=0xffdbb655;
colors[111]=0xffffb655;
colors[112]=0xff00db55;
colors[113]=0xff24db55;
colors[114]=0xff49db55;
colors[115]=0xff6ddb55;
colors[116]=0xff92db55;
colors[117]=0xffb6db55;
colors[118]=0xffdbdb55;
colors[119]=0xffffdb55;
colors[120]=0xff00ff55;
colors[121]=0xff24ff55;
colors[122]=0xff49ff55;
colors[123]=0xff6dff55;
colors[124]=0xff92ff55;
colors[125]=0xffb6ff55;
colors[126]=0xffdbff55;
colors[127]=0xffffff55;
colors[128]=0xff0000aa;
colors[129]=0xff2400aa;
colors[130]=0xff4900aa;
colors[131]=0xff6d00aa;
colors[132]=0xff9200aa;
colors[133]=0xffb600aa;
colors[134]=0xffdb00aa;
colors[135]=0xffff00aa;
colors[136]=0xff0024aa;
colors[137]=0xff2424aa;
colors[138]=0xff4924aa;
colors[139]=0xff6d24aa;
colors[140]=0xff9224aa;
colors[141]=0xffb624aa;
colors[142]=0xffdb24aa;
colors[143]=0xffff24aa;
colors[144]=0xff0049aa;
colors[145]=0xff2449aa;
colors[146]=0xff4949aa;
colors[147]=0xff6d49aa;
colors[148]=0xff9249aa;
colors[149]=0xffb649aa;
colors[150]=0xffdb49aa;
colors[151]=0xffff49aa;
colors[152]=0xff006daa;
colors[153]=0xff246daa;
colors[154]=0xff496daa;
colors[155]=0xff6d6daa;
colors[156]=0xff926daa;
colors[157]=0xffb66daa;
colors[158]=0xffdb6daa;
colors[159]=0xffff6daa;
colors[160]=0xff0092aa;
colors[161]=0xff2492aa;
colors[162]=0xff4992aa;
colors[163]=0xff6d92aa;
colors[164]=0xff9292aa;
colors[165]=0xffb692aa;
colors[166]=0xffdb92aa;
colors[167]=0xffff92aa;
colors[168]=0xff00b6aa;
colors[169]=0xff24b6aa;
colors[170]=0xff49b6aa;
colors[171]=0xff6db6aa;
colors[172]=0xff92b6aa;
colors[173]=0xffb6b6aa;
colors[174]=0xffdbb6aa;
colors[175]=0xffffb6aa;
colors[176]=0xff00dbaa;
colors[177]=0xff24dbaa;
colors[178]=0xff49dbaa;
colors[179]=0xff6ddbaa;
colors[180]=0xff92dbaa;
colors[181]=0xffb6dbaa;
colors[182]=0xffdbdbaa;
colors[183]=0xffffdbaa;
colors[184]=0xff00ffaa;
colors[185]=0xff24ffaa;
colors[186]=0xff49ffaa;
colors[187]=0xff6dffaa;
colors[188]=0xff92ffaa;
colors[189]=0xffb6ffaa;
colors[190]=0xffdbffaa;
colors[191]=0xffffffaa;
colors[192]=0xff0000ff;
colors[193]=0xff2400ff;
colors[194]=0xff4900ff;
colors[195]=0xff6d00ff;
colors[196]=0xff9200ff;
colors[197]=0xffb600ff;
colors[198]=0xffdb00ff;
colors[199]=0xffff00ff;
colors[200]=0xff0024ff;
colors[201]=0xff2424ff;
colors[202]=0xff4924ff;
colors[203]=0xff6d24ff;
colors[204]=0xff9224ff;
colors[205]=0xffb624ff;
colors[206]=0xffdb24ff;
colors[207]=0xffff24ff;
colors[208]=0xff0049ff;
colors[209]=0xff2449ff;
colors[210]=0xff4949ff;
colors[211]=0xff6d49ff;
colors[212]=0xff9249ff;
colors[213]=0xffb649ff;
colors[214]=0xffdb49ff;
colors[215]=0xffff49ff;
colors[216]=0xff006dff;
colors[217]=0xff246dff;
colors[218]=0xff496dff;
colors[219]=0xff6d6dff;
colors[220]=0xff926dff;
colors[221]=0xffb66dff;
colors[222]=0xffdb6dff;
colors[223]=0xffff6dff;
colors[224]=0xff0092ff;
colors[225]=0xff2492ff;
colors[226]=0xff4992ff;
colors[227]=0xff6d92ff;
colors[228]=0xff9292ff;
colors[229]=0xffb692ff;
colors[230]=0xffdb92ff;
colors[231]=0xffff92ff;
colors[232]=0xff00b6ff;
colors[233]=0xff24b6ff;
colors[234]=0xff49b6ff;
colors[235]=0xff6db6ff;
colors[236]=0xff92b6ff;
colors[237]=0xffb6b6ff;
colors[238]=0xffdbb6ff;
colors[239]=0xffffb6ff;
colors[240]=0xff00dbff;
colors[241]=0xff24dbff;
colors[242]=0xff49dbff;
colors[243]=0xff6ddbff;
colors[244]=0xff92dbff;
colors[245]=0xffb6dbff;
colors[246]=0xffdbdbff;
colors[247]=0xffffdbff;
colors[248]=0xff00ffff;
colors[249]=0xff24ffff;
colors[250]=0xff49ffff;
colors[251]=0xff6dffff;
colors[252]=0xff92ffff;
colors[253]=0xffb6ffff;
colors[254]=0xffdbffff;
colors[255]=0xffffffff;
}
}

View File

@@ -0,0 +1,267 @@
package android.androidVNC;
public class ColorModel64 {
public final static int [] colors;
static {
colors = new int[256];
colors[0]=0xff000000;
colors[1]=0xff000055;
colors[2]=0xff0000aa;
colors[3]=0xff0000ff;
colors[4]=0xff005500;
colors[5]=0xff005555;
colors[6]=0xff0055aa;
colors[7]=0xff0055ff;
colors[8]=0xff00aa00;
colors[9]=0xff00aa55;
colors[10]=0xff00aaaa;
colors[11]=0xff00aaff;
colors[12]=0xff00ff00;
colors[13]=0xff00ff55;
colors[14]=0xff00ffaa;
colors[15]=0xff00ffff;
colors[16]=0xff550000;
colors[17]=0xff550055;
colors[18]=0xff5500aa;
colors[19]=0xff5500ff;
colors[20]=0xff555500;
colors[21]=0xff555555;
colors[22]=0xff5555aa;
colors[23]=0xff5555ff;
colors[24]=0xff55aa00;
colors[25]=0xff55aa55;
colors[26]=0xff55aaaa;
colors[27]=0xff55aaff;
colors[28]=0xff55ff00;
colors[29]=0xff55ff55;
colors[30]=0xff55ffaa;
colors[31]=0xff55ffff;
colors[32]=0xffaa0000;
colors[33]=0xffaa0055;
colors[34]=0xffaa00aa;
colors[35]=0xffaa00ff;
colors[36]=0xffaa5500;
colors[37]=0xffaa5555;
colors[38]=0xffaa55aa;
colors[39]=0xffaa55ff;
colors[40]=0xffaaaa00;
colors[41]=0xffaaaa55;
colors[42]=0xffaaaaaa;
colors[43]=0xffaaaaff;
colors[44]=0xffaaff00;
colors[45]=0xffaaff55;
colors[46]=0xffaaffaa;
colors[47]=0xffaaffff;
colors[48]=0xffff0000;
colors[49]=0xffff0055;
colors[50]=0xffff00aa;
colors[51]=0xffff00ff;
colors[52]=0xffff5500;
colors[53]=0xffff5555;
colors[54]=0xffff55aa;
colors[55]=0xffff55ff;
colors[56]=0xffffaa00;
colors[57]=0xffffaa55;
colors[58]=0xffffaaaa;
colors[59]=0xffffaaff;
colors[60]=0xffffff00;
colors[61]=0xffffff55;
colors[62]=0xffffffaa;
colors[63]=0xffffffff;
colors[64]=0xff000000;
colors[65]=0xff000055;
colors[66]=0xff0000aa;
colors[67]=0xff0000ff;
colors[68]=0xff005500;
colors[69]=0xff005555;
colors[70]=0xff0055aa;
colors[71]=0xff0055ff;
colors[72]=0xff00aa00;
colors[73]=0xff00aa55;
colors[74]=0xff00aaaa;
colors[75]=0xff00aaff;
colors[76]=0xff00ff00;
colors[77]=0xff00ff55;
colors[78]=0xff00ffaa;
colors[79]=0xff00ffff;
colors[80]=0xff550000;
colors[81]=0xff550055;
colors[82]=0xff5500aa;
colors[83]=0xff5500ff;
colors[84]=0xff555500;
colors[85]=0xff555555;
colors[86]=0xff5555aa;
colors[87]=0xff5555ff;
colors[88]=0xff55aa00;
colors[89]=0xff55aa55;
colors[90]=0xff55aaaa;
colors[91]=0xff55aaff;
colors[92]=0xff55ff00;
colors[93]=0xff55ff55;
colors[94]=0xff55ffaa;
colors[95]=0xff55ffff;
colors[96]=0xffaa0000;
colors[97]=0xffaa0055;
colors[98]=0xffaa00aa;
colors[99]=0xffaa00ff;
colors[100]=0xffaa5500;
colors[101]=0xffaa5555;
colors[102]=0xffaa55aa;
colors[103]=0xffaa55ff;
colors[104]=0xffaaaa00;
colors[105]=0xffaaaa55;
colors[106]=0xffaaaaaa;
colors[107]=0xffaaaaff;
colors[108]=0xffaaff00;
colors[109]=0xffaaff55;
colors[110]=0xffaaffaa;
colors[111]=0xffaaffff;
colors[112]=0xffff0000;
colors[113]=0xffff0055;
colors[114]=0xffff00aa;
colors[115]=0xffff00ff;
colors[116]=0xffff5500;
colors[117]=0xffff5555;
colors[118]=0xffff55aa;
colors[119]=0xffff55ff;
colors[120]=0xffffaa00;
colors[121]=0xffffaa55;
colors[122]=0xffffaaaa;
colors[123]=0xffffaaff;
colors[124]=0xffffff00;
colors[125]=0xffffff55;
colors[126]=0xffffffaa;
colors[127]=0xffffffff;
colors[128]=0xff000000;
colors[129]=0xff000055;
colors[130]=0xff0000aa;
colors[131]=0xff0000ff;
colors[132]=0xff005500;
colors[133]=0xff005555;
colors[134]=0xff0055aa;
colors[135]=0xff0055ff;
colors[136]=0xff00aa00;
colors[137]=0xff00aa55;
colors[138]=0xff00aaaa;
colors[139]=0xff00aaff;
colors[140]=0xff00ff00;
colors[141]=0xff00ff55;
colors[142]=0xff00ffaa;
colors[143]=0xff00ffff;
colors[144]=0xff550000;
colors[145]=0xff550055;
colors[146]=0xff5500aa;
colors[147]=0xff5500ff;
colors[148]=0xff555500;
colors[149]=0xff555555;
colors[150]=0xff5555aa;
colors[151]=0xff5555ff;
colors[152]=0xff55aa00;
colors[153]=0xff55aa55;
colors[154]=0xff55aaaa;
colors[155]=0xff55aaff;
colors[156]=0xff55ff00;
colors[157]=0xff55ff55;
colors[158]=0xff55ffaa;
colors[159]=0xff55ffff;
colors[160]=0xffaa0000;
colors[161]=0xffaa0055;
colors[162]=0xffaa00aa;
colors[163]=0xffaa00ff;
colors[164]=0xffaa5500;
colors[165]=0xffaa5555;
colors[166]=0xffaa55aa;
colors[167]=0xffaa55ff;
colors[168]=0xffaaaa00;
colors[169]=0xffaaaa55;
colors[170]=0xffaaaaaa;
colors[171]=0xffaaaaff;
colors[172]=0xffaaff00;
colors[173]=0xffaaff55;
colors[174]=0xffaaffaa;
colors[175]=0xffaaffff;
colors[176]=0xffff0000;
colors[177]=0xffff0055;
colors[178]=0xffff00aa;
colors[179]=0xffff00ff;
colors[180]=0xffff5500;
colors[181]=0xffff5555;
colors[182]=0xffff55aa;
colors[183]=0xffff55ff;
colors[184]=0xffffaa00;
colors[185]=0xffffaa55;
colors[186]=0xffffaaaa;
colors[187]=0xffffaaff;
colors[188]=0xffffff00;
colors[189]=0xffffff55;
colors[190]=0xffffffaa;
colors[191]=0xffffffff;
colors[192]=0xff000000;
colors[193]=0xff000055;
colors[194]=0xff0000aa;
colors[195]=0xff0000ff;
colors[196]=0xff005500;
colors[197]=0xff005555;
colors[198]=0xff0055aa;
colors[199]=0xff0055ff;
colors[200]=0xff00aa00;
colors[201]=0xff00aa55;
colors[202]=0xff00aaaa;
colors[203]=0xff00aaff;
colors[204]=0xff00ff00;
colors[205]=0xff00ff55;
colors[206]=0xff00ffaa;
colors[207]=0xff00ffff;
colors[208]=0xff550000;
colors[209]=0xff550055;
colors[210]=0xff5500aa;
colors[211]=0xff5500ff;
colors[212]=0xff555500;
colors[213]=0xff555555;
colors[214]=0xff5555aa;
colors[215]=0xff5555ff;
colors[216]=0xff55aa00;
colors[217]=0xff55aa55;
colors[218]=0xff55aaaa;
colors[219]=0xff55aaff;
colors[220]=0xff55ff00;
colors[221]=0xff55ff55;
colors[222]=0xff55ffaa;
colors[223]=0xff55ffff;
colors[224]=0xffaa0000;
colors[225]=0xffaa0055;
colors[226]=0xffaa00aa;
colors[227]=0xffaa00ff;
colors[228]=0xffaa5500;
colors[229]=0xffaa5555;
colors[230]=0xffaa55aa;
colors[231]=0xffaa55ff;
colors[232]=0xffaaaa00;
colors[233]=0xffaaaa55;
colors[234]=0xffaaaaaa;
colors[235]=0xffaaaaff;
colors[236]=0xffaaff00;
colors[237]=0xffaaff55;
colors[238]=0xffaaffaa;
colors[239]=0xffaaffff;
colors[240]=0xffff0000;
colors[241]=0xffff0055;
colors[242]=0xffff00aa;
colors[243]=0xffff00ff;
colors[244]=0xffff5500;
colors[245]=0xffff5555;
colors[246]=0xffff55aa;
colors[247]=0xffff55ff;
colors[248]=0xffffaa00;
colors[249]=0xffffaa55;
colors[250]=0xffffaaaa;
colors[251]=0xffffaaff;
colors[252]=0xffffff00;
colors[253]=0xffffff55;
colors[254]=0xffffffaa;
colors[255]=0xffffffff;
}
}

View File

@@ -0,0 +1,266 @@
package android.androidVNC;
public class ColorModel8 {
public final static int [] colors;
static {
colors = new int[256];
colors[0]=0xff000000;
colors[1]=0xff0000ff;
colors[2]=0xff00ff00;
colors[3]=0xff00ffff;
colors[4]=0xffff0000;
colors[5]=0xffff00ff;
colors[6]=0xffffff00;
colors[7]=0xffffffff;
colors[8]=0xff000000;
colors[9]=0xff0000ff;
colors[10]=0xff00ff00;
colors[11]=0xff00ffff;
colors[12]=0xffff0000;
colors[13]=0xffff00ff;
colors[14]=0xffffff00;
colors[15]=0xffffffff;
colors[16]=0xff000000;
colors[17]=0xff0000ff;
colors[18]=0xff00ff00;
colors[19]=0xff00ffff;
colors[20]=0xffff0000;
colors[21]=0xffff00ff;
colors[22]=0xffffff00;
colors[23]=0xffffffff;
colors[24]=0xff000000;
colors[25]=0xff0000ff;
colors[26]=0xff00ff00;
colors[27]=0xff00ffff;
colors[28]=0xffff0000;
colors[29]=0xffff00ff;
colors[30]=0xffffff00;
colors[31]=0xffffffff;
colors[32]=0xff000000;
colors[33]=0xff0000ff;
colors[34]=0xff00ff00;
colors[35]=0xff00ffff;
colors[36]=0xffff0000;
colors[37]=0xffff00ff;
colors[38]=0xffffff00;
colors[39]=0xffffffff;
colors[40]=0xff000000;
colors[41]=0xff0000ff;
colors[42]=0xff00ff00;
colors[43]=0xff00ffff;
colors[44]=0xffff0000;
colors[45]=0xffff00ff;
colors[46]=0xffffff00;
colors[47]=0xffffffff;
colors[48]=0xff000000;
colors[49]=0xff0000ff;
colors[50]=0xff00ff00;
colors[51]=0xff00ffff;
colors[52]=0xffff0000;
colors[53]=0xffff00ff;
colors[54]=0xffffff00;
colors[55]=0xffffffff;
colors[56]=0xff000000;
colors[57]=0xff0000ff;
colors[58]=0xff00ff00;
colors[59]=0xff00ffff;
colors[60]=0xffff0000;
colors[61]=0xffff00ff;
colors[62]=0xffffff00;
colors[63]=0xffffffff;
colors[64]=0xff000000;
colors[65]=0xff0000ff;
colors[66]=0xff00ff00;
colors[67]=0xff00ffff;
colors[68]=0xffff0000;
colors[69]=0xffff00ff;
colors[70]=0xffffff00;
colors[71]=0xffffffff;
colors[72]=0xff000000;
colors[73]=0xff0000ff;
colors[74]=0xff00ff00;
colors[75]=0xff00ffff;
colors[76]=0xffff0000;
colors[77]=0xffff00ff;
colors[78]=0xffffff00;
colors[79]=0xffffffff;
colors[80]=0xff000000;
colors[81]=0xff0000ff;
colors[82]=0xff00ff00;
colors[83]=0xff00ffff;
colors[84]=0xffff0000;
colors[85]=0xffff00ff;
colors[86]=0xffffff00;
colors[87]=0xffffffff;
colors[88]=0xff000000;
colors[89]=0xff0000ff;
colors[90]=0xff00ff00;
colors[91]=0xff00ffff;
colors[92]=0xffff0000;
colors[93]=0xffff00ff;
colors[94]=0xffffff00;
colors[95]=0xffffffff;
colors[96]=0xff000000;
colors[97]=0xff0000ff;
colors[98]=0xff00ff00;
colors[99]=0xff00ffff;
colors[100]=0xffff0000;
colors[101]=0xffff00ff;
colors[102]=0xffffff00;
colors[103]=0xffffffff;
colors[104]=0xff000000;
colors[105]=0xff0000ff;
colors[106]=0xff00ff00;
colors[107]=0xff00ffff;
colors[108]=0xffff0000;
colors[109]=0xffff00ff;
colors[110]=0xffffff00;
colors[111]=0xffffffff;
colors[112]=0xff000000;
colors[113]=0xff0000ff;
colors[114]=0xff00ff00;
colors[115]=0xff00ffff;
colors[116]=0xffff0000;
colors[117]=0xffff00ff;
colors[118]=0xffffff00;
colors[119]=0xffffffff;
colors[120]=0xff000000;
colors[121]=0xff0000ff;
colors[122]=0xff00ff00;
colors[123]=0xff00ffff;
colors[124]=0xffff0000;
colors[125]=0xffff00ff;
colors[126]=0xffffff00;
colors[127]=0xffffffff;
colors[128]=0xff000000;
colors[129]=0xff0000ff;
colors[130]=0xff00ff00;
colors[131]=0xff00ffff;
colors[132]=0xffff0000;
colors[133]=0xffff00ff;
colors[134]=0xffffff00;
colors[135]=0xffffffff;
colors[136]=0xff000000;
colors[137]=0xff0000ff;
colors[138]=0xff00ff00;
colors[139]=0xff00ffff;
colors[140]=0xffff0000;
colors[141]=0xffff00ff;
colors[142]=0xffffff00;
colors[143]=0xffffffff;
colors[144]=0xff000000;
colors[145]=0xff0000ff;
colors[146]=0xff00ff00;
colors[147]=0xff00ffff;
colors[148]=0xffff0000;
colors[149]=0xffff00ff;
colors[150]=0xffffff00;
colors[151]=0xffffffff;
colors[152]=0xff000000;
colors[153]=0xff0000ff;
colors[154]=0xff00ff00;
colors[155]=0xff00ffff;
colors[156]=0xffff0000;
colors[157]=0xffff00ff;
colors[158]=0xffffff00;
colors[159]=0xffffffff;
colors[160]=0xff000000;
colors[161]=0xff0000ff;
colors[162]=0xff00ff00;
colors[163]=0xff00ffff;
colors[164]=0xffff0000;
colors[165]=0xffff00ff;
colors[166]=0xffffff00;
colors[167]=0xffffffff;
colors[168]=0xff000000;
colors[169]=0xff0000ff;
colors[170]=0xff00ff00;
colors[171]=0xff00ffff;
colors[172]=0xffff0000;
colors[173]=0xffff00ff;
colors[174]=0xffffff00;
colors[175]=0xffffffff;
colors[176]=0xff000000;
colors[177]=0xff0000ff;
colors[178]=0xff00ff00;
colors[179]=0xff00ffff;
colors[180]=0xffff0000;
colors[181]=0xffff00ff;
colors[182]=0xffffff00;
colors[183]=0xffffffff;
colors[184]=0xff000000;
colors[185]=0xff0000ff;
colors[186]=0xff00ff00;
colors[187]=0xff00ffff;
colors[188]=0xffff0000;
colors[189]=0xffff00ff;
colors[190]=0xffffff00;
colors[191]=0xffffffff;
colors[192]=0xff000000;
colors[193]=0xff0000ff;
colors[194]=0xff00ff00;
colors[195]=0xff00ffff;
colors[196]=0xffff0000;
colors[197]=0xffff00ff;
colors[198]=0xffffff00;
colors[199]=0xffffffff;
colors[200]=0xff000000;
colors[201]=0xff0000ff;
colors[202]=0xff00ff00;
colors[203]=0xff00ffff;
colors[204]=0xffff0000;
colors[205]=0xffff00ff;
colors[206]=0xffffff00;
colors[207]=0xffffffff;
colors[208]=0xff000000;
colors[209]=0xff0000ff;
colors[210]=0xff00ff00;
colors[211]=0xff00ffff;
colors[212]=0xffff0000;
colors[213]=0xffff00ff;
colors[214]=0xffffff00;
colors[215]=0xffffffff;
colors[216]=0xff000000;
colors[217]=0xff0000ff;
colors[218]=0xff00ff00;
colors[219]=0xff00ffff;
colors[220]=0xffff0000;
colors[221]=0xffff00ff;
colors[222]=0xffffff00;
colors[223]=0xffffffff;
colors[224]=0xff000000;
colors[225]=0xff0000ff;
colors[226]=0xff00ff00;
colors[227]=0xff00ffff;
colors[228]=0xffff0000;
colors[229]=0xffff00ff;
colors[230]=0xffffff00;
colors[231]=0xffffffff;
colors[232]=0xff000000;
colors[233]=0xff0000ff;
colors[234]=0xff00ff00;
colors[235]=0xff00ffff;
colors[236]=0xffff0000;
colors[237]=0xffff00ff;
colors[238]=0xffffff00;
colors[239]=0xffffffff;
colors[240]=0xff000000;
colors[241]=0xff0000ff;
colors[242]=0xff00ff00;
colors[243]=0xff00ffff;
colors[244]=0xffff0000;
colors[245]=0xffff00ff;
colors[246]=0xffffff00;
colors[247]=0xffffffff;
colors[248]=0xff000000;
colors[249]=0xff0000ff;
colors[250]=0xff00ff00;
colors[251]=0xff00ffff;
colors[252]=0xffff0000;
colors[253]=0xffff00ff;
colors[254]=0xffffff00;
colors[255]=0xffffffff;
}
}

View File

@@ -0,0 +1,107 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import java.io.IOException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
/**
* @author Michael A. MacDonald
*
*/
class CompactBitmapData extends AbstractBitmapData {
class CompactBitmapDrawable extends AbstractBitmapDrawable
{
CompactBitmapDrawable()
{
super(CompactBitmapData.this);
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#draw(android.graphics.Canvas)
*/
@Override
public void draw(Canvas canvas) {
draw(canvas, 0, 0);
}
}
CompactBitmapData(RfbProto rfb, VncCanvas c)
{
super(rfb,c);
bitmapwidth=framebufferwidth;
bitmapheight=framebufferheight;
mbitmap = Bitmap.createBitmap(rfb.framebufferWidth, rfb.framebufferHeight, Bitmap.Config.RGB_565);
memGraphics = new Canvas(mbitmap);
bitmapPixels = new int[rfb.framebufferWidth * rfb.framebufferHeight];
}
@Override
void writeFullUpdateRequest(boolean incremental) throws IOException {
rfb.writeFramebufferUpdateRequest(0, 0, framebufferwidth, framebufferheight, incremental);
}
@Override
boolean validDraw(int x, int y, int w, int h) {
return true;
}
@Override
int offset(int x, int y) {
return y * bitmapwidth + x;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#createDrawable()
*/
@Override
AbstractBitmapDrawable createDrawable() {
return new CompactBitmapDrawable();
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#updateBitmap(int, int, int, int)
*/
@Override
void updateBitmap(int x, int y, int w, int h) {
mbitmap.setPixels(bitmapPixels, offset(x,y), bitmapwidth, x, y, w, h);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#copyRect(android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
*/
@Override
void copyRect(Rect src, Rect dest, Paint paint) {
memGraphics.drawBitmap(mbitmap, src, dest, paint);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#drawRect(int, int, int, int, android.graphics.Paint)
*/
@Override
void drawRect(int x, int y, int w, int h, Paint paint) {
memGraphics.drawRect(x, y, x + w, y + h, paint);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#scrollChanged(int, int)
*/
@Override
void scrollChanged(int newx, int newy) {
// Don't need to do anything here
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#syncScroll()
*/
@Override
void syncScroll() {
// Don't need anything here either
}
}

View File

@@ -0,0 +1,89 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.widget.ImageView.ScaleType;
import com.antlersoft.android.dbimpl.NewInstance;
import java.lang.Comparable;
/**
* @author Michael A. MacDonald
*
*/
class ConnectionBean extends AbstractConnectionBean implements Comparable<ConnectionBean> {
static final NewInstance<ConnectionBean> newInstance=new NewInstance<ConnectionBean>() {
public ConnectionBean get() { return new ConnectionBean(); }
};
ConnectionBean()
{
set_Id(0);
setAddress("");
setPassword("");
setKeepPassword(true);
setNickname("");
setUserName("");
setPort(5900);
setColorModel(COLORMODEL.C64.nameString());
setScaleMode(ScaleType.MATRIX);
setInputMode(VncCanvasActivity.TOUCH_ZOOM_MODE);
setRepeaterId("");
setMetaListId(1);
}
boolean isNew()
{
return get_Id()== 0;
}
void save(SQLiteDatabase database) {
ContentValues values=Gen_getValues();
values.remove(GEN_FIELD__ID);
if ( ! getKeepPassword()) {
values.put(GEN_FIELD_PASSWORD, "");
}
if ( isNew()) {
set_Id(database.insert(GEN_TABLE_NAME, null, values));
} else {
database.update(GEN_TABLE_NAME, values, GEN_FIELD__ID + " = ?", new String[] { Long.toString(get_Id()) });
}
}
ScaleType getScaleMode()
{
return ScaleType.valueOf(getScaleModeAsString());
}
void setScaleMode(ScaleType value)
{
setScaleModeAsString(value.toString());
}
@Override
public String toString() {
if ( isNew())
{
return "New";
}
return getNickname()+":"+getAddress()+":"+getPort();
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(ConnectionBean another) {
int result = getNickname().compareTo(another.getNickname());
if (result == 0) {
result = getAddress().compareTo(another.getAddress());
if ( result == 0) {
result = getPort() - another.getPort();
}
}
return result;
}
}

View File

@@ -0,0 +1,120 @@
/*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*
* Copyright 2009,2010 Michael A. MacDonald
*/
package android.androidVNC;
import android.app.*;
import android.content.*;
import android.content.Intent.*;
import android.database.*;
import android.net.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*
*/
public class ConnectionListActivity extends ListActivity {
VncDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
database = new VncDatabase(this);
// Query for all people contacts using the Contacts.People convenience class.
// Put a managed wrapper around the retrieved cursor so we don't have to worry about
// requerying or closing it as the activity changes state.
Cursor mCursor = database.getReadableDatabase().query(ConnectionBean.GEN_TABLE_NAME, new String[] {
ConnectionBean.GEN_FIELD__ID,
ConnectionBean.GEN_FIELD_NICKNAME,
ConnectionBean.GEN_FIELD_USERNAME,
ConnectionBean.GEN_FIELD_ADDRESS,
ConnectionBean.GEN_FIELD_PORT,
ConnectionBean.GEN_FIELD_REPEATERID },
ConnectionBean.GEN_FIELD_KEEPPASSWORD + " <> 0", null, null, null, ConnectionBean.GEN_FIELD_NICKNAME);
startManagingCursor(mCursor);
// Now create a new list adapter bound to the cursor.
// SimpleListAdapter is designed for binding to a Cursor.
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this, // Context.
R.layout.connection_list,
mCursor, // Pass in the cursor to bind to.
new String[] {
ConnectionBean.GEN_FIELD_NICKNAME,
ConnectionBean.GEN_FIELD_ADDRESS,
ConnectionBean.GEN_FIELD_PORT,
ConnectionBean.GEN_FIELD_REPEATERID }, // Array of cursor columns to bind to.
new int[] {
R.id.list_text_nickname,
R.id.list_text_address,
R.id.list_text_port,
R.id.list_text_repeater
}); // Parallel array of which template objects to bind to those columns.
// Bind to our new adapter.
setListAdapter(adapter);
}
/* (non-Javadoc)
* @see android.app.ListActivity#onListItemClick(android.widget.ListView, android.view.View, int, long)
*/
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
ConnectionBean connection = new ConnectionBean();
if (connection.Gen_read(database.getReadableDatabase(), id))
{
// create shortcut if requested
ShortcutIconResource icon = Intent.ShortcutIconResource.fromContext(this, R.drawable.ic_xvnc);
Intent intent = new Intent();
Intent launchIntent = new Intent(this,VncCanvasActivity.class);
Uri.Builder builder = new Uri.Builder();
builder.authority(VncConstants.CONNECTION + ":" + connection.get_Id());
builder.scheme("vnc");
launchIntent.setData(builder.build());
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launchIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, connection.getNickname());
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
setResult(RESULT_OK, intent);
}
else
setResult(RESULT_CANCELED);
finish();
}
/* (non-Javadoc)
* @see android.app.Activity#onDestroy()
*/
@Override
protected void onDestroy() {
database.close();
super.onDestroy();
}
}

View File

@@ -0,0 +1,12 @@
/**
*
*/
package android.androidVNC;
/**
* @author mike
*
*/
interface ConnectionSettable {
void setConnection(ConnectionBean connection);
}

View File

@@ -0,0 +1,183 @@
package android.androidVNC;
// CRYPTO LIBRARY FOR EXCHANGING KEYS
// USING THE DIFFIE-HELLMAN KEY EXCHANGE PROTOCOL
// The diffie-hellman can be used to securely exchange keys
// between parties, where a third party eavesdropper given
// the values being transmitted cannot determine the key.
// Implemented by Lee Griffiths, Jan 2004.
// This software is freeware, you may use it to your discretion,
// however by doing so you take full responsibility for any damage
// it may cause.
// Hope you find it useful, even if you just use some of the functions
// out of it like the prime number generator and the XtoYmodN function.
// It would be great if you could send me emails to: lee.griffiths@first4internet.co.uk
// with any suggestions, comments, or questions!
// Enjoy.
// Adopted to ms-logon for ultravnc and ported to Java by marscha, 2006.
//import java.lang.Math;
public class DH {
public DH() {
maxNum = (((long) 1) << DH_MAX_BITS) - 1;
}
public DH(long generator, long modulus) throws Exception {
maxNum = (((long) 1) << DH_MAX_BITS) - 1;
if (generator >= maxNum || modulus >= maxNum)
throw new Exception("Modulus or generator too large.");
gen = generator;
mod = modulus;
}
private long rng(long limit) {
return (long) (java.lang.Math.random() * limit);
}
//Performs the miller-rabin primality test on a guessed prime n.
//trials is the number of attempts to verify this, because the function
//is not 100% accurate it may be a composite. However setting the trial
//value to around 5 should guarantee success even with very large primes
private boolean millerRabin (long n, int trials) {
long a = 0;
for (int i = 0; i < trials; i++) {
a = rng(n - 3) + 2;// gets random value in [2..n-1]
if (XpowYmodN(a, n - 1, n) != 1) return false; //n composite, return false
}
return true; // n probably prime
}
//Generates a large prime number by
//choosing a randomly large integer, and ensuring the value is odd
//then uses the miller-rabin primality test on it to see if it is prime
//if not the value gets increased until it is prime
private long generatePrime() {
long prime = 0;
do {
long start = rng(maxNum);
prime = tryToGeneratePrime(start);
} while (prime == 0);
return prime;
}
private long tryToGeneratePrime(long prime) {
//ensure it is an odd number
if ((prime & 1) == 0)
prime += 1;
long cnt = 0;
while (!millerRabin(prime, 25) && (cnt++ < DH_RANGE) && prime < maxNum) {
prime += 2;
if ((prime % 3) == 0) prime += 2;
}
return (cnt >= DH_RANGE || prime >= maxNum) ? 0 : prime;
}
//Raises X to the power Y in modulus N
//the values of X, Y, and N can be massive, and this can be
//achieved by first calculating X to the power of 2 then
//using power chaining over modulus N
private long XpowYmodN(long x, long y, long N) {
long result = 1;
final long oneShift63 = ((long) 1) << 63;
for (int i = 0; i < 64; y <<= 1, i++){
result = result * result % N;
if ((y & oneShift63) != 0)
result = result * x % N;
}
return result;
}
public void createKeys() {
gen = generatePrime();
mod = generatePrime();
if (gen > mod) {
long swap = gen;
gen = mod;
mod = swap;
}
}
public long createInterKey() {
priv = rng(maxNum);
return pub = XpowYmodN(gen,priv,mod);
}
public long createEncryptionKey(long interKey) throws Exception {
if (interKey >= maxNum){
throw new Exception("interKey too large");
}
return key = XpowYmodN(interKey,priv,mod);
}
public long getValue(int flags) {
switch (flags) {
case DH_MOD:
return mod;
case DH_GEN:
return gen;
case DH_PRIV:
return priv;
case DH_PUB:
return pub;
case DH_KEY:
return key;
default:
return (long) 0;
}
}
public int bits(long number){
for (int i = 0; i < 64; i++){
number /= 2;
if (number < 2) return i;
}
return 0;
}
public static byte[] longToBytes(long number) {
byte[] bytes = new byte[8];
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) (0xff & (number >> (8 * (7 - i))));
}
return bytes;
}
public static long bytesToLong(byte[] bytes) {
long result = 0;
for (int i = 0; i < 8; i++) {
result <<= 8;
result += (byte) bytes[i];
}
return result;
}
private long gen;
private long mod;
private long priv;
private long pub;
private long key;
private long maxNum;
private static final int DH_MAX_BITS = 31;
private static final int DH_RANGE = 100;
private static final int DH_MOD = 1;
private static final int DH_GEN = 2;
private static final int DH_PRIV = 3;
private static final int DH_PUB = 4;
private static final int DH_KEY = 5;
}

View File

@@ -0,0 +1,115 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package android.androidVNC;
import android.graphics.PointF;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.MotionEvent;
/**
* Input handlers delegate to this class to handle keystrokes; this detects keystrokes
* from the DPad and uses them to perform mouse actions; other keystrokes are passed to
* VncCanvasActivity.defaultKeyXXXHandler
*
* @author Michael A. MacDonald
*
*/
class DPadMouseKeyHandler {
private MouseMover mouseMover;
private boolean mouseDown;
private VncCanvasActivity activity;
private VncCanvas canvas;
private boolean isMoving;
DPadMouseKeyHandler(VncCanvasActivity activity, Handler handler)
{
this.activity = activity;
canvas = activity.vncCanvas;
mouseMover = new MouseMover(activity, handler);
}
public boolean onKeyDown(int keyCode, KeyEvent evt) {
int xv = 0;
int yv = 0;
boolean result = true;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
xv = -1;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
xv = 1;
break;
case KeyEvent.KEYCODE_DPAD_UP:
yv = -1;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
yv = 1;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
if (!mouseDown) {
mouseDown = true;
result = canvas.processPointerEvent(canvas.mouseX, canvas.mouseY, MotionEvent.ACTION_DOWN, evt.getMetaState(), mouseDown, canvas.cameraButtonDown);
}
break;
default:
result = activity.defaultKeyDownHandler(keyCode, evt);
break;
}
if ((xv != 0 || yv != 0) && !isMoving) {
final int x = xv;
final int y = yv;
isMoving = true;
mouseMover.start(x, y, new Panner.VelocityUpdater() {
/*
* (non-Javadoc)
*
* @see android.androidVNC.Panner.VelocityUpdater#updateVelocity(android.graphics.Point,
* long)
*/
@Override
public boolean updateVelocity(PointF p, long interval) {
double scale = (1.2 * (double) interval / 50.0);
if (Math.abs(p.x) < 500)
p.x += (int) (scale * x);
if (Math.abs(p.y) < 500)
p.y += (int) (scale * y);
return true;
}
});
canvas.processPointerEvent(canvas.mouseX + x, canvas.mouseY + y, MotionEvent.ACTION_MOVE, evt.getMetaState(), mouseDown, canvas.cameraButtonDown);
}
return result;
}
public boolean onKeyUp(int keyCode, KeyEvent evt) {
boolean result = false;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
mouseMover.stop();
isMoving = false;
result = true;
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
if (mouseDown) {
mouseDown = false;
result = canvas.processPointerEvent(canvas.mouseX, canvas.mouseY, MotionEvent.ACTION_UP, evt.getMetaState(), mouseDown, canvas.cameraButtonDown);
} else {
result = true;
}
break;
default:
result = activity.defaultKeyUpHandler(keyCode, evt);
break;
}
return result;
}
}

View File

@@ -0,0 +1,539 @@
//
// This DES class has been extracted from package Acme.Crypto for use in VNC.
// The bytebit[] array has been reversed so that the most significant bit
// in each byte of the key is ignored, not the least significant. Also the
// unnecessary odd parity code has been removed.
//
// These changes are:
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This software 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.
//
// DesCipher - the DES encryption method
//
// The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:
//
// Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
//
// Permission to use, copy, modify, and distribute this software
// and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
// without fee is hereby granted, provided that this copyright notice is kept
// intact.
//
// WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
// OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE
// FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
// DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
//
// THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
// CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
// PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
// NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
// SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
// SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
// PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP
// SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
// HIGH RISK ACTIVITIES.
//
//
// The rest is:
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// Visit the ACME Labs Java page for up-to-date versions of this and other
// fine Java utilities: http://www.acme.com/java/
/// The DES encryption method.
// <P>
// This is surprisingly fast, for pure Java. On a SPARC 20, wrapped
// in Acme.Crypto.EncryptedOutputStream or Acme.Crypto.EncryptedInputStream,
// it does around 7000 bytes/second.
// <P>
// Most of this code is by Dave Zimmerman <dzimm@widget.com>, and is
// Copyright (c) 1996 Widget Workshop, Inc. See the source file for details.
// <P>
// <A HREF="/resources/classes/Acme/Crypto/DesCipher.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>
// <P>
// @see Des3Cipher
// @see EncryptedOutputStream
// @see EncryptedInputStream
package android.androidVNC;
//- import java.io.*;
public class DesCipher
{
// Constructor, byte-array key.
public DesCipher( byte[] key )
{
setKey( key );
}
// Key routines.
private int[] encryptKeys = new int[32];
private int[] decryptKeys = new int[32];
/// Set the key.
public void setKey( byte[] key )
{
deskey( key, true, encryptKeys );
deskey( key, false, decryptKeys );
}
// Turn an 8-byte key into internal keys.
private void deskey( byte[] keyBlock, boolean encrypting, int[] KnL )
{
int i, j, l, m, n;
int[] pc1m = new int[56];
int[] pcr = new int[56];
int[] kn = new int[32];
for ( j = 0; j < 56; ++j )
{
l = pc1[j];
m = l & 07;
pc1m[j] = ( (keyBlock[l >>> 3] & bytebit[m]) != 0 )? 1: 0;
}
for ( i = 0; i < 16; ++i )
{
if ( encrypting )
m = i << 1;
else
m = (15-i) << 1;
n = m+1;
kn[m] = kn[n] = 0;
for ( j = 0; j < 28; ++j )
{
l = j+totrot[i];
if ( l < 28 )
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l-28];
}
for ( j=28; j < 56; ++j )
{
l = j+totrot[i];
if ( l < 56 )
pcr[j] = pc1m[l];
else
pcr[j] = pc1m[l-28];
}
for ( j = 0; j < 24; ++j )
{
if ( pcr[pc2[j]] != 0 )
kn[m] |= bigbyte[j];
if ( pcr[pc2[j+24]] != 0 )
kn[n] |= bigbyte[j];
}
}
cookey( kn, KnL );
}
private void cookey( int[] raw, int KnL[] )
{
int raw0, raw1;
int rawi, KnLi;
int i;
for ( i = 0, rawi = 0, KnLi = 0; i < 16; ++i )
{
raw0 = raw[rawi++];
raw1 = raw[rawi++];
KnL[KnLi] = (raw0 & 0x00fc0000) << 6;
KnL[KnLi] |= (raw0 & 0x00000fc0) << 10;
KnL[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
KnL[KnLi] |= (raw1 & 0x00000fc0) >>> 6;
++KnLi;
KnL[KnLi] = (raw0 & 0x0003f000) << 12;
KnL[KnLi] |= (raw0 & 0x0000003f) << 16;
KnL[KnLi] |= (raw1 & 0x0003f000) >>> 4;
KnL[KnLi] |= (raw1 & 0x0000003f);
++KnLi;
}
}
// Block encryption routines.
private int[] tempInts = new int[2];
/// Encrypt a block of eight bytes.
public void encrypt( byte[] clearText, int clearOff, byte[] cipherText, int cipherOff )
{
squashBytesToInts( clearText, clearOff, tempInts, 0, 2 );
des( tempInts, tempInts, encryptKeys );
spreadIntsToBytes( tempInts, 0, cipherText, cipherOff, 2 );
}
/// Decrypt a block of eight bytes.
public void decrypt( byte[] cipherText, int cipherOff, byte[] clearText, int clearOff )
{
squashBytesToInts( cipherText, cipherOff, tempInts, 0, 2 );
des( tempInts, tempInts, decryptKeys );
spreadIntsToBytes( tempInts, 0, clearText, clearOff, 2 );
}
// Encrypt a text which is a multiple of 8 bytes.
public void encryptText(byte[] clearText, byte[] cipherText, byte[] key)
{
int i, j;
for(i=0; i<8; i++)
{
clearText[i] ^= key[i];
}
encrypt(clearText, 0, cipherText, 0);
for(i=8; i<clearText.length; i+=8)
{
for(j=0; j<8; j++)
{
clearText[i+j] ^= cipherText[i+j-8];
}
encrypt(clearText, i, cipherText, i);
}
}
// Decrypt a text which is a multiple of 8 bytes.
public void decryptText(byte[] cipherText, byte[] clearText, byte[] key)
{
int i, j;
for(i=cipherText.length-8; i>0; i-=8)
{
decrypt(cipherText, i, clearText, i);
for(j=0; j<8; j++)
{
clearText[i+j] ^= cipherText[i+j-8];
}
}
/* i = 0 */
decrypt(cipherText, 0, clearText, 0);
for(i=0; i<8; i++)
{
clearText[i] ^= key[i];
}
}
// The DES function.
private void des( int[] inInts, int[] outInts, int[] keys )
{
int fval, work, right, leftt;
int round;
int keysi = 0;
leftt = inInts[0];
right = inInts[1];
work = ((leftt >>> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
leftt ^= (work << 4);
work = ((leftt >>> 16) ^ right) & 0x0000ffff;
right ^= work;
leftt ^= (work << 16);
work = ((right >>> 2) ^ leftt) & 0x33333333;
leftt ^= work;
right ^= (work << 2);
work = ((right >>> 8) ^ leftt) & 0x00ff00ff;
leftt ^= work;
right ^= (work << 8);
right = (right << 1) | ((right >>> 31) & 1);
work = (leftt ^ right) & 0xaaaaaaaa;
leftt ^= work;
right ^= work;
leftt = (leftt << 1) | ((leftt >>> 31) & 1);
for ( round = 0; round < 8; ++round )
{
work = (right << 28) | (right >>> 4);
work ^= keys[keysi++];
fval = SP7[ work & 0x0000003f ];
fval |= SP5[(work >>> 8) & 0x0000003f ];
fval |= SP3[(work >>> 16) & 0x0000003f ];
fval |= SP1[(work >>> 24) & 0x0000003f ];
work = right ^ keys[keysi++];
fval |= SP8[ work & 0x0000003f ];
fval |= SP6[(work >>> 8) & 0x0000003f ];
fval |= SP4[(work >>> 16) & 0x0000003f ];
fval |= SP2[(work >>> 24) & 0x0000003f ];
leftt ^= fval;
work = (leftt << 28) | (leftt >>> 4);
work ^= keys[keysi++];
fval = SP7[ work & 0x0000003f ];
fval |= SP5[(work >>> 8) & 0x0000003f ];
fval |= SP3[(work >>> 16) & 0x0000003f ];
fval |= SP1[(work >>> 24) & 0x0000003f ];
work = leftt ^ keys[keysi++];
fval |= SP8[ work & 0x0000003f ];
fval |= SP6[(work >>> 8) & 0x0000003f ];
fval |= SP4[(work >>> 16) & 0x0000003f ];
fval |= SP2[(work >>> 24) & 0x0000003f ];
right ^= fval;
}
right = (right << 31) | (right >>> 1);
work = (leftt ^ right) & 0xaaaaaaaa;
leftt ^= work;
right ^= work;
leftt = (leftt << 31) | (leftt >>> 1);
work = ((leftt >>> 8) ^ right) & 0x00ff00ff;
right ^= work;
leftt ^= (work << 8);
work = ((leftt >>> 2) ^ right) & 0x33333333;
right ^= work;
leftt ^= (work << 2);
work = ((right >>> 16) ^ leftt) & 0x0000ffff;
leftt ^= work;
right ^= (work << 16);
work = ((right >>> 4) ^ leftt) & 0x0f0f0f0f;
leftt ^= work;
right ^= (work << 4);
outInts[0] = right;
outInts[1] = leftt;
}
// Tables, permutations, S-boxes, etc.
private static byte[] bytebit = {
(byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08,
(byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80
};
private static int[] bigbyte = {
0x800000, 0x400000, 0x200000, 0x100000,
0x080000, 0x040000, 0x020000, 0x010000,
0x008000, 0x004000, 0x002000, 0x001000,
0x000800, 0x000400, 0x000200, 0x000100,
0x000080, 0x000040, 0x000020, 0x000010,
0x000008, 0x000004, 0x000002, 0x000001
};
private static byte[] pc1 = {
(byte)56, (byte)48, (byte)40, (byte)32, (byte)24, (byte)16, (byte) 8,
(byte) 0, (byte)57, (byte)49, (byte)41, (byte)33, (byte)25, (byte)17,
(byte) 9, (byte) 1, (byte)58, (byte)50, (byte)42, (byte)34, (byte)26,
(byte)18, (byte)10, (byte) 2, (byte)59, (byte)51, (byte)43, (byte)35,
(byte)62, (byte)54, (byte)46, (byte)38, (byte)30, (byte)22, (byte)14,
(byte) 6, (byte)61, (byte)53, (byte)45, (byte)37, (byte)29, (byte)21,
(byte)13, (byte) 5, (byte)60, (byte)52, (byte)44, (byte)36, (byte)28,
(byte)20, (byte)12, (byte) 4, (byte)27, (byte)19, (byte)11, (byte)3
};
private static int[] totrot = {
1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28
};
private static byte[] pc2 = {
(byte)13, (byte)16, (byte)10, (byte)23, (byte) 0, (byte) 4,
(byte) 2, (byte)27, (byte)14, (byte) 5, (byte)20, (byte) 9,
(byte)22, (byte)18, (byte)11, (byte)3 , (byte)25, (byte) 7,
(byte)15, (byte) 6, (byte)26, (byte)19, (byte)12, (byte) 1,
(byte)40, (byte)51, (byte)30, (byte)36, (byte)46, (byte)54,
(byte)29, (byte)39, (byte)50, (byte)44, (byte)32, (byte)47,
(byte)43, (byte)48, (byte)38, (byte)55, (byte)33, (byte)52,
(byte)45, (byte)41, (byte)49, (byte)35, (byte)28, (byte)31,
};
private static int[] SP1 = {
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004
};
private static int[] SP2 = {
0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000
};
private static int[] SP3 = {
0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200
};
private static int[] SP4 = {
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080
};
private static int[] SP5 = {
0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100
};
private static int[] SP6 = {
0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010
};
private static int[] SP7 = {
0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002
};
private static int[] SP8 = {
0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000
};
// Routines taken from other parts of the Acme utilities.
/// Squash bytes down to ints.
public static void squashBytesToInts( byte[] inBytes, int inOff, int[] outInts, int outOff, int intLen )
{
for ( int i = 0; i < intLen; ++i )
outInts[outOff + i] =
( ( inBytes[inOff + i * 4 ] & 0xff ) << 24 ) |
( ( inBytes[inOff + i * 4 + 1] & 0xff ) << 16 ) |
( ( inBytes[inOff + i * 4 + 2] & 0xff ) << 8 ) |
( inBytes[inOff + i * 4 + 3] & 0xff );
}
/// Spread ints into bytes.
public static void spreadIntsToBytes( int[] inInts, int inOff, byte[] outBytes, int outOff, int intLen )
{
for ( int i = 0; i < intLen; ++i )
{
outBytes[outOff + i * 4 ] = (byte) ( inInts[inOff + i] >>> 24 );
outBytes[outOff + i * 4 + 1] = (byte) ( inInts[inOff + i] >>> 16 );
outBytes[outOff + i * 4 + 2] = (byte) ( inInts[inOff + i] >>> 8 );
outBytes[outOff + i * 4 + 3] = (byte) inInts[inOff + i];
}
}
}

View File

@@ -0,0 +1,240 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.app.*;
import android.content.*;
import android.database.*;
import android.database.sqlite.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import java.io.*;
import java.util.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*
*/
class EnterTextDialog extends Dialog {
static final int NUMBER_SENT_SAVED = 100;
static final int DELETED_ID = -10;
private VncCanvasActivity _canvasActivity;
private EditText _textEnterText;
private ArrayList<SentTextBean> _history;
private int _historyIndex;
private ImageButton _buttonNextEntry;
private ImageButton _buttonPreviousEntry;
public EnterTextDialog(Context context) {
super(context);
setOwnerActivity((Activity)context);
_canvasActivity = (VncCanvasActivity)context;
_history = new ArrayList<SentTextBean>();
}
private String saveText(boolean wasSent)
{
CharSequence cs = _textEnterText.getText();
if (cs.length()==0)
return "";
String s = cs.toString();
if (wasSent || _historyIndex>=_history.size() || ! s.equals(_history.get(_historyIndex).getSentText()))
{
SentTextBean added = new SentTextBean();
added.setSentText(s);
SQLiteDatabase db = _canvasActivity.database.getWritableDatabase();
added.Gen_insert(db);
_history.add(added);
for (int i = 0; i < _historyIndex - NUMBER_SENT_SAVED; i++)
{
SentTextBean deleteCandidate = _history.get(i);
if (deleteCandidate.get_Id() != DELETED_ID)
{
deleteCandidate.Gen_delete(db);
deleteCandidate.set_Id(DELETED_ID);
}
}
}
return s;
}
private void sendText(String s)
{
RfbProto rfb = _canvasActivity.vncCanvas.rfb;
int l = s.length();
for (int i = 0; i<l; i++)
{
char c = s.charAt(i);
int meta = 0;
int keysym = c;
if (Character.isISOControl(c))
{
if (c=='\n')
keysym = MetaKeyBean.keysByKeyCode.get(KeyEvent.KEYCODE_ENTER).keySym;
else
continue;
}
try
{
rfb.writeKeyEvent(keysym, meta, true);
rfb.writeKeyEvent(keysym, meta, false);
}
catch (IOException ioe)
{
// TODO: log this
}
}
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.entertext);
setTitle(R.string.enter_text_title);
_textEnterText = (EditText)findViewById(R.id.textEnterText);
_buttonNextEntry = (ImageButton)findViewById(R.id.buttonNextEntry);
_buttonNextEntry.setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
int oldSize = _history.size();
if (_historyIndex < oldSize)
{
saveText(false);
_historyIndex++;
if (_history.size()>oldSize && _historyIndex==oldSize)
_historyIndex++;
if (_historyIndex < _history.size())
{
_textEnterText.setText(_history.get(_historyIndex).getSentText());
}
else
{
_textEnterText.setText("");
}
}
updateButtons();
}
});
_buttonPreviousEntry = (ImageButton)findViewById(R.id.buttonPreviousEntry);
_buttonPreviousEntry.setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
if (_historyIndex > 0)
{
saveText(false);
_historyIndex--;
_textEnterText.setText(_history.get(_historyIndex).getSentText());
}
updateButtons();
}
});
((Button)findViewById(R.id.buttonSendText)).setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
String s = saveText(true);
sendText(s);
_textEnterText.setText("");
_historyIndex = _history.size();
updateButtons();
dismiss();
}
});
((Button)findViewById(R.id.buttonSendWithoutSaving)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String s = _textEnterText.getText().toString();
sendText(s);
_textEnterText.setText("");
_historyIndex = _history.size();
updateButtons();
dismiss();
}
});
((ImageButton)findViewById(R.id.buttonTextDelete)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (_historyIndex < _history.size())
{
String s = _textEnterText.getText().toString();
SentTextBean bean = _history.get(_historyIndex);
if (s.equals(bean.getSentText()))
{
bean.Gen_delete(_canvasActivity.database.getWritableDatabase());
_history.remove(_historyIndex);
if (_historyIndex > 0)
{
_historyIndex = _historyIndex - 1;
}
}
}
String s = "";
if (_historyIndex < _history.size())
{
s = _history.get(_historyIndex).getSentText();
}
_textEnterText.setText(s);
updateButtons();
}
});
Cursor readInOrder = _canvasActivity.database.getReadableDatabase().rawQuery(
"select * from " + SentTextBean.GEN_TABLE_NAME + " ORDER BY _id", null);
try
{
SentTextBean.Gen_populateFromCursor(readInOrder, _history, SentTextBean.GEN_NEW);
}
finally
{
readInOrder.close();
}
_historyIndex = _history.size();
updateButtons();
}
private void updateButtons()
{
_buttonPreviousEntry.setEnabled(_historyIndex > 0);
_buttonNextEntry.setEnabled(_historyIndex <_history.size());
}
/* (non-Javadoc)
* @see android.app.Dialog#onStart()
*/
@Override
protected void onStart() {
super.onStart();
_textEnterText.requestFocus();
}
}

View File

@@ -0,0 +1,56 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.widget.ImageView.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*/
class FitToScreenScaling extends AbstractScaling {
/**
* @param id
* @param scaleType
*/
FitToScreenScaling() {
super(R.id.itemFitToScreen, ScaleType.FIT_CENTER);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#isAbleToPan()
*/
@Override
boolean isAbleToPan() {
return false;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#isValidInputMode(int)
*/
@Override
boolean isValidInputMode(int mode) {
return mode == R.id.itemInputFitToScreen;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#getDefaultHandlerId()
*/
@Override
int getDefaultHandlerId() {
return R.id.itemInputFitToScreen;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#setCanvasScaleType(android.androidVNC.VncCanvas)
*/
@Override
void setScaleTypeForActivity(VncCanvasActivity activity) {
super.setScaleTypeForActivity(activity);
activity.vncCanvas.absoluteXPosition = activity.vncCanvas.absoluteYPosition = 0;
activity.vncCanvas.scrollTo(0, 0);
}
}

View File

@@ -0,0 +1,202 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package android.androidVNC;
import java.io.IOException;
import java.util.Arrays;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.widget.ImageView;
/**
* @author Michael A. MacDonald
*
*/
class FullBufferBitmapData extends AbstractBitmapData {
int xoffset;
int yoffset;
/**
* @author Michael A. MacDonald
*
*/
class Drawable extends AbstractBitmapDrawable {
/**
* @param data
*/
public Drawable(AbstractBitmapData data) {
super(data);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#draw(android.graphics.Canvas)
*/
@Override
public void draw(Canvas canvas) {
if (vncCanvas.getScaleType() == ImageView.ScaleType.FIT_CENTER)
{
canvas.drawBitmap(data.bitmapPixels, 0, data.framebufferwidth, xoffset, yoffset, framebufferwidth, framebufferheight, false, null);
}
else
{
float scale = vncCanvas.getScale();
int xo = xoffset < 0 ? 0 : xoffset;
int yo = yoffset < 0 ? 0 : yoffset;
/*
if (scale == 1 || scale <= 0)
{
*/
int drawWidth = vncCanvas.getVisibleWidth();
if (drawWidth + xo > data.framebufferwidth)
drawWidth = data.framebufferwidth - xo;
int drawHeight = vncCanvas.getVisibleHeight();
if (drawHeight + yo > data.framebufferheight)
drawHeight = data.framebufferheight - yo;
canvas.drawBitmap(data.bitmapPixels, offset(xo, yo), data.framebufferwidth, xo, yo, drawWidth, drawHeight, false, null);
/*
}
else
{
int scalewidth = (int)(vncCanvas.getVisibleWidth() / scale + 1);
if (scalewidth + xo > data.framebufferwidth)
scalewidth = data.framebufferwidth - xo;
int scaleheight = (int)(vncCanvas.getVisibleHeight() / scale + 1);
if (scaleheight + yo > data.framebufferheight)
scaleheight = data.framebufferheight - yo;
canvas.drawBitmap(data.bitmapPixels, offset(xo, yo), data.framebufferwidth, xo, yo, scalewidth, scaleheight, false, null);
}
*/
}
if(data.vncCanvas.connection.getUseLocalCursor())
{
setCursorRect(data.vncCanvas.mouseX, data.vncCanvas.mouseY);
clipRect.set(cursorRect);
if (canvas.clipRect(cursorRect))
{
drawCursor(canvas);
}
}
}
}
/**
* Multiply this times total number of pixels to get estimate of process size with all buffers plus
* safety factor
*/
static final int CAPACITY_MULTIPLIER = 7;
/**
* @param p
* @param c
*/
public FullBufferBitmapData(RfbProto p, VncCanvas c, int capacity) {
super(p, c);
framebufferwidth=rfb.framebufferWidth;
framebufferheight=rfb.framebufferHeight;
bitmapwidth=framebufferwidth;
bitmapheight=framebufferheight;
android.util.Log.i("FBBM", "bitmapsize = ("+bitmapwidth+","+bitmapheight+")");
bitmapPixels = new int[framebufferwidth * framebufferheight];
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#copyRect(android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
*/
@Override
void copyRect(Rect src, Rect dest, Paint paint) {
// TODO copy rect working?
throw new RuntimeException( "copyrect Not implemented");
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#createDrawable()
*/
@Override
AbstractBitmapDrawable createDrawable() {
return new Drawable(this);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#drawRect(int, int, int, int, android.graphics.Paint)
*/
@Override
void drawRect(int x, int y, int w, int h, Paint paint) {
int color = paint.getColor();
int offset = offset(x,y);
if (w > 10)
{
for (int j = 0; j < h; j++, offset += framebufferwidth)
{
Arrays.fill(bitmapPixels, offset, offset + w, color);
}
}
else
{
for (int j = 0; j < h; j++, offset += framebufferwidth - w)
{
for (int k = 0; k < w; k++, offset++)
{
bitmapPixels[offset] = color;
}
}
}
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#offset(int, int)
*/
@Override
int offset(int x, int y) {
return x + y * framebufferwidth;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#scrollChanged(int, int)
*/
@Override
void scrollChanged(int newx, int newy) {
xoffset = newx;
yoffset = newy;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#syncScroll()
*/
@Override
void syncScroll() {
// Don't need to do anything here
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#updateBitmap(int, int, int, int)
*/
@Override
void updateBitmap(int x, int y, int w, int h) {
// Don't need to do anything here
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#validDraw(int, int, int, int)
*/
@Override
boolean validDraw(int x, int y, int w, int h) {
return true;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#writeFullUpdateRequest(boolean)
*/
@Override
void writeFullUpdateRequest(boolean incremental) throws IOException {
rfb.writeFramebufferUpdateRequest(0, 0, framebufferwidth, framebufferheight, incremental);
}
}

View File

@@ -0,0 +1,62 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import com.antlersoft.android.db.*;
/**
* @author Michael A. MacDonald
*
*/
@TableInterface(ImplementingClassName="AbstractConnectionBean",TableName="CONNECTION_BEAN")
interface IConnectionBean {
@FieldAccessor
long get_Id();
@FieldAccessor
String getNickname();
@FieldAccessor
String getAddress();
@FieldAccessor
int getPort();
@FieldAccessor
String getPassword();
@FieldAccessor
String getColorModel();
/**
* Records bitmap data implementation selection. 0 for auto, 1 for force full bitmap, 2 for force tiled
* <p>
* For historical reasons, this is named as if it were just a boolean selection for auto and force full.
* @return 0 for auto, 1 for force full bitmap, 2 for forced tiled
*/
@FieldAccessor
long getForceFull();
@FieldAccessor
String getRepeaterId();
@FieldAccessor
String getInputMode();
@FieldAccessor(Name="SCALEMODE")
String getScaleModeAsString();
@FieldAccessor
boolean getUseLocalCursor();
@FieldAccessor
boolean getKeepPassword();
@FieldAccessor
boolean getFollowMouse();
@FieldAccessor
boolean getUseRepeater();
@FieldAccessor
long getMetaListId();
@FieldAccessor(Name="LAST_META_KEY_ID")
long getLastMetaKeyId();
@FieldAccessor(DefaultValue="false")
boolean getFollowPan();
@FieldAccessor
String getUserName();
@FieldAccessor
String getSecureConnectionType();
@FieldAccessor(DefaultValue="true")
boolean getShowZoomButtons();
@FieldAccessor(Name="DOUBLE_TAP_ACTION")
String getDoubleTapActionAsString();
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import com.antlersoft.android.db.FieldAccessor;
import com.antlersoft.android.db.TableInterface;
/**
* @author Michael A. MacDonald
*
*/
@TableInterface(TableName="META_KEY",ImplementingClassName="AbstractMetaKeyBean")
public interface IMetaKey {
@FieldAccessor
long get_Id();
@FieldAccessor
long getMetaListId();
@FieldAccessor
String getKeyDesc();
@FieldAccessor
int getMetaFlags();
@FieldAccessor
boolean isMouseClick();
@FieldAccessor
int getMouseButtons();
@FieldAccessor
int getKeySym();
@FieldAccessor
String getShortcut();
}

View File

@@ -0,0 +1,19 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import com.antlersoft.android.db.FieldAccessor;
import com.antlersoft.android.db.TableInterface;
/**
* @author Michael A. MacDonald
*
*/
@TableInterface(TableName="META_LIST",ImplementingIsAbstract=false,ImplementingClassName="MetaList")
public interface IMetaList {
@FieldAccessor
long get_Id();
@FieldAccessor
String getName();
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import com.antlersoft.android.db.*;
/**
* @author Michael A. MacDonald
*
*/
@TableInterface(TableName="MOST_RECENT",ImplementingIsAbstract=false,ImplementingClassName="MostRecentBean")
public interface IMostRecentBean {
@FieldAccessor
long get_Id();
@FieldAccessor(Name="CONNECTION_ID")
long getConnectionId();
@FieldAccessor(Name="SHOW_SPLASH_VERSION")
long getShowSplashVersion();
@FieldAccessor(Name="TEXT_INDEX")
long getTextIndex();
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package android.androidVNC;
import com.antlersoft.android.db.FieldAccessor;
import com.antlersoft.android.db.TableInterface;
/**
* Interface specification for table storing sent text; the last N text items sent are stored in a table
* and will be recalled on demand
*
* @author Michael A. MacDonald
*
*/
@TableInterface(TableName="SENT_TEXT",ImplementingIsAbstract=false,ImplementingClassName="SentTextBean")
public interface ISentText {
@FieldAccessor
long get_Id();
@FieldAccessor
String getSentText();
}

View File

@@ -0,0 +1,126 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package android.androidVNC;
import android.app.*;
import android.os.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import com.antlersoft.android.bc.*;
import com.antlersoft.android.contentxml.*;
import com.antlersoft.android.contentxml.SqliteElement.*;
import java.io.*;
import java.net.*;
import net.kdt.pojavlaunch.*;
import org.xml.sax.*;
/**
* @author Michael A. MacDonald
*
*/
class ImportExportDialog extends Dialog {
private androidVNC _configurationDialog;
private EditText _textLoadUrl;
private EditText _textSaveUrl;
/**
* @param context
*/
public ImportExportDialog(androidVNC context) {
super(context);
setOwnerActivity((Activity)context);
_configurationDialog = context;
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.importexport);
setTitle(R.string.import_export_settings);
_textLoadUrl = (EditText)findViewById(R.id.textImportUrl);
_textSaveUrl = (EditText)findViewById(R.id.textExportPath);
File f = BCFactory.getInstance().getStorageContext().getExternalStorageDir(_configurationDialog, null);
// Sdcard not mounted; nothing else to do
if (f == null)
return;
f = new File(f, "vnc_settings.xml");
_textSaveUrl.setText(f.getAbsolutePath());
try {
_textLoadUrl.setText(f.toURL().toString());
} catch (MalformedURLException e) {
// Do nothing; default value not set
}
Button export = (Button)findViewById(R.id.buttonExport);
export.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
File f = new File(_textSaveUrl.getText().toString());
Writer writer = new OutputStreamWriter(new FileOutputStream(f, false));
SqliteElement.exportDbAsXmlToStream(_configurationDialog.getDatabaseHelper().getReadableDatabase(), writer);
writer.close();
dismiss();
}
catch (IOException ioe)
{
errorNotify("I/O Exception exporting config", ioe);
} catch (SAXException e) {
errorNotify("XML Exception exporting config", e);
}
}
});
((Button)findViewById(R.id.buttonImport)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try
{
URL url = new URL(_textLoadUrl.getText().toString());
URLConnection connection = url.openConnection();
connection.connect();
Reader reader = new InputStreamReader(connection.getInputStream());
SqliteElement.importXmlStreamToDb(
_configurationDialog.getDatabaseHelper().getWritableDatabase(),
reader,
ReplaceStrategy.REPLACE_EXISTING);
dismiss();
_configurationDialog.arriveOnPage();
}
catch (MalformedURLException mfe)
{
errorNotify("Improper URL given: " + _textLoadUrl.getText(), mfe);
}
catch (IOException ioe)
{
errorNotify("I/O error reading configuration", ioe);
}
catch (SAXException e)
{
errorNotify("XML or format error reading configuration", e);
}
}
});
}
private void errorNotify(String msg, Throwable t)
{
Log.i("android.androidVNC.ImportExportDialog", msg, t);
Utils.showErrorMessage(this.getContext(), msg + ":" + t.getMessage());
}
}

View File

@@ -0,0 +1,155 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// rdr::InStream marshalls data from a buffer stored in RDR (RFB Data
// Representation).
//
package android.androidVNC;
abstract public class InStream {
// check() ensures there is buffer data for at least one item of size
// itemSize bytes. Returns the number of items in the buffer (up to a
// maximum of nItems).
public final int check(int itemSize, int nItems) throws Exception {
if (ptr + itemSize * nItems > end) {
if (ptr + itemSize > end)
return overrun(itemSize, nItems);
nItems = (end - ptr) / itemSize;
}
return nItems;
}
public final void check(int itemSize) throws Exception {
if (ptr + itemSize > end)
overrun(itemSize, 1);
}
// readU/SN() methods read unsigned and signed N-bit integers.
public final int readS8() throws Exception {
check(1); return b[ptr++];
}
public final int readS16() throws Exception {
check(2); int b0 = b[ptr++];
int b1 = b[ptr++] & 0xff; return b0 << 8 | b1;
}
public final int readS32() throws Exception {
check(4); int b0 = b[ptr++];
int b1 = b[ptr++] & 0xff;
int b2 = b[ptr++] & 0xff;
int b3 = b[ptr++] & 0xff;
return b0 << 24 | b1 << 16 | b2 << 8 | b3;
}
public final int readU8() throws Exception {
return readS8() & 0xff;
}
public final int readU16() throws Exception {
return readS16() & 0xffff;
}
public final int readU32() throws Exception {
return readS32() & 0xffffffff;
}
public final void skip(int bytes) throws Exception {
while (bytes > 0) {
int n = check(1, bytes);
ptr += n;
bytes -= n;
}
}
// readBytes() reads an exact number of bytes into an array at an offset.
public void readBytes(byte[] data, int offset, int length) throws Exception {
int offsetEnd = offset + length;
while (offset < offsetEnd) {
int n = check(1, offsetEnd - offset);
System.arraycopy(b, ptr, data, offset, n);
ptr += n;
offset += n;
}
}
// readOpaqueN() reads a quantity "without byte-swapping". Because java has
// no byte-ordering, we just use big-endian.
public final int readOpaque8() throws Exception {
return readU8();
}
public final int readOpaque16() throws Exception {
return readU16();
}
public final int readOpaque32() throws Exception {
return readU32();
}
public final int readOpaque24A() throws Exception {
check(3); int b0 = b[ptr++];
int b1 = b[ptr++]; int b2 = b[ptr++];
return b0 << 24 | b1 << 16 | b2 << 8;
}
public final int readOpaque24B() throws Exception {
check(3); int b0 = b[ptr++];
int b1 = b[ptr++]; int b2 = b[ptr++];
return b0 << 16 | b1 << 8 | b2;
}
// pos() returns the position in the stream.
abstract public int pos();
// bytesAvailable() returns true if at least one byte can be read from the
// stream without blocking. i.e. if false is returned then readU8() would
// block.
public boolean bytesAvailable() { return end != ptr; }
// getbuf(), getptr(), getend() and setptr() are "dirty" methods which allow
// you to manipulate the buffer directly. This is useful for a stream which
// is a wrapper around an underlying stream.
public final byte[] getbuf() { return b; }
public final int getptr() { return ptr; }
public final int getend() { return end; }
public final void setptr(int p) { ptr = p; }
// overrun() is implemented by a derived class to cope with buffer overrun.
// It ensures there are at least itemSize bytes of buffer data. Returns
// the number of items in the buffer (up to a maximum of nItems). itemSize
// is supposed to be "small" (a few bytes).
abstract protected int overrun(int itemSize, int nItems) throws Exception;
protected InStream() {}
protected byte[] b;
protected int ptr;
protected int end;
}

View File

@@ -0,0 +1,149 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package android.androidVNC;
import android.app.*;
import android.content.pm.*;
import android.database.sqlite.*;
import android.os.*;
import android.text.*;
import android.text.method.*;
import android.view.*;
import android.view.MenuItem.*;
import android.widget.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*
*/
class IntroTextDialog extends Dialog {
private PackageInfo packageInfo;
private VncDatabase database;
static IntroTextDialog dialog;
static void showIntroTextIfNecessary(Activity context, VncDatabase database)
{
PackageInfo pi;
try
{
pi = context.getPackageManager().getPackageInfo("android.androidVNC", 0);
}
catch (PackageManager.NameNotFoundException nnfe)
{
return;
}
MostRecentBean mr = androidVNC.getMostRecent(database.getReadableDatabase());
if (mr == null || mr.getShowSplashVersion() != pi.versionCode)
{
if (dialog == null)
{
dialog = new IntroTextDialog(context, pi, database);
dialog.show();
}
}
}
/**
* @param context -- Containing dialog
*/
private IntroTextDialog(Activity context, PackageInfo pi, VncDatabase database) {
super(context);
setOwnerActivity(context);
packageInfo = pi;
this.database = database;
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intro_dialog);
StringBuilder sb = new StringBuilder(getContext().getResources().getString(R.string.intro_title));
sb.append(" ");
sb.append(packageInfo.versionName);
setTitle(sb);
sb.delete(0, sb.length());
sb.append(getContext().getResources().getString(R.string.intro_text));
sb.append(packageInfo.versionName);
sb.append(getContext().getResources().getString(R.string.intro_version_text));
TextView introTextView = (TextView)findViewById(R.id.textIntroText);
introTextView.setText(Html.fromHtml(sb.toString()));
introTextView.setMovementMethod(LinkMovementMethod.getInstance());
((Button)findViewById(R.id.buttonCloseIntro)).setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
dismiss();
}
});
((Button)findViewById(R.id.buttonCloseIntroDontShow)).setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
dontShowAgain();
}
});
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getOwnerActivity().getMenuInflater().inflate(R.menu.intro_dialog_menu,menu);
menu.findItem(R.id.itemOpenDoc).setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Utils.showDocumentation(getOwnerActivity());
dismiss();
return true;
}
});
menu.findItem(R.id.itemClose).setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
dismiss();
return true;
}
});
menu.findItem(R.id.itemDontShowAgain).setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
dontShowAgain();
return true;
}
});
return true;
}
private void dontShowAgain()
{
SQLiteDatabase db = database.getWritableDatabase();
MostRecentBean mostRecent = androidVNC.getMostRecent(db);
if (mostRecent != null)
{
mostRecent.setShowSplashVersion(packageInfo.versionCode);
mostRecent.Gen_update(db);
}
dismiss();
}
}

View File

@@ -0,0 +1,318 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import java.io.IOException;
import com.antlersoft.android.drawing.OverlappingCopy;
import com.antlersoft.android.drawing.RectList;
import com.antlersoft.util.ObjectPool;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
/**
* @author Michael A. MacDonald
*
*/
class LargeBitmapData extends AbstractBitmapData {
/**
* Multiply this times total number of pixels to get estimate of process size with all buffers plus
* safety factor
*/
static final int CAPACITY_MULTIPLIER = 21;
int xoffset;
int yoffset;
int scrolledToX;
int scrolledToY;
private Rect bitmapRect;
private Paint defaultPaint;
private RectList invalidList;
private RectList pendingList;
/**
* Pool of temporary rectangle objects. Need to synchronize externally access from
* multiple threads.
*/
private static ObjectPool<Rect> rectPool = new ObjectPool<Rect>() {
/* (non-Javadoc)
* @see com.antlersoft.util.ObjectPool#itemForPool()
*/
@Override
protected Rect itemForPool() {
return new Rect();
}
};
class LargeBitmapDrawable extends AbstractBitmapDrawable
{
LargeBitmapDrawable()
{
super(LargeBitmapData.this);
}
/* (non-Javadoc)
* @see android.graphics.drawable.DrawableContainer#draw(android.graphics.Canvas)
*/
@Override
public void draw(Canvas canvas) {
//android.util.Log.i("LBM", "Drawing "+xoffset+" "+yoffset);
int xoff, yoff;
synchronized ( LargeBitmapData.this )
{
xoff=xoffset;
yoff=yoffset;
}
draw(canvas, xoff, yoff);
}
}
/**
*
* @param p Protocol implementation
* @param c View that will display screen
* @param displayWidth
* @param displayHeight
* @param capacity Max process heap size in bytes
*/
LargeBitmapData(RfbProto p, VncCanvas c, int displayWidth, int displayHeight, int capacity)
{
super(p,c);
double scaleMultiplier = Math.sqrt((double)(capacity * 1024 * 1024) / (double)(CAPACITY_MULTIPLIER * framebufferwidth * framebufferheight));
if (scaleMultiplier > 1)
scaleMultiplier = 1;
bitmapwidth=(int)((double)framebufferwidth * scaleMultiplier);
if (bitmapwidth < displayWidth)
bitmapwidth = displayWidth;
bitmapheight=(int)((double)framebufferheight * scaleMultiplier);
if (bitmapheight < displayHeight)
bitmapheight = displayHeight;
android.util.Log.i("LBM", "bitmapsize = ("+bitmapwidth+","+bitmapheight+")");
mbitmap = Bitmap.createBitmap(bitmapwidth, bitmapheight, Bitmap.Config.RGB_565);
memGraphics = new Canvas(mbitmap);
bitmapPixels = new int[bitmapwidth * bitmapheight];
invalidList = new RectList(rectPool);
pendingList = new RectList(rectPool);
bitmapRect=new Rect(0,0,bitmapwidth,bitmapheight);
defaultPaint = new Paint();
}
@Override
AbstractBitmapDrawable createDrawable()
{
return new LargeBitmapDrawable();
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#copyRect(android.graphics.Rect, android.graphics.Rect, android.graphics.Paint)
*/
@Override
void copyRect(Rect src, Rect dest, Paint paint) {
// TODO copy rect working?
throw new RuntimeException( "copyrect Not implemented");
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#drawRect(int, int, int, int, android.graphics.Paint)
*/
@Override
void drawRect(int x, int y, int w, int h, Paint paint) {
x-=xoffset;
y-=yoffset;
memGraphics.drawRect(x, y, x+w, y+h, paint);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#offset(int, int)
*/
@Override
int offset(int x, int y) {
return (y - yoffset) * bitmapwidth + x - xoffset;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#scrollChanged(int, int)
*/
@Override
synchronized void scrollChanged(int newx, int newy) {
//android.util.Log.i("LBM","scroll "+newx+" "+newy);
int newScrolledToX = scrolledToX;
int newScrolledToY = scrolledToY;
int visibleWidth = vncCanvas.getVisibleWidth();
int visibleHeight = vncCanvas.getVisibleHeight();
if (newx - xoffset < 0 )
{
newScrolledToX = newx + visibleWidth / 2 - bitmapwidth / 2;
if (newScrolledToX < 0)
newScrolledToX = 0;
}
else if (newx - xoffset + visibleWidth > bitmapwidth)
{
newScrolledToX = newx + visibleWidth / 2 - bitmapwidth / 2;
if (newScrolledToX + bitmapwidth > framebufferwidth)
newScrolledToX = framebufferwidth - bitmapwidth;
}
if (newy - yoffset < 0 )
{
newScrolledToY = newy + visibleHeight / 2 - bitmapheight / 2;
if (newScrolledToY < 0)
newScrolledToY = 0;
}
else if (newy - yoffset + visibleHeight > bitmapheight)
{
newScrolledToY = newy + visibleHeight / 2 - bitmapheight / 2;
if (newScrolledToY + bitmapheight > framebufferheight)
newScrolledToY = framebufferheight - bitmapheight;
}
if (newScrolledToX != scrolledToX || newScrolledToY != scrolledToY)
{
scrolledToX = newScrolledToX;
scrolledToY = newScrolledToY;
if ( waitingForInput)
syncScroll();
}
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#updateBitmap(int, int, int, int)
*/
@Override
void updateBitmap(int x, int y, int w, int h) {
mbitmap.setPixels(bitmapPixels, offset(x,y), bitmapwidth, x-xoffset, y-yoffset, w, h);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#validDraw(int, int, int, int)
*/
@Override
synchronized boolean validDraw(int x, int y, int w, int h) {
//android.util.Log.i("LBM", "Validate Drawing "+x+" "+y+" "+w+" "+h+" "+xoffset+" "+yoffset+" "+(x-xoffset>=0 && x-xoffset+w<=bitmapwidth && y-yoffset>=0 && y-yoffset+h<=bitmapheight));
boolean result = x-xoffset>=0 && x-xoffset+w<=bitmapwidth && y-yoffset>=0 && y-yoffset+h<=bitmapheight;
ObjectPool.Entry<Rect> entry = rectPool.reserve();
Rect r = entry.get();
r.set(x, y, x+w, y+h);
pendingList.subtract(r);
if ( ! result)
{
invalidList.add(r);
}
else
invalidList.subtract(r);
rectPool.release(entry);
return result;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#writeFullUpdateRequest(boolean)
*/
@Override
synchronized void writeFullUpdateRequest(boolean incremental) throws IOException {
if (! incremental) {
ObjectPool.Entry<Rect> entry = rectPool.reserve();
Rect r = entry.get();
r.left=xoffset;
r.top=yoffset;
r.right=xoffset + bitmapwidth;
r.bottom=yoffset + bitmapheight;
pendingList.add(r);
invalidList.add(r);
rectPool.release(entry);
}
rfb.writeFramebufferUpdateRequest(xoffset, yoffset, bitmapwidth, bitmapheight, incremental);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractBitmapData#syncScroll()
*/
@Override
synchronized void syncScroll() {
int deltaX = xoffset - scrolledToX;
int deltaY = yoffset - scrolledToY;
xoffset=scrolledToX;
yoffset=scrolledToY;
bitmapRect.top=scrolledToY;
bitmapRect.bottom=scrolledToY+bitmapheight;
bitmapRect.left=scrolledToX;
bitmapRect.right=scrolledToX+bitmapwidth;
invalidList.intersect(bitmapRect);
if ( deltaX != 0 || deltaY != 0)
{
boolean didOverlapping = false;
if (Math.abs(deltaX) < bitmapwidth && Math.abs(deltaY) < bitmapheight) {
ObjectPool.Entry<Rect> sourceEntry = rectPool.reserve();
ObjectPool.Entry<Rect> addedEntry = rectPool.reserve();
try
{
Rect added = addedEntry.get();
Rect sourceRect = sourceEntry.get();
sourceRect.set(deltaX<0 ? -deltaX : 0,
deltaY<0 ? -deltaY : 0,
deltaX<0 ? bitmapwidth : bitmapwidth - deltaX,
deltaY < 0 ? bitmapheight : bitmapheight - deltaY);
if (! invalidList.testIntersect(sourceRect)) {
didOverlapping = true;
OverlappingCopy.Copy(mbitmap, memGraphics, defaultPaint, sourceRect, deltaX + sourceRect.left, deltaY + sourceRect.top, rectPool);
// Write request for side pixels
if (deltaX != 0) {
added.left = deltaX < 0 ? bitmapRect.right + deltaX : bitmapRect.left;
added.right = added.left + Math.abs(deltaX);
added.top = bitmapRect.top;
added.bottom = bitmapRect.bottom;
invalidList.add(added);
}
if (deltaY != 0) {
added.left = deltaX < 0 ? bitmapRect.left : bitmapRect.left + deltaX;
added.top = deltaY < 0 ? bitmapRect.bottom + deltaY : bitmapRect.top;
added.right = added.left + bitmapwidth - Math.abs(deltaX);
added.bottom = added.top + Math.abs(deltaY);
invalidList.add(added);
}
}
}
finally {
rectPool.release(addedEntry);
rectPool.release(sourceEntry);
}
}
if (! didOverlapping)
{
try
{
//android.util.Log.i("LBM","update req "+xoffset+" "+yoffset);
mbitmap.eraseColor(Color.GREEN);
writeFullUpdateRequest(false);
}
catch ( IOException ioe)
{
// TODO log this
}
}
}
int size = pendingList.getSize();
for (int i=0; i<size; i++) {
invalidList.subtract(pendingList.get(i));
}
size = invalidList.getSize();
for (int i=0; i<size; i++) {
Rect invalidRect = invalidList.get(i);
try
{
rfb.writeFramebufferUpdateRequest(invalidRect.left, invalidRect.top, invalidRect.right-invalidRect.left, invalidRect.bottom-invalidRect.top, false);
pendingList.add(invalidRect);
}
catch (IOException ioe)
{
//TODO Log this
}
}
waitingForInput=true;
//android.util.Log.i("LBM", "pending "+pendingList.toString() + "invalid "+invalidList.toString());
}
}

View File

@@ -0,0 +1,33 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package android.androidVNC;
public class MemInStream extends InStream {
public MemInStream(byte[] data, int offset, int len) {
b = data;
ptr = offset;
end = offset + len;
}
public int pos() { return ptr; }
protected int overrun(int itemSize, int nItems) throws Exception {
throw new Exception("MemInStream overrun: end of stream");
}
}

View File

@@ -0,0 +1,50 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
/**
* @author Michael A. MacDonald
*
*/
class MetaKeyBase implements Comparable<MetaKeyBase> {
int keySym;
int mouseButtons;
int keyEvent;
String name;
boolean isMouse;
boolean isKeyEvent;
MetaKeyBase(int mouseButtons, String name)
{
this.mouseButtons = mouseButtons;
this.name = name;
this.isMouse = true;
this.isKeyEvent = false;
}
MetaKeyBase(String name, int keySym, int keyEvent)
{
this.name = name;
this.keySym = keySym;
this.keyEvent = keyEvent;
this.isMouse = false;
this.isKeyEvent = true;
}
MetaKeyBase(String name, int keySym)
{
this.name = name;
this.keySym = keySym;
this.isMouse = false;
this.isKeyEvent = false;
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(MetaKeyBase another) {
return name.compareTo(another.name);
}
}

View File

@@ -0,0 +1,269 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import java.util.ArrayList;
import java.util.HashMap;
import com.antlersoft.android.dbimpl.NewInstance;
import android.view.KeyEvent;
/**
* @author Michael A. MacDonald
*
*/
class MetaKeyBean extends AbstractMetaKeyBean implements Comparable<MetaKeyBean> {
static final ArrayList<MetaKeyBase> allKeys;
static final String[] allKeysNames;
static final HashMap<Integer,MetaKeyBase> keysByKeyCode;
static final HashMap<Integer,MetaKeyBase> keysByMouseButton;
static final HashMap<Integer,MetaKeyBase> keysByKeySym;
static final MetaKeyBean keyCtrlAltDel;
static final MetaKeyBean keyArrowLeft;
static final MetaKeyBean keyArrowRight;
static final MetaKeyBean keyArrowUp;
static final MetaKeyBean keyArrowDown;
static final NewInstance<MetaKeyBean> NEW;
static {
allKeys = new ArrayList<MetaKeyBase>();
allKeys.add(new MetaKeyBase("Hangul", 0xff31));
allKeys.add(new MetaKeyBase("Hangul_Start", 0xff32));
allKeys.add(new MetaKeyBase("Hangul_End", 0xff33));
allKeys.add(new MetaKeyBase("Hangul_Hanja", 0xff34));
allKeys.add(new MetaKeyBase("Kana_Shift", 0xff2e));
allKeys.add(new MetaKeyBase("Right_Alt", 0xffea));
allKeys.add(new MetaKeyBase(VncCanvas.MOUSE_BUTTON_LEFT,"Mouse Left"));
allKeys.add(new MetaKeyBase(VncCanvas.MOUSE_BUTTON_MIDDLE,"Mouse Middle"));
allKeys.add(new MetaKeyBase(VncCanvas.MOUSE_BUTTON_RIGHT,"Mouse Right"));
allKeys.add(new MetaKeyBase(VncCanvas.MOUSE_BUTTON_SCROLL_DOWN, "Mouse Scroll Down"));
allKeys.add(new MetaKeyBase(VncCanvas.MOUSE_BUTTON_SCROLL_UP, "Mouse Scroll Up"));
allKeys.add(new MetaKeyBase("Home", 0xFF50));
allKeys.add(new MetaKeyBase("Arrow Left", 0xFF51));
allKeys.add(new MetaKeyBase("Arrow Up", 0xFF52));
allKeys.add(new MetaKeyBase("Arrow Right", 0xFF53));
allKeys.add(new MetaKeyBase("Arrow Down", 0xFF54));
allKeys.add(new MetaKeyBase("Page Up", 0xFF55));
allKeys.add(new MetaKeyBase("Page Down", 0xFF56));
allKeys.add(new MetaKeyBase("End", 0xFF57));
allKeys.add(new MetaKeyBase("Insert", 0xFF63));
allKeys.add(new MetaKeyBase("Delete", 0xFFFF, KeyEvent.KEYCODE_DEL));
allKeys.add(new MetaKeyBase("Num Lock", 0xFF7F));
allKeys.add(new MetaKeyBase("Break", 0xFF6b));
allKeys.add(new MetaKeyBase("Scroll Lock", 0xFF14));
allKeys.add(new MetaKeyBase("Print Scrn", 0xFF15));
allKeys.add(new MetaKeyBase("Escape", 0xFF1B));
allKeys.add(new MetaKeyBase("Enter", 0xFF0D, KeyEvent.KEYCODE_ENTER));
allKeys.add(new MetaKeyBase("Tab", 0xFF09, KeyEvent.KEYCODE_TAB));
allKeys.add(new MetaKeyBase("BackSpace", 0xFF08));
allKeys.add(new MetaKeyBase("Space", 0x020, KeyEvent.KEYCODE_SPACE));
StringBuilder sb = new StringBuilder(" ");
for (int i=0; i<26; i++)
{
sb.setCharAt(0, (char)('A' + i));
allKeys.add(new MetaKeyBase(sb.toString(), 'a' + i, KeyEvent.KEYCODE_A + i));
}
for (int i=0; i<10; i++)
{
sb.setCharAt(0, (char)('0' + i));
allKeys.add(new MetaKeyBase(sb.toString(), '0' + i, KeyEvent.KEYCODE_0 + i));
}
for (int i=0; i<12; i++)
{
sb.setLength(0);
sb.append('F');
if (i<9)
sb.append(' ');
sb.append(Integer.toString(i+1));
allKeys.add(new MetaKeyBase(sb.toString(), 0xFFBE + i));
}
java.util.Collections.sort(allKeys);
allKeysNames = new String[allKeys.size()];
keysByKeyCode = new HashMap<Integer,MetaKeyBase>();
keysByMouseButton = new HashMap<Integer,MetaKeyBase>();
keysByKeySym = new HashMap<Integer,MetaKeyBase>();
for (int i=0; i<allKeysNames.length; ++i)
{
MetaKeyBase b=allKeys.get(i);
allKeysNames[i] = b.name;
if (b.isKeyEvent)
keysByKeyCode.put(b.keyEvent,b);
if (b.isMouse)
keysByMouseButton.put(b.mouseButtons,b);
else
keysByKeySym.put(b.keySym,b);
}
NEW = new NewInstance<MetaKeyBean>() {
/* (non-Javadoc)
* @see com.antlersoft.android.dbimpl.NewInstance#get()
*/
@Override
public MetaKeyBean get() {
return new MetaKeyBean();
}
};
keyCtrlAltDel = new MetaKeyBean(0,VncCanvas.CTRL_MASK|VncCanvas.ALT_MASK,keysByKeyCode.get(KeyEvent.KEYCODE_DEL));
keyArrowLeft = new MetaKeyBean(0,0,keysByKeySym.get(0xFF51));
keyArrowUp = new MetaKeyBean(0,0,keysByKeySym.get(0xFF52));
keyArrowRight = new MetaKeyBean(0,0,keysByKeySym.get(0xFF53));
keyArrowDown = new MetaKeyBean(0,0,keysByKeySym.get(0xFF54));
}
private boolean _regenDesc;
MetaKeyBean()
{
}
MetaKeyBean(MetaKeyBean toCopy)
{
_regenDesc = true;
if (toCopy.isMouseClick())
setMouseButtons(toCopy.getMouseButtons());
else
setKeySym(toCopy.getKeySym());
setMetaListId(toCopy.getMetaListId());
setMetaFlags(toCopy.getMetaFlags());
}
MetaKeyBean(long listId, int metaFlags, MetaKeyBase base)
{
setMetaListId(listId);
setKeyBase(base);
setMetaFlags(metaFlags);
_regenDesc = true;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractMetaKeyBean#getKeyDesc()
*/
@Override
public String getKeyDesc() {
if (_regenDesc)
{
synchronized(this)
{
if (_regenDesc)
{
StringBuilder sb=new StringBuilder();
int meta=getMetaFlags();
if (0 != (meta & VncCanvas.SHIFT_MASK))
{
sb.append("Shift");
}
if (0 != (meta & VncCanvas.CTRL_MASK))
{
if (sb.length()>0)
sb.append('-');
sb.append("Ctrl");
}
if (0 != (meta & VncCanvas.ALT_MASK))
{
if (sb.length()>0)
sb.append('-');
sb.append("Alt");
}
if (sb.length()>0)
sb.append(' ');
MetaKeyBase base;
if (isMouseClick())
base=keysByMouseButton.get(getMouseButtons());
else
base=keysByKeySym.get(getKeySym());
sb.append(base.name);
setKeyDesc(sb.toString());
}
}
}
return super.getKeyDesc();
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractMetaKeyBean#setKeyDesc(java.lang.String)
*/
@Override
public void setKeyDesc(String arg_keyDesc) {
super.setKeyDesc(arg_keyDesc);
_regenDesc = false;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractMetaKeyBean#setKeySym(int)
*/
@Override
public void setKeySym(int arg_keySym) {
if (arg_keySym!=getKeySym() || isMouseClick())
{
setMouseClick(false);
_regenDesc=true;
super.setKeySym(arg_keySym);
}
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractMetaKeyBean#setMetaFlags(int)
*/
@Override
public void setMetaFlags(int arg_metaFlags) {
if (arg_metaFlags != getMetaFlags())
{
_regenDesc = true;
super.setMetaFlags(arg_metaFlags);
}
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractMetaKeyBean#setMouseButtons(int)
*/
@Override
public void setMouseButtons(int arg_mouseButtons) {
if (arg_mouseButtons!=getMouseButtons() || ! isMouseClick())
{
setMouseClick(true);
_regenDesc = true;
super.setMouseButtons(arg_mouseButtons);
}
}
void setKeyBase(MetaKeyBase base)
{
if (base.isMouse)
{
setMouseButtons(base.mouseButtons);
}
else
{
setKeySym(base.keySym);
}
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object o) {
if (o instanceof MetaKeyBean)
{
return getKeyDesc().equals(((MetaKeyBean)o).getKeyDesc());
}
return false;
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(MetaKeyBean another) {
return getKeyDesc().compareTo(another.getKeyDesc());
}
}

View File

@@ -0,0 +1,602 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.app.*;
import android.content.*;
import android.database.*;
import android.database.sqlite.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.widget.AdapterView.*;
import android.widget.CompoundButton.*;
import java.text.*;
import java.util.*;
import java.util.Map.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*
*/
class MetaKeyDialog extends Dialog implements ConnectionSettable {
CheckBox _checkShift;
CheckBox _checkCtrl;
CheckBox _checkAlt;
TextView _textKeyDesc;
EditText _textListName;
Spinner _spinnerKeySelect;
Spinner _spinnerKeysInList;
Spinner _spinnerLists;
VncDatabase _database;
static ArrayList<MetaList> _lists;
ArrayList<MetaKeyBean> _keysInList;
long _listId;
VncCanvasActivity _canvasActivity;
MetaKeyBean _currentKeyBean;
static final String[] EMPTY_ARGS = new String[0];
ConnectionBean _connection;
/**
* @param context
*/
public MetaKeyDialog(Context context) {
super(context);
setOwnerActivity((Activity)context);
_canvasActivity = (VncCanvasActivity)context;
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
_canvasActivity.getMenuInflater().inflate(R.menu.metakeymenu, menu);
menu.findItem(R.id.itemDeleteKeyList).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
/* (non-Javadoc)
* @see android.view.MenuItem.OnMenuItemClickListener#onMenuItemClick(android.view.MenuItem)
*/
@Override
public boolean onMenuItemClick(MenuItem item) {
Utils.showYesNoPrompt(_canvasActivity, "Delete key list",
"Delete list "+_textListName.getText().toString(),
new OnClickListener() {
/* (non-Javadoc)
* @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int)
*/
@Override
public void onClick(DialogInterface dialog, int which) {
int position = _spinnerLists.getSelectedItemPosition();
if (position == Spinner.INVALID_POSITION)
return;
_listId = _lists.get(position).get_Id();
if (_listId > 1)
{
_lists.remove(position);
ArrayAdapter<String> adapter = getSpinnerAdapter(_spinnerLists);
adapter.remove(adapter.getItem(position));
SQLiteDatabase db = _database.getWritableDatabase();
db.execSQL(MessageFormat.format("DELETE FROM {0} WHERE {1} = {2}",
MetaKeyBean.GEN_TABLE_NAME, MetaKeyBean.GEN_FIELD_METALISTID,
_listId));
db.execSQL(MessageFormat.format("DELETE FROM {0} WHERE {1} = {2}",
MetaList.GEN_TABLE_NAME, MetaList.GEN_FIELD__ID,
_listId));
_connection.setMetaListId(1);
_connection.save(db);
setMetaKeyList();
}
}
},
null);
return true;
}
});
menu.findItem(R.id.itemDeleteKey).setOnMenuItemClickListener(
new MenuItem.OnMenuItemClickListener() {
/* (non-Javadoc)
* @see android.view.MenuItem.OnMenuItemClickListener#onMenuItemClick(android.view.MenuItem)
*/
@Override
public boolean onMenuItemClick(MenuItem item) {
final int position = _spinnerKeysInList.getSelectedItemPosition();
if (position != Spinner.INVALID_POSITION)
{
final MetaKeyBean toDelete = _keysInList.get(position);
Utils.showYesNoPrompt(_canvasActivity, "Delete from list",
"Delete key " + toDelete.getKeyDesc(),
new OnClickListener() {
/* (non-Javadoc)
* @see android.content.DialogInterface.OnClickListener#onClick(android.content.DialogInterface, int)
*/
@Override
public void onClick(DialogInterface dialog, int which) {
getSpinnerAdapter(_spinnerKeysInList).remove(toDelete.getKeyDesc());
_keysInList.remove(position);
SQLiteDatabase db = _database.getWritableDatabase();
db.execSQL(
MessageFormat.format("DELETE FROM {0} WHERE {1} = {2}",
MetaKeyBean.GEN_TABLE_NAME, MetaKeyBean.GEN_FIELD_METALISTID,
toDelete.get_Id())
);
if (_connection.getLastMetaKeyId() == toDelete.get_Id())
{
_connection.setLastMetaKeyId(0);
_connection.save(db);
}
int newPos = _spinnerKeysInList.getSelectedItemPosition();
if (newPos != Spinner.INVALID_POSITION && newPos < _keysInList.size())
{
_currentKeyBean = new MetaKeyBean(_keysInList.get(newPos));
updateDialogForCurrentKey();
}
}
},
null);
}
return true;
}
});
return true;
}
/* (non-Javadoc)
* @see android.app.Dialog#onMenuOpened(int, android.view.Menu)
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.itemDeleteKeyList).setEnabled(_currentKeyBean.getMetaListId()>1);
menu.findItem(R.id.itemDeleteKey).setEnabled(_spinnerKeysInList.getSelectedItemPosition()!=Spinner.INVALID_POSITION);
return true;
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.metakey);
setTitle(R.string.meta_key_title);
_checkShift = (CheckBox)findViewById(R.id.checkboxShift);
_checkCtrl = (CheckBox)findViewById(R.id.checkboxCtrl);
_checkAlt = (CheckBox)findViewById(R.id.checkboxAlt);
_textKeyDesc = (TextView)findViewById(R.id.textKeyDesc);
_textListName = (EditText)findViewById(R.id.textListName);
_spinnerKeySelect = (Spinner)findViewById(R.id.spinnerKeySelect);
_spinnerKeysInList = (Spinner)findViewById(R.id.spinnerKeysInList);
_spinnerLists = (Spinner)findViewById(R.id.spinnerLists);
_database = _canvasActivity.database;
if (_lists == null) {
_lists = new ArrayList<MetaList>();
MetaList.getAll(_database.getReadableDatabase(), MetaList.GEN_TABLE_NAME, _lists, MetaList.GEN_NEW);
}
_spinnerKeySelect.setAdapter(new ArrayAdapter<String>(getOwnerActivity(), android.R.layout.simple_spinner_item, MetaKeyBean.allKeysNames));
_spinnerKeySelect.setSelection(0);
setListSpinner();
_checkShift.setOnCheckedChangeListener(new MetaCheckListener(VncCanvas.SHIFT_MASK));
_checkAlt.setOnCheckedChangeListener(new MetaCheckListener(VncCanvas.ALT_MASK));
_checkCtrl.setOnCheckedChangeListener(new MetaCheckListener(VncCanvas.CTRL_MASK));
_spinnerLists.setOnItemSelectedListener(new OnItemSelectedListener() {
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long)
*/
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
_connection.setMetaListId(_lists.get(position).get_Id());
_connection.Gen_update(_database.getWritableDatabase());
setMetaKeyList();
}
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView)
*/
public void onNothingSelected(AdapterView<?> parent) {
}
});
_spinnerKeysInList.setOnItemSelectedListener(new OnItemSelectedListener() {
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long)
*/
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
_currentKeyBean = new MetaKeyBean(_keysInList.get(position));
updateDialogForCurrentKey();
}
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView)
*/
public void onNothingSelected(AdapterView<?> parent) {
}
});
_spinnerKeySelect.setOnItemSelectedListener(new OnItemSelectedListener() {
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long)
*/
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
if (_currentKeyBean == null) {
_currentKeyBean = new MetaKeyBean(0,0,MetaKeyBean.allKeys.get(position));
}
else {
_currentKeyBean.setKeyBase(MetaKeyBean.allKeys.get(position));
}
updateDialogForCurrentKey();
}
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView)
*/
public void onNothingSelected(AdapterView<?> parent) {
}
});
((Button)findViewById(R.id.buttonSend)).setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
public void onClick(View v) {
sendCurrentKey();
dismiss();
}
});
((Button)findViewById(R.id.buttonNewList)).setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
MetaList newList = new MetaList();
newList.setName("New");
SQLiteDatabase db = _database.getWritableDatabase();
newList.Gen_insert(db);
_connection.setMetaListId(newList.get_Id());
_connection.save(db);
_lists.add(newList);
getSpinnerAdapter(_spinnerLists).add(newList.getName());
setMetaKeyList();
}
});
((Button)findViewById(R.id.buttonCopyList)).setOnClickListener(new View.OnClickListener() {
/* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
MetaList newList = new MetaList();
newList.setName("Copy of " + _textListName.getText().toString());
SQLiteDatabase db = _database.getWritableDatabase();
newList.Gen_insert(db);
db.execSQL(MessageFormat.format(getCopyListString(), newList.get_Id(), _listId));
_connection.setMetaListId(newList.get_Id());
_connection.save(db);
_lists.add(newList);
getSpinnerAdapter(_spinnerLists).add(newList.getName());
setMetaKeyList();
}
});
}
private static String copyListString;
private String getCopyListString()
{
if (copyListString==null)
{
StringBuilder sb = new StringBuilder("INSERT INTO ");
sb.append(MetaKeyBean.GEN_TABLE_NAME);
sb.append(" ( ");
sb.append(MetaKeyBean.GEN_FIELD_METALISTID);
StringBuilder fieldList = new StringBuilder();
for (Entry<String,Object> s : _currentKeyBean.Gen_getValues().valueSet())
{
if (!s.getKey().equals(MetaKeyBean.GEN_FIELD__ID) && !s.getKey().equals(MetaKeyBean.GEN_FIELD_METALISTID)) {
fieldList.append(',');
fieldList.append(s.getKey());
}
}
String fl = fieldList.toString();
sb.append(fl);
sb.append(" ) SELECT {0} ");
sb.append(fl);
sb.append(" FROM ");
sb.append(MetaKeyBean.GEN_TABLE_NAME);
sb.append(" WHERE ");
sb.append(MetaKeyBean.GEN_FIELD_METALISTID);
sb.append(" = {1}");
copyListString = sb.toString();
}
return copyListString;
}
private boolean _justStarted;
/* (non-Javadoc)
* @see android.app.Dialog#onStart()
*/
@Override
protected void onStart() {
takeKeyEvents(true);
_justStarted = true;
super.onStart();
View v = getCurrentFocus();
if (v!=null)
v.clearFocus();
}
/* (non-Javadoc)
* @see android.app.Dialog#onStop()
*/
@Override
protected void onStop() {
int i = 0;
for (MetaList l : _lists)
{
if (l.get_Id() == _listId)
{
String s = _textListName.getText().toString();
if (! s.equals(l.getName()))
{
l.setName(s);
l.Gen_update(_database.getWritableDatabase());
ArrayAdapter<String> adapter = getSpinnerAdapter(_spinnerLists);
adapter.remove(adapter.getItem(i));
adapter.insert(s,i);
}
break;
}
i++;
}
takeKeyEvents(false);
super.onStop();
}
/* (non-Javadoc)
* @see android.app.Dialog#onKeyDown(int, android.view.KeyEvent)
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
_justStarted = false;
if (keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_MENU && getCurrentFocus() == null)
{
int flags = event.getMetaState();
int currentFlags = _currentKeyBean.getMetaFlags();
MetaKeyBase base = MetaKeyBean.keysByKeyCode.get(keyCode);
if (base != null)
{
if (0 != (flags & KeyEvent.META_SHIFT_ON))
{
currentFlags |= VncCanvas.SHIFT_MASK;
}
if (0 != (flags & KeyEvent.META_ALT_ON))
{
currentFlags |= VncCanvas.ALT_MASK;
}
_currentKeyBean.setKeyBase(base);
}
else
{
// Toggle flags according to meta keys
if (0 != (flags & KeyEvent.META_SHIFT_ON))
{
currentFlags ^= VncCanvas.SHIFT_MASK;
}
if (0 != (flags & KeyEvent.META_ALT_ON))
{
currentFlags ^= VncCanvas.ALT_MASK;
}
if (keyCode == KeyEvent.KEYCODE_SEARCH)
{
currentFlags ^= VncCanvas.CTRL_MASK;
}
}
_currentKeyBean.setMetaFlags(currentFlags);
updateDialogForCurrentKey();
return true;
}
return super.onKeyDown(keyCode, event);
}
/* (non-Javadoc)
* @see android.app.Dialog#onKeyUp(int, android.view.KeyEvent)
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (! _justStarted && keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_MENU && getCurrentFocus()==null)
{
if (MetaKeyBean.keysByKeyCode.get(keyCode) != null)
{
sendCurrentKey();
dismiss();
}
return true;
}
_justStarted = false;
return super.onKeyUp(keyCode, event);
}
@SuppressWarnings("unchecked")
private static ArrayAdapter<String> getSpinnerAdapter(Spinner spinner)
{
return (ArrayAdapter<String>)spinner.getAdapter();
}
void sendCurrentKey()
{
int index = Collections.binarySearch(_keysInList, _currentKeyBean);
SQLiteDatabase db = _database.getWritableDatabase();
if (index < 0)
{
int insertionPoint = -(index + 1);
_currentKeyBean.Gen_insert(db);
_keysInList.add(insertionPoint,_currentKeyBean);
getSpinnerAdapter(_spinnerKeysInList).insert(_currentKeyBean.getKeyDesc(), insertionPoint);
_spinnerKeysInList.setSelection(insertionPoint);
_connection.setLastMetaKeyId(_currentKeyBean.get_Id());
}
else
{
MetaKeyBean bean = _keysInList.get(index);
_connection.setLastMetaKeyId(bean.get_Id());
_spinnerKeysInList.setSelection(index);
}
_connection.Gen_update(db);
_canvasActivity.vncCanvas.sendMetaKey(_currentKeyBean);
}
void setMetaKeyList()
{
long listId = _connection.getMetaListId();
if (listId!=_listId) {
for (int i=0; i<_lists.size(); ++i)
{
MetaList list = _lists.get(i);
if (list.get_Id()==listId)
{
_spinnerLists.setSelection(i);
_keysInList = new ArrayList<MetaKeyBean>();
Cursor c = _database.getReadableDatabase().rawQuery(
MessageFormat.format("SELECT * FROM {0} WHERE {1} = {2} ORDER BY KEYDESC",
MetaKeyBean.GEN_TABLE_NAME,
MetaKeyBean.GEN_FIELD_METALISTID,
listId),
EMPTY_ARGS);
MetaKeyBean.Gen_populateFromCursor(
c,
_keysInList,
MetaKeyBean.NEW);
c.close();
ArrayList<String> keys = new ArrayList<String>(_keysInList.size());
int selectedOffset = 0;
long lastSelectedKeyId = _canvasActivity.getConnection().getLastMetaKeyId();
for (int j=0; j<_keysInList.size(); j++)
{
MetaKeyBean key = _keysInList.get(j);
keys.add( key.getKeyDesc());
if (lastSelectedKeyId==key.get_Id())
{
selectedOffset = j;
}
}
_spinnerKeysInList.setAdapter(new ArrayAdapter<String>(getOwnerActivity(), android.R.layout.simple_spinner_item, keys));
if (keys.size()>0)
{
_spinnerKeysInList.setSelection(selectedOffset);
_currentKeyBean = new MetaKeyBean(_keysInList.get(selectedOffset));
}
else
{
_currentKeyBean = new MetaKeyBean(listId, 0, MetaKeyBean.allKeys.get(0));
}
updateDialogForCurrentKey();
_textListName.setText(list.getName());
break;
}
}
_listId = listId;
}
}
private void updateDialogForCurrentKey()
{
int flags = _currentKeyBean.getMetaFlags();
_checkAlt.setChecked(0 != (flags & VncCanvas.ALT_MASK));
_checkShift.setChecked(0 != (flags & VncCanvas.SHIFT_MASK));
_checkCtrl.setChecked(0 != (flags & VncCanvas.CTRL_MASK));
MetaKeyBase base = null;
if (_currentKeyBean.isMouseClick())
{
base = MetaKeyBean.keysByMouseButton.get(_currentKeyBean.getMouseButtons());
} else {
base = MetaKeyBean.keysByKeySym.get(_currentKeyBean.getKeySym());
}
if (base != null) {
int index = Collections.binarySearch(MetaKeyBean.allKeys,base);
if (index >= 0) {
_spinnerKeySelect.setSelection(index);
}
}
_textKeyDesc.setText(_currentKeyBean.getKeyDesc());
}
public void setConnection(ConnectionBean conn)
{
if ( _connection != conn) {
_connection = conn;
setMetaKeyList();
}
}
void setListSpinner()
{
ArrayList<String> listNames = new ArrayList<String>(_lists.size());
for (int i=0; i<_lists.size(); ++i)
{
MetaList l = _lists.get(i);
listNames.add(l.getName());
}
_spinnerLists.setAdapter(new ArrayAdapter<String>(getOwnerActivity(),android.R.layout.simple_spinner_item, listNames));
}
/**
* @author Michael A. MacDonald
*
*/
class MetaCheckListener implements OnCheckedChangeListener {
private int _mask;
MetaCheckListener(int mask) {
_mask = mask;
}
/* (non-Javadoc)
* @see android.widget.CompoundButton.OnCheckedChangeListener#onCheckedChanged(android.widget.CompoundButton, boolean)
*/
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked)
{
_currentKeyBean.setMetaFlags(_currentKeyBean.getMetaFlags() | _mask);
}
else
{
_currentKeyBean.setMetaFlags(_currentKeyBean.getMetaFlags() & ~_mask);
}
_textKeyDesc.setText(_currentKeyBean.getKeyDesc());
}
}
}

View File

@@ -0,0 +1,84 @@
// This class was generated from android.androidVNC.IMetaList by a tool
// Do not edit this file directly! PLX THX
package android.androidVNC;
public class MetaList extends com.antlersoft.android.dbimpl.IdImplementationBase implements IMetaList {
public static final String GEN_TABLE_NAME = "META_LIST";
public static final int GEN_COUNT = 2;
// Field constants
public static final String GEN_FIELD__ID = "_id";
public static final int GEN_ID__ID = 0;
public static final String GEN_FIELD_NAME = "NAME";
public static final int GEN_ID_NAME = 1;
// SQL Command for creating the table
public static String GEN_CREATE = "CREATE TABLE META_LIST (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"NAME TEXT" +
")";
// Members corresponding to defined fields
private long gen__Id;
private java.lang.String gen_name;
public static final com.antlersoft.android.dbimpl.NewInstance<MetaList> GEN_NEW = new com.antlersoft.android.dbimpl.NewInstance<MetaList>() {
public MetaList get() {
return new MetaList();
}
}
;
public String Gen_tableName() { return GEN_TABLE_NAME; }
// Field accessors
public long get_Id() { return gen__Id; }
public void set_Id(long arg__Id) { gen__Id = arg__Id; }
public java.lang.String getName() { return gen_name; }
public void setName(java.lang.String arg_name) { gen_name = arg_name; }
public android.content.ContentValues Gen_getValues() {
android.content.ContentValues values=new android.content.ContentValues();
values.put(GEN_FIELD__ID,Long.toString(this.gen__Id));
values.put(GEN_FIELD_NAME,this.gen_name);
return values;
}
/**
* Return an array that gives the column index in the cursor for each field defined
* @param cursor Database cursor over some columns, possibly including this table
* @return array of column indices; -1 if the column with that id is not in cursor
*/
public int[] Gen_columnIndices(android.database.Cursor cursor) {
int[] result=new int[GEN_COUNT];
result[0] = cursor.getColumnIndex(GEN_FIELD__ID);
// Make compatible with database generated by older version of plugin with uppercase column name
if (result[0] == -1) {
result[0] = cursor.getColumnIndex("_ID");
}
result[1] = cursor.getColumnIndex(GEN_FIELD_NAME);
return result;
}
/**
* Populate one instance from a cursor
*/
public void Gen_populate(android.database.Cursor cursor,int[] columnIndices) {
if ( columnIndices[GEN_ID__ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID__ID])) {
gen__Id = cursor.getLong(columnIndices[GEN_ID__ID]);
}
if ( columnIndices[GEN_ID_NAME] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_NAME])) {
gen_name = cursor.getString(columnIndices[GEN_ID_NAME]);
}
}
/**
* Populate one instance from a ContentValues
*/
public void Gen_populate(android.content.ContentValues values) {
gen__Id = values.getAsLong(GEN_FIELD__ID);
gen_name = values.getAsString(GEN_FIELD_NAME);
}
}

View File

@@ -0,0 +1,108 @@
// This class was generated from android.androidVNC.IMostRecentBean by a tool
// Do not edit this file directly! PLX THX
package android.androidVNC;
public class MostRecentBean extends com.antlersoft.android.dbimpl.IdImplementationBase implements IMostRecentBean {
public static final String GEN_TABLE_NAME = "MOST_RECENT";
public static final int GEN_COUNT = 4;
// Field constants
public static final String GEN_FIELD__ID = "_id";
public static final int GEN_ID__ID = 0;
public static final String GEN_FIELD_CONNECTION_ID = "CONNECTION_ID";
public static final int GEN_ID_CONNECTION_ID = 1;
public static final String GEN_FIELD_SHOW_SPLASH_VERSION = "SHOW_SPLASH_VERSION";
public static final int GEN_ID_SHOW_SPLASH_VERSION = 2;
public static final String GEN_FIELD_TEXT_INDEX = "TEXT_INDEX";
public static final int GEN_ID_TEXT_INDEX = 3;
// SQL Command for creating the table
public static String GEN_CREATE = "CREATE TABLE MOST_RECENT (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"CONNECTION_ID INTEGER," +
"SHOW_SPLASH_VERSION INTEGER," +
"TEXT_INDEX INTEGER" +
")";
// Members corresponding to defined fields
private long gen__Id;
private long gen_CONNECTION_ID;
private long gen_SHOW_SPLASH_VERSION;
private long gen_TEXT_INDEX;
public static final com.antlersoft.android.dbimpl.NewInstance<MostRecentBean> GEN_NEW = new com.antlersoft.android.dbimpl.NewInstance<MostRecentBean>() {
public MostRecentBean get() {
return new MostRecentBean();
}
}
;
public String Gen_tableName() { return GEN_TABLE_NAME; }
// Field accessors
public long get_Id() { return gen__Id; }
public void set_Id(long arg__Id) { gen__Id = arg__Id; }
public long getConnectionId() { return gen_CONNECTION_ID; }
public void setConnectionId(long arg_CONNECTION_ID) { gen_CONNECTION_ID = arg_CONNECTION_ID; }
public long getShowSplashVersion() { return gen_SHOW_SPLASH_VERSION; }
public void setShowSplashVersion(long arg_SHOW_SPLASH_VERSION) { gen_SHOW_SPLASH_VERSION = arg_SHOW_SPLASH_VERSION; }
public long getTextIndex() { return gen_TEXT_INDEX; }
public void setTextIndex(long arg_TEXT_INDEX) { gen_TEXT_INDEX = arg_TEXT_INDEX; }
public android.content.ContentValues Gen_getValues() {
android.content.ContentValues values=new android.content.ContentValues();
values.put(GEN_FIELD__ID,Long.toString(this.gen__Id));
values.put(GEN_FIELD_CONNECTION_ID,Long.toString(this.gen_CONNECTION_ID));
values.put(GEN_FIELD_SHOW_SPLASH_VERSION,Long.toString(this.gen_SHOW_SPLASH_VERSION));
values.put(GEN_FIELD_TEXT_INDEX,Long.toString(this.gen_TEXT_INDEX));
return values;
}
/**
* Return an array that gives the column index in the cursor for each field defined
* @param cursor Database cursor over some columns, possibly including this table
* @return array of column indices; -1 if the column with that id is not in cursor
*/
public int[] Gen_columnIndices(android.database.Cursor cursor) {
int[] result=new int[GEN_COUNT];
result[0] = cursor.getColumnIndex(GEN_FIELD__ID);
// Make compatible with database generated by older version of plugin with uppercase column name
if (result[0] == -1) {
result[0] = cursor.getColumnIndex("_ID");
}
result[1] = cursor.getColumnIndex(GEN_FIELD_CONNECTION_ID);
result[2] = cursor.getColumnIndex(GEN_FIELD_SHOW_SPLASH_VERSION);
result[3] = cursor.getColumnIndex(GEN_FIELD_TEXT_INDEX);
return result;
}
/**
* Populate one instance from a cursor
*/
public void Gen_populate(android.database.Cursor cursor,int[] columnIndices) {
if ( columnIndices[GEN_ID__ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID__ID])) {
gen__Id = cursor.getLong(columnIndices[GEN_ID__ID]);
}
if ( columnIndices[GEN_ID_CONNECTION_ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_CONNECTION_ID])) {
gen_CONNECTION_ID = cursor.getLong(columnIndices[GEN_ID_CONNECTION_ID]);
}
if ( columnIndices[GEN_ID_SHOW_SPLASH_VERSION] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_SHOW_SPLASH_VERSION])) {
gen_SHOW_SPLASH_VERSION = cursor.getLong(columnIndices[GEN_ID_SHOW_SPLASH_VERSION]);
}
if ( columnIndices[GEN_ID_TEXT_INDEX] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_TEXT_INDEX])) {
gen_TEXT_INDEX = cursor.getLong(columnIndices[GEN_ID_TEXT_INDEX]);
}
}
/**
* Populate one instance from a ContentValues
*/
public void Gen_populate(android.content.ContentValues values) {
gen__Id = values.getAsLong(GEN_FIELD__ID);
gen_CONNECTION_ID = values.getAsLong(GEN_FIELD_CONNECTION_ID);
gen_SHOW_SPLASH_VERSION = values.getAsLong(GEN_FIELD_SHOW_SPLASH_VERSION);
gen_TEXT_INDEX = values.getAsLong(GEN_FIELD_TEXT_INDEX);
}
}

View File

@@ -0,0 +1,51 @@
/**
* Copyright 2010 Michael A. MacDonald
*/
package android.androidVNC;
import android.os.Handler;
import android.os.SystemClock;
import android.view.MotionEvent;
/**
* Specialization of panner that moves the mouse instead of panning the screen
*
* @author Michael A. MacDonald
*
*/
class MouseMover extends Panner {
public MouseMover(VncCanvasActivity act, Handler hand) {
super(act, hand);
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
long interval = SystemClock.uptimeMillis() - lastSent;
lastSent += interval;
double scale = (double)interval / 50.0;
VncCanvas canvas = activity.vncCanvas;
//Log.v(TAG, String.format("panning %f %d %d", scale, (int)((double)velocity.x * scale), (int)((double)velocity.y * scale)));
if ( canvas.processPointerEvent((int)(canvas.mouseX + ((double)velocity.x * scale)), (int)(canvas.mouseY + ((double)velocity.y * scale)), MotionEvent.ACTION_MOVE, 0, false, false))
{
if (updater.updateVelocity(velocity, interval))
{
handler.postDelayed(this, 50);
}
else
{
//Log.v(TAG, "Updater requests stop");
stop();
}
}
else
{
//Log.v(TAG, "Panning failed");
stop();
}
}
}

View File

@@ -0,0 +1,56 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.widget.ImageView.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*/
class OneToOneScaling extends AbstractScaling {
/**
* @param id
* @param scaleType
*/
public OneToOneScaling() {
super(R.id.itemOneToOne,ScaleType.CENTER);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#getDefaultHandlerId()
*/
@Override
int getDefaultHandlerId() {
return R.id.itemInputTouchPanTrackballMouse;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#isAbleToPan()
*/
@Override
boolean isAbleToPan() {
return true;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#isValidInputMode(int)
*/
@Override
boolean isValidInputMode(int mode) {
return mode != R.id.itemInputFitToScreen;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#setScaleTypeForActivity(android.androidVNC.VncCanvasActivity)
*/
@Override
void setScaleTypeForActivity(VncCanvasActivity activity) {
super.setScaleTypeForActivity(activity);
activity.vncCanvas.scrollToAbsolute();
activity.vncCanvas.pan(0,0);
}
}

View File

@@ -0,0 +1,104 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.graphics.PointF;
import android.os.Handler;
import android.os.SystemClock;
/**
* Handles panning the screen continuously over a period of time
* @author Michael A. MacDonald
*/
class Panner implements Runnable {
VncCanvasActivity activity;
Handler handler;
PointF velocity;
long lastSent;
VelocityUpdater updater;
private static final String TAG = "PANNER";
/**
* Specify how the panning velocity changes over time
* @author Michael A. MacDonald
*/
interface VelocityUpdater {
/**
* Called approximately every 50 ms to update the velocity of panning
* @param p X and Y components to update
* @param interval Milliseconds since last update
* @return False if the panning should stop immediately; true otherwise
*/
boolean updateVelocity(PointF p, long interval);
}
static class DefaultUpdater implements VelocityUpdater {
static DefaultUpdater instance = new DefaultUpdater();
/**
* Don't change velocity
*/
@Override
public boolean updateVelocity(PointF p, long interval) {
return true;
}
}
Panner(VncCanvasActivity act, Handler hand) {
activity = act;
velocity = new PointF();
handler = hand;
}
void stop()
{
handler.removeCallbacks(this);
}
void start(float xv, float yv, VelocityUpdater update)
{
if (update == null)
update = DefaultUpdater.instance;
updater = update;
velocity.x = xv;
velocity.y = yv;
//Log.v(TAG, String.format("pan start %f %f", velocity.x, velocity.y));
lastSent = SystemClock.uptimeMillis();
handler.postDelayed(this, 50);
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
long interval = SystemClock.uptimeMillis() - lastSent;
lastSent += interval;
double scale = (double)interval / 50.0;
//Log.v(TAG, String.format("panning %f %d %d", scale, (int)((double)velocity.x * scale), (int)((double)velocity.y * scale)));
if ( activity.vncCanvas.pan((int)((double)velocity.x * scale), (int)((double)velocity.y * scale)))
{
if (updater.updateVelocity(velocity, interval))
{
handler.postDelayed(this, 50);
}
else
{
//Log.v(TAG, "Updater requests stop");
stop();
}
}
else
{
//Log.v(TAG, "Panning failed");
stop();
}
}
}

View File

@@ -0,0 +1,55 @@
/**
*
*/
package android.androidVNC;
import android.app.*;
import android.os.*;
import android.text.*;
import android.view.*;
import android.widget.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*
*/
class RepeaterDialog extends Dialog {
private EditText _repeaterId;
androidVNC _configurationDialog;
RepeaterDialog(androidVNC context) {
super(context);
setOwnerActivity((Activity)context);
_configurationDialog = context;
}
/* (non-Javadoc)
* @see android.app.Dialog#onCreate(android.os.Bundle)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.repeater_dialog_title);
setContentView(R.layout.repeater_dialog);
_repeaterId=(EditText)findViewById(R.id.textRepeaterInfo);
((TextView)findViewById(R.id.textRepeaterCaption)).setText(Html.fromHtml(getContext().getString(R.string.repeater_caption)));
((Button)findViewById(R.id.buttonSaveRepeater)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
_configurationDialog.updateRepeaterInfo(true, _repeaterId.getText().toString());
dismiss();
}
});
((Button)findViewById(R.id.buttonClearRepeater)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
_configurationDialog.updateRepeaterInfo(false, "");
dismiss();
}
});
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
// This class was generated from android.androidVNC.ISentText by a tool
// Do not edit this file directly! PLX THX
package android.androidVNC;
public class SentTextBean extends com.antlersoft.android.dbimpl.IdImplementationBase implements ISentText {
public static final String GEN_TABLE_NAME = "SENT_TEXT";
public static final int GEN_COUNT = 2;
// Field constants
public static final String GEN_FIELD__ID = "_id";
public static final int GEN_ID__ID = 0;
public static final String GEN_FIELD_SENTTEXT = "SENTTEXT";
public static final int GEN_ID_SENTTEXT = 1;
// SQL Command for creating the table
public static String GEN_CREATE = "CREATE TABLE SENT_TEXT (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"SENTTEXT TEXT" +
")";
// Members corresponding to defined fields
private long gen__Id;
private java.lang.String gen_sentText;
public static final com.antlersoft.android.dbimpl.NewInstance<SentTextBean> GEN_NEW = new com.antlersoft.android.dbimpl.NewInstance<SentTextBean>() {
public SentTextBean get() {
return new SentTextBean();
}
}
;
public String Gen_tableName() { return GEN_TABLE_NAME; }
// Field accessors
public long get_Id() { return gen__Id; }
public void set_Id(long arg__Id) { gen__Id = arg__Id; }
public java.lang.String getSentText() { return gen_sentText; }
public void setSentText(java.lang.String arg_sentText) { gen_sentText = arg_sentText; }
public android.content.ContentValues Gen_getValues() {
android.content.ContentValues values=new android.content.ContentValues();
values.put(GEN_FIELD__ID,Long.toString(this.gen__Id));
values.put(GEN_FIELD_SENTTEXT,this.gen_sentText);
return values;
}
/**
* Return an array that gives the column index in the cursor for each field defined
* @param cursor Database cursor over some columns, possibly including this table
* @return array of column indices; -1 if the column with that id is not in cursor
*/
public int[] Gen_columnIndices(android.database.Cursor cursor) {
int[] result=new int[GEN_COUNT];
result[0] = cursor.getColumnIndex(GEN_FIELD__ID);
// Make compatible with database generated by older version of plugin with uppercase column name
if (result[0] == -1) {
result[0] = cursor.getColumnIndex("_ID");
}
result[1] = cursor.getColumnIndex(GEN_FIELD_SENTTEXT);
return result;
}
/**
* Populate one instance from a cursor
*/
public void Gen_populate(android.database.Cursor cursor,int[] columnIndices) {
if ( columnIndices[GEN_ID__ID] >= 0 && ! cursor.isNull(columnIndices[GEN_ID__ID])) {
gen__Id = cursor.getLong(columnIndices[GEN_ID__ID]);
}
if ( columnIndices[GEN_ID_SENTTEXT] >= 0 && ! cursor.isNull(columnIndices[GEN_ID_SENTTEXT])) {
gen_sentText = cursor.getString(columnIndices[GEN_ID_SENTTEXT]);
}
}
/**
* Populate one instance from a ContentValues
*/
public void Gen_populate(android.content.ContentValues values) {
gen__Id = values.getAsLong(GEN_FIELD__ID);
gen_sentText = values.getAsString(GEN_FIELD_SENTTEXT);
}
}

View File

@@ -0,0 +1,75 @@
package android.androidVNC;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.text.Html;
public class Utils {
public static void showYesNoPrompt(Context _context, String title, String message, OnClickListener onYesListener, OnClickListener onNoListener) {
AlertDialog.Builder builder = new AlertDialog.Builder(_context);
builder.setTitle(title);
builder.setIcon(android.R.drawable.ic_dialog_info); // lame icon
builder.setMessage(message);
builder.setCancelable(false);
builder.setPositiveButton("Yes", onYesListener);
builder.setNegativeButton("No", onNoListener);
builder.show();
}
private static final Intent docIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://code.google.com/p/android-vnc-viewer/wiki/Documentation"));
public static ActivityManager getActivityManager(Context context)
{
ActivityManager result = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
if (result == null)
throw new UnsupportedOperationException("Could not retrieve ActivityManager");
return result;
}
public static MemoryInfo getMemoryInfo(Context _context) {
MemoryInfo info = new MemoryInfo();
getActivityManager(_context).getMemoryInfo(info);
return info;
}
public static void showDocumentation(Context c) {
c.startActivity(docIntent);
}
private static int nextNoticeID = 0;
public static int nextNoticeID() {
nextNoticeID++;
return nextNoticeID;
}
public static void showErrorMessage(Context _context, String message) {
showMessage(_context, "Error!", message, android.R.drawable.ic_dialog_alert, null);
}
public static void showFatalErrorMessage(final Context _context, String message) {
showMessage(_context, "Fatal Error!", message, android.R.drawable.ic_dialog_alert, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// ((Activity) _context).finish();
}
});
}
public static void showMessage(Context _context, String title, String message, int icon, DialogInterface.OnClickListener ackHandler) {
AlertDialog.Builder builder = new AlertDialog.Builder(_context);
builder.setTitle(title);
builder.setMessage(Html.fromHtml(message));
builder.setCancelable(false);
builder.setPositiveButton("Acknowledged", ackHandler);
builder.setIcon(icon);
builder.show();
}
}

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
package android.androidVNC;
/**
* Keys for intent values
*/
public class VncConstants {
public static final String CONNECTION = "android.androidVNC.CONNECTION";
}

View File

@@ -0,0 +1,92 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* @author Michael A. MacDonald
*
*/
class VncDatabase extends SQLiteOpenHelper {
static final int DBV_0_2_X = 9;
static final int DBV_0_2_4 = 10;
static final int DBV_0_4_7 = 11;
static final int DBV_0_5_0 = 12;
public final static String TAG = VncDatabase.class.toString();
VncDatabase(Context context)
{
super(context,"VncDatabase",null,DBV_0_5_0);
}
/* (non-Javadoc)
* @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase)
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(AbstractConnectionBean.GEN_CREATE);
db.execSQL(MostRecentBean.GEN_CREATE);
db.execSQL(MetaList.GEN_CREATE);
db.execSQL(AbstractMetaKeyBean.GEN_CREATE);
db.execSQL(SentTextBean.GEN_CREATE);
db.execSQL("INSERT INTO "+MetaList.GEN_TABLE_NAME+" VALUES ( 1, 'DEFAULT')");
}
private void defaultUpgrade(SQLiteDatabase db)
{
Log.i(TAG, "Doing default database upgrade (drop and create tables)");
db.execSQL("DROP TABLE IF EXISTS " + AbstractConnectionBean.GEN_TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + MostRecentBean.GEN_TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + MetaList.GEN_TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + AbstractMetaKeyBean.GEN_TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + SentTextBean.GEN_TABLE_NAME);
onCreate(db);
}
/* (non-Javadoc)
* @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < DBV_0_2_X)
{
defaultUpgrade(db);
}
else {
if (oldVersion == DBV_0_2_X)
{
Log.i(TAG, "Doing upgrade from 9 to 10");
db.execSQL("ALTER TABLE " + AbstractConnectionBean.GEN_TABLE_NAME + " RENAME TO OLD_" +
AbstractConnectionBean.GEN_TABLE_NAME);
db.execSQL(AbstractConnectionBean.GEN_CREATE);
db.execSQL("INSERT INTO " + AbstractConnectionBean.GEN_TABLE_NAME +
" SELECT *, 0 FROM OLD_" + AbstractConnectionBean.GEN_TABLE_NAME);
db.execSQL("DROP TABLE OLD_" + AbstractConnectionBean.GEN_TABLE_NAME);
oldVersion = DBV_0_2_4;
}
if (oldVersion == DBV_0_2_4)
{
Log.i(TAG,"Doing upgrade from 10 to 11");
db.execSQL("ALTER TABLE " + AbstractConnectionBean.GEN_TABLE_NAME + " ADD COLUMN " +AbstractConnectionBean.GEN_FIELD_USERNAME+" TEXT");
db.execSQL("ALTER TABLE " + AbstractConnectionBean.GEN_TABLE_NAME + " ADD COLUMN " +AbstractConnectionBean.GEN_FIELD_SECURECONNECTIONTYPE+" TEXT");
db.execSQL("ALTER TABLE " + MostRecentBean.GEN_TABLE_NAME + " ADD COLUMN " + MostRecentBean.GEN_FIELD_SHOW_SPLASH_VERSION + " INTEGER");
db.execSQL("ALTER TABLE " + MostRecentBean.GEN_TABLE_NAME + " ADD COLUMN " + MostRecentBean.GEN_FIELD_TEXT_INDEX);
oldVersion = DBV_0_4_7;
}
Log.i(TAG,"Doing upgrade from 11 to 12");
// Haven't been using SentText before, primary key handling changed so drop and recreate it
db.execSQL("DROP TABLE IF EXISTS " + SentTextBean.GEN_TABLE_NAME);
db.execSQL(SentTextBean.GEN_CREATE);
db.execSQL("ALTER TABLE " + AbstractConnectionBean.GEN_TABLE_NAME + " ADD COLUMN " +AbstractConnectionBean.GEN_FIELD_SHOWZOOMBUTTONS+" INTEGER DEFAULT 1");
db.execSQL("ALTER TABLE " + AbstractConnectionBean.GEN_TABLE_NAME + " ADD COLUMN " +AbstractConnectionBean.GEN_FIELD_DOUBLE_TAP_ACTION+" TEXT");
}
}
}

View File

@@ -0,0 +1,112 @@
package android.androidVNC;
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// A ZlibInStream reads from a zlib.io.InputStream
//
public class ZlibInStream extends InStream {
static final int defaultBufSize = 16384;
public ZlibInStream(int bufSize_) {
bufSize = bufSize_;
b = new byte[bufSize];
ptr = end = ptrOffset = 0;
inflater = new java.util.zip.Inflater();
}
public ZlibInStream() { this(defaultBufSize); }
public void setUnderlying(InStream is, int bytesIn_) {
underlying = is;
bytesIn = bytesIn_;
ptr = end = 0;
}
public void reset() throws Exception {
ptr = end = 0;
if (underlying == null) return;
while (bytesIn > 0) {
decompress();
end = 0; // throw away any data
}
underlying = null;
}
public int pos() { return ptrOffset + ptr; }
protected int overrun(int itemSize, int nItems) throws Exception {
if (itemSize > bufSize)
throw new Exception("ZlibInStream overrun: max itemSize exceeded");
if (underlying == null)
throw new Exception("ZlibInStream overrun: no underlying stream");
if (end - ptr != 0)
System.arraycopy(b, ptr, b, 0, end - ptr);
ptrOffset += ptr;
end -= ptr;
ptr = 0;
while (end < itemSize) {
decompress();
}
if (itemSize * nItems > end)
nItems = end / itemSize;
return nItems;
}
// decompress() calls the decompressor once. Note that this won't
// necessarily generate any output data - it may just consume some input
// data. Returns false if wait is false and we would block on the underlying
// stream.
private void decompress() throws Exception {
try {
underlying.check(1);
int avail_in = underlying.getend() - underlying.getptr();
if (avail_in > bytesIn)
avail_in = bytesIn;
if (inflater.needsInput()) {
inflater.setInput(underlying.getbuf(), underlying.getptr(), avail_in);
}
int n = inflater.inflate(b, end, bufSize - end);
end += n;
if (inflater.needsInput()) {
bytesIn -= avail_in;
underlying.setptr(underlying.getptr() + avail_in);
}
} catch (java.util.zip.DataFormatException e) {
throw new Exception("ZlibInStream: inflate failed");
}
}
private InStream underlying;
private int bufSize;
private int ptrOffset;
private java.util.zip.Inflater inflater;
private int bytesIn;
}

View File

@@ -0,0 +1,186 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package android.androidVNC;
import android.graphics.*;
import android.widget.ImageView.*;
import net.kdt.pojavlaunch.*;
/**
* @author Michael A. MacDonald
*/
class ZoomScaling extends AbstractScaling {
static final String TAG = "ZoomScaling";
private Matrix matrix;
int canvasXOffset;
int canvasYOffset;
float scaling;
float minimumScale;
/**
* @param id
* @param scaleType
*/
public ZoomScaling() {
super(R.id.itemZoomable, ScaleType.MATRIX);
matrix = new Matrix();
scaling = 1;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#getDefaultHandlerId()
*/
@Override
int getDefaultHandlerId() {
return R.id.itemInputTouchPanZoomMouse;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#isAbleToPan()
*/
@Override
boolean isAbleToPan() {
return true;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#isValidInputMode(int)
*/
@Override
boolean isValidInputMode(int mode) {
return mode != R.id.itemInputFitToScreen;
}
/**
* Call after scaling and matrix have been changed to resolve scrolling
* @param activity
*/
private void resolveZoom(VncCanvasActivity activity)
{
activity.vncCanvas.scrollToAbsolute();
activity.vncCanvas.pan(0,0);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#zoomIn(android.androidVNC.VncCanvasActivity)
*/
@Override
void zoomIn(VncCanvasActivity activity) {
resetMatrix();
standardizeScaling();
scaling += 0.25;
if (scaling > 4.0)
{
scaling = (float)4.0;
activity.zoomer.setIsZoomInEnabled(false);
}
activity.zoomer.setIsZoomOutEnabled(true);
matrix.postScale(scaling, scaling);
//Log.v(TAG,String.format("before set matrix scrollx = %d scrolly = %d", activity.vncCanvas.getScrollX(), activity.vncCanvas.getScrollY()));
activity.vncCanvas.setImageMatrix(matrix);
resolveZoom(activity);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#getScale()
*/
@Override
float getScale() {
return scaling;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#zoomOut(android.androidVNC.VncCanvasActivity)
*/
@Override
void zoomOut(VncCanvasActivity activity) {
resetMatrix();
standardizeScaling();
scaling -= 0.25;
if (scaling < minimumScale)
{
scaling = minimumScale;
activity.zoomer.setIsZoomOutEnabled(false);
}
activity.zoomer.setIsZoomInEnabled(true);
matrix.postScale(scaling, scaling);
//Log.v(TAG,String.format("before set matrix scrollx = %d scrolly = %d", activity.vncCanvas.getScrollX(), activity.vncCanvas.getScrollY()));
activity.vncCanvas.setImageMatrix(matrix);
//Log.v(TAG,String.format("after set matrix scrollx = %d scrolly = %d", activity.vncCanvas.getScrollX(), activity.vncCanvas.getScrollY()));
resolveZoom(activity);
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#adjust(android.androidVNC.VncCanvasActivity, float, float, float)
*/
@Override
void adjust(VncCanvasActivity activity, float scaleFactor, float fx,
float fy) {
float newScale = scaleFactor * scaling;
if (scaleFactor < 1)
{
if (newScale < minimumScale)
{
newScale = minimumScale;
activity.zoomer.setIsZoomOutEnabled(false);
}
activity.zoomer.setIsZoomInEnabled(true);
}
else
{
if (newScale > 4)
{
newScale = 4;
activity.zoomer.setIsZoomInEnabled(false);
}
activity.zoomer.setIsZoomOutEnabled(true);
}
// ax is the absolute x of the focus
int xPan = activity.vncCanvas.absoluteXPosition;
float ax = (fx / scaling) + xPan;
float newXPan = (scaling * xPan - scaling * ax + newScale * ax)/newScale;
int yPan = activity.vncCanvas.absoluteYPosition;
float ay = (fy / scaling) + yPan;
float newYPan = (scaling * yPan - scaling * ay + newScale * ay)/newScale;
resetMatrix();
scaling = newScale;
matrix.postScale(scaling, scaling);
activity.vncCanvas.setImageMatrix(matrix);
resolveZoom(activity);
activity.vncCanvas.pan((int)(newXPan - xPan), (int)(newYPan - yPan));
}
private void resetMatrix()
{
matrix.reset();
matrix.preTranslate(canvasXOffset, canvasYOffset);
}
/**
* Set scaling to one of the clicks on the zoom scale
*/
private void standardizeScaling()
{
scaling = ((float)((int)(scaling * 4))) / 4;
}
/* (non-Javadoc)
* @see android.androidVNC.AbstractScaling#setScaleTypeForActivity(android.androidVNC.VncCanvasActivity)
*/
@Override
void setScaleTypeForActivity(VncCanvasActivity activity) {
super.setScaleTypeForActivity(activity);
scaling = (float)1.0;
minimumScale = activity.vncCanvas.bitmapData.getMinimumScale();
canvasXOffset = -activity.vncCanvas.getCenteredXOffset();
canvasYOffset = -activity.vncCanvas.getCenteredYOffset();
resetMatrix();
activity.vncCanvas.setImageMatrix(matrix);
// Reset the pan position to (0,0)
resolveZoom(activity);
}
}

View File

@@ -0,0 +1,379 @@
/*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
//
// androidVNC is the Activity for setting VNC server IP and port.
//
package android.androidVNC;
import android.app.*;
import android.app.ActivityManager.*;
import android.content.*;
import android.database.sqlite.*;
import android.os.*;
import android.support.v7.app.*;
import android.view.*;
import android.widget.*;
import java.util.*;
import net.kdt.pojavlaunch.*;
public class androidVNC extends AppCompatActivity {
private EditText ipText;
private EditText portText;
private EditText passwordText;
private Button goButton;
private TextView repeaterText;
private RadioGroup groupForceFullScreen;
private Spinner colorSpinner;
private Spinner spinnerConnection;
private VncDatabase database;
private ConnectionBean selected;
private EditText textNickname;
private EditText textUsername;
private CheckBox checkboxKeepPassword;
private CheckBox checkboxLocalCursor;
private boolean repeaterTextSet;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.androidvncmain);
ipText = (EditText) findViewById(R.id.textIP);
portText = (EditText) findViewById(R.id.textPORT);
passwordText = (EditText) findViewById(R.id.textPASSWORD);
textNickname = (EditText) findViewById(R.id.textNickname);
textUsername = (EditText) findViewById(R.id.textUsername);
goButton = (Button) findViewById(R.id.buttonGO);
((Button) findViewById(R.id.buttonRepeater)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDialog(R.layout.repeater_dialog);
}
});
((Button)findViewById(R.id.buttonImportExport)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDialog(R.layout.importexport);
}
});
colorSpinner = (Spinner)findViewById(R.id.colorformat);
COLORMODEL[] models=COLORMODEL.values();
ArrayAdapter<COLORMODEL> colorSpinnerAdapter = new ArrayAdapter<COLORMODEL>(this, android.R.layout.simple_spinner_item, models);
groupForceFullScreen = (RadioGroup)findViewById(R.id.groupForceFullScreen);
checkboxKeepPassword = (CheckBox)findViewById(R.id.checkboxKeepPassword);
checkboxLocalCursor = (CheckBox)findViewById(R.id.checkboxUseLocalCursor);
colorSpinner.setAdapter(colorSpinnerAdapter);
colorSpinner.setSelection(0);
spinnerConnection = (Spinner)findViewById(R.id.spinnerConnection);
spinnerConnection.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> ad, View view, int itemIndex, long id) {
selected = (ConnectionBean)ad.getSelectedItem();
updateViewFromSelected();
}
@Override
public void onNothingSelected(AdapterView<?> ad) {
selected = null;
}
});
spinnerConnection.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
/* (non-Javadoc)
* @see android.widget.AdapterView.OnItemLongClickListener#onItemLongClick(android.widget.AdapterView, android.view.View, int, long)
*/
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
spinnerConnection.setSelection(arg2);
selected = (ConnectionBean)spinnerConnection.getItemAtPosition(arg2);
canvasStart();
return true;
}
});
repeaterText = (TextView)findViewById(R.id.textRepeaterId);
goButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
canvasStart();
}
});
database = new VncDatabase(this);
}
protected void onDestroy() {
database.close();
super.onDestroy();
}
/* (non-Javadoc)
* @see android.app.Activity#onCreateDialog(int)
*/
@Override
protected Dialog onCreateDialog(int id) {
if (id == R.layout.importexport)
return new ImportExportDialog(this);
else
return new RepeaterDialog(this);
}
/* (non-Javadoc)
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.androidvncmenu,menu);
return true;
}
/* (non-Javadoc)
* @see android.app.Activity#onMenuOpened(int, android.view.Menu)
*/
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
menu.findItem(R.id.itemDeleteConnection).setEnabled(selected!=null && ! selected.isNew());
menu.findItem(R.id.itemSaveAsCopy).setEnabled(selected!=null && ! selected.isNew());
return true;
}
/* (non-Javadoc)
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
{
case R.id.itemSaveAsCopy :
if (selected.getNickname().equals(textNickname.getText().toString()))
textNickname.setText("Copy of "+selected.getNickname());
updateSelectedFromView();
selected.set_Id(0);
saveAndWriteRecent();
arriveOnPage();
break;
case R.id.itemDeleteConnection :
Utils.showYesNoPrompt(this, "Delete?", "Delete " + selected.getNickname() + "?",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i)
{
selected.Gen_delete(database.getWritableDatabase());
arriveOnPage();
}
}, null);
break;
case R.id.itemOpenDoc :
Utils.showDocumentation(this);
break;
}
return true;
}
private void updateViewFromSelected() {
if (selected==null)
return;
ipText.setText(selected.getAddress());
portText.setText(Integer.toString(selected.getPort()));
if (selected.getKeepPassword() || selected.getPassword().length()>0) {
passwordText.setText(selected.getPassword());
}
groupForceFullScreen.check(selected.getForceFull()==BitmapImplHint.AUTO ? R.id.radioForceFullScreenAuto : (selected.getForceFull() == BitmapImplHint.FULL ? R.id.radioForceFullScreenOn : R.id.radioForceFullScreenOff));
checkboxKeepPassword.setChecked(selected.getKeepPassword());
checkboxLocalCursor.setChecked(selected.getUseLocalCursor());
textNickname.setText(selected.getNickname());
textUsername.setText(selected.getUserName());
COLORMODEL cm = COLORMODEL.valueOf(selected.getColorModel());
COLORMODEL[] colors=COLORMODEL.values();
for (int i=0; i<colors.length; ++i)
{
if (colors[i] == cm) {
colorSpinner.setSelection(i);
break;
}
}
updateRepeaterInfo(selected.getUseRepeater(), selected.getRepeaterId());
}
/**
* Called when changing view to match selected connection or from
* Repeater dialog to update the repeater information shown.
* @param repeaterId If null or empty, show text for not using repeater
*/
void updateRepeaterInfo(boolean useRepeater, String repeaterId)
{
if (useRepeater)
{
repeaterText.setText(repeaterId);
repeaterTextSet = true;
}
else
{
repeaterText.setText(getText(R.string.repeater_empty_text));
repeaterTextSet = false;
}
}
private void updateSelectedFromView() {
if (selected==null) {
return;
}
selected.setAddress(ipText.getText().toString());
try
{
selected.setPort(Integer.parseInt(portText.getText().toString()));
}
catch (NumberFormatException nfe)
{
}
selected.setNickname(textNickname.getText().toString());
selected.setUserName(textUsername.getText().toString());
selected.setForceFull(groupForceFullScreen.getCheckedRadioButtonId()==R.id.radioForceFullScreenAuto ? BitmapImplHint.AUTO : (groupForceFullScreen.getCheckedRadioButtonId()==R.id.radioForceFullScreenOn ? BitmapImplHint.FULL : BitmapImplHint.TILE));
selected.setPassword(passwordText.getText().toString());
selected.setKeepPassword(checkboxKeepPassword.isChecked());
selected.setUseLocalCursor(checkboxLocalCursor.isChecked());
selected.setColorModel(((COLORMODEL)colorSpinner.getSelectedItem()).nameString());
if (repeaterTextSet)
{
selected.setRepeaterId(repeaterText.getText().toString());
selected.setUseRepeater(true);
}
else
{
selected.setUseRepeater(false);
}
}
protected void onStart() {
super.onStart();
arriveOnPage();
}
/**
* Return the object representing the app global state in the database, or null
* if the object hasn't been set up yet
* @param db App's database -- only needs to be readable
* @return Object representing the single persistent instance of MostRecentBean, which
* is the app's global state
*/
static MostRecentBean getMostRecent(SQLiteDatabase db)
{
ArrayList<MostRecentBean> recents = new ArrayList<MostRecentBean>(1);
MostRecentBean.getAll(db, MostRecentBean.GEN_TABLE_NAME, recents, MostRecentBean.GEN_NEW);
if (recents.size() == 0)
return null;
return recents.get(0);
}
void arriveOnPage() {
ArrayList<ConnectionBean> connections=new ArrayList<ConnectionBean>();
ConnectionBean.getAll(database.getReadableDatabase(), ConnectionBean.GEN_TABLE_NAME, connections, ConnectionBean.newInstance);
Collections.sort(connections);
connections.add(0, new ConnectionBean());
int connectionIndex=0;
if ( connections.size()>1)
{
MostRecentBean mostRecent = getMostRecent(database.getReadableDatabase());
if (mostRecent != null)
{
for ( int i=1; i<connections.size(); ++i)
{
if (connections.get(i).get_Id() == mostRecent.getConnectionId())
{
connectionIndex=i;
break;
}
}
}
}
spinnerConnection.setAdapter(new ArrayAdapter<ConnectionBean>(this,android.R.layout.simple_spinner_item,
connections.toArray(new ConnectionBean[connections.size()])));
spinnerConnection.setSelection(connectionIndex,false);
selected=connections.get(connectionIndex);
updateViewFromSelected();
IntroTextDialog.showIntroTextIfNecessary(this, database);
}
protected void onStop() {
super.onStop();
if ( selected == null ) {
return;
}
updateSelectedFromView();
selected.save(database.getWritableDatabase());
}
VncDatabase getDatabaseHelper()
{
return database;
}
private void canvasStart() {
if (selected == null) return;
MemoryInfo info = Utils.getMemoryInfo(this);
if (info.lowMemory) {
// Low Memory situation. Prompt.
Utils.showYesNoPrompt(this, "Continue?", "Android reports low system memory.\nContinue with VNC connection?", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
vnc();
}
}, null);
} else
vnc();
}
private void saveAndWriteRecent()
{
SQLiteDatabase db = database.getWritableDatabase();
db.beginTransaction();
try
{
selected.save(db);
MostRecentBean mostRecent = getMostRecent(db);
if (mostRecent == null)
{
mostRecent = new MostRecentBean();
mostRecent.setConnectionId(selected.get_Id());
mostRecent.Gen_insert(db);
}
else
{
mostRecent.setConnectionId(selected.get_Id());
mostRecent.Gen_update(db);
}
db.setTransactionSuccessful();
}
finally
{
db.endTransaction();
}
}
private void vnc() {
updateSelectedFromView();
saveAndWriteRecent();
Intent intent = new Intent(this, VncCanvasActivity.class);
intent.putExtra(VncConstants.CONNECTION,selected.Gen_getValues());
startActivity(intent);
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.app.ActivityManager;
/**
* @author Michael A. MacDonald
*/
class BCActivityManagerDefault implements IBCActivityManager {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCActivityManager#getMemoryClass(android.app.ActivityManager)
*/
@Override
public int getMemoryClass(ActivityManager am) {
return 16;
}
}

View File

@@ -0,0 +1,21 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.app.ActivityManager;
/**
* @author Michael A. MacDonald
*/
public class BCActivityManagerV5 implements IBCActivityManager {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCActivityManager#getMemoryClass(android.app.ActivityManager)
*/
@Override
public int getMemoryClass(ActivityManager am) {
return am.getMemoryClass();
}
}

View File

@@ -0,0 +1,255 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.content.Context;
/**
* Create interface implementations appropriate to the current version of the SDK;
* implementations can allow use of higher-level SDK calls in .apk's that will still run
* on lower-level SDK's
* @author Michael A. MacDonald
*/
public class BCFactory {
private static BCFactory _theInstance = new BCFactory();
private IBCActivityManager bcActivityManager;
private IBCGestureDetector bcGestureDetector;
private IBCHaptic bcHaptic;
private IBCMotionEvent bcMotionEvent;
private IBCStorageContext bcStorageContext;
/**
* This is here so checking the static doesn't get optimized away;
* note we can't use SDK_INT because that is too new
* @return sdk version
*/
int getSdkVersion()
{
try
{
return Integer.parseInt(android.os.Build.VERSION.SDK);
}
catch (NumberFormatException nfe)
{
return 1;
}
}
/**
* Return the implementation of IBCActivityManager appropriate for this SDK level
* @return
*/
public IBCActivityManager getBCActivityManager()
{
if (bcActivityManager == null)
{
synchronized (this)
{
if (bcActivityManager == null)
{
if (getSdkVersion() >= 5)
{
try
{
bcActivityManager = (IBCActivityManager)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCActivityManagerV5").newInstance();
}
catch (Exception ie)
{
bcActivityManager = new BCActivityManagerDefault();
throw new RuntimeException("Error instantiating", ie);
}
}
else
{
bcActivityManager = new BCActivityManagerDefault();
}
}
}
}
return bcActivityManager;
}
/**
* Return the implementation of IBCGestureDetector appropriate for this SDK level
*
* Since we dropped support of SDK levels < 3, there is only one version at the moment.
* @return
*/
public IBCGestureDetector getBCGestureDetector()
{
if (bcGestureDetector == null)
{
synchronized (this)
{
if (bcGestureDetector == null)
{
try
{
bcGestureDetector = (IBCGestureDetector)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCGestureDetectorDefault").newInstance();
}
catch (Exception ie)
{
throw new RuntimeException("Error instantiating", ie);
}
}
}
}
return bcGestureDetector;
}
/**
* Return the implementation of IBCHaptic appropriate for this SDK level
*
* Since we dropped support of SDK levels prior to 3, there is only one version at the moment.
* @return
*/
public IBCHaptic getBCHaptic()
{
if (bcHaptic == null)
{
synchronized (this)
{
if (bcHaptic == null)
{
try
{
bcHaptic = (IBCHaptic)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCHapticDefault").newInstance();
}
catch (Exception ie)
{
throw new RuntimeException("Error instantiating", ie);
}
}
}
}
return bcHaptic;
}
/**
* Return the implementation of IBCMotionEvent appropriate for this SDK level
* @return
*/
public IBCMotionEvent getBCMotionEvent()
{
if (bcMotionEvent == null)
{
synchronized (this)
{
if (bcMotionEvent == null)
{
if (getSdkVersion() >= 5)
{
try
{
bcMotionEvent = (IBCMotionEvent)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCMotionEvent5").newInstance();
}
catch (Exception ie)
{
throw new RuntimeException("Error instantiating", ie);
}
}
else
{
try
{
bcMotionEvent = (IBCMotionEvent)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCMotionEvent4").newInstance();
}
catch (Exception ie)
{
throw new RuntimeException("Error instantiating", ie);
}
}
}
}
}
return bcMotionEvent;
}
@SuppressWarnings("unchecked")
static private Class[] scaleDetectorConstructorArgs = new Class[] { Context.class, OnScaleGestureListener.class };
/**
* Return an instance of an implementation of {@link IBCScaleGestureDetector} appropriate to the SDK of this device.
* This will work very much like android.view.ScaleGestureDetector on SDK >= 5. For previous
* SDK versions, it is a dummy implementation that does nothing and will never call the listener.
* <p>
* Note that unlike the other methods in this class, the returned interface instance is not
* stateless.
* @param context The context to which the detector is applied
* @param listener The listener to which the implementation will send scale events
* @return The gesture detector
*/
public IBCScaleGestureDetector getScaleGestureDetector(Context context, OnScaleGestureListener listener)
{
IBCScaleGestureDetector result;
if (getSdkVersion() >= 5)
{
try {
result = (IBCScaleGestureDetector)getClass().getClassLoader().
loadClass("com.antlersoft.android.bc.ScaleGestureDetector").
getConstructor(scaleDetectorConstructorArgs).newInstance(new Object[] { context, listener });
} catch (Exception e) {
throw new RuntimeException("Error instantiating ScaleGestureDetector", e);
}
}
else
{
result = new DummyScaleGestureDetector();
}
return result;
}
/**
*
* @return An implementation of IBCStorageContext appropriate for the running Android release
*/
public IBCStorageContext getStorageContext()
{
if (bcStorageContext == null)
{
synchronized (this)
{
if (bcStorageContext == null)
{
if (getSdkVersion() >= 8)
{
try
{
bcStorageContext = (IBCStorageContext)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCStorageContext8").newInstance();
}
catch (Exception ie)
{
throw new RuntimeException("Error instantiating", ie);
}
}
else
{
try
{
bcStorageContext = (IBCStorageContext)getClass().getClassLoader().loadClass("com.antlersoft.android.bc.BCStorageContext7").newInstance();
}
catch (Exception ie)
{
throw new RuntimeException("Error instantiating", ie);
}
}
}
}
}
return bcStorageContext;
}
/**
* Returns the only instance of this class, which manages the SDK specific interface
* implementations
* @return Factory instance
*/
public static BCFactory getInstance()
{
return _theInstance;
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
/**
* @author Michael A. MacDonald
*/
public class BCGestureDetectorDefault implements IBCGestureDetector {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCGestureDetector#createGestureDetector(android.content.Context, android.view.GestureDetector.OnGestureListener)
*/
@Override
public GestureDetector createGestureDetector(Context context,
OnGestureListener listener) {
return new GestureDetector(context, listener);
}
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.view.View;
import android.view.HapticFeedbackConstants;
/**
* Implementation for SDK version >= 3
* @author Michael A. MacDonald
*/
class BCHapticDefault implements IBCHaptic {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCHaptic#performLongPressHaptic(android.view.View)
*/
@Override
public boolean performLongPressHaptic(View v) {
return v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING|HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
);
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCHaptic#setIsHapticEnabled(android.view.View, boolean)
*/
/*
* @Override
public boolean setIsHapticEnabled(View v, boolean enabled) {
return v.setHapticFeedbackEnabled(hapticFeedbackEnabled)
}
*/
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.view.MotionEvent;
/**
* Pre-sdk 5 version; add fake multi-touch sensing later?
*
* @author Michael A. MacDonald
*
*/
class BCMotionEvent4 implements IBCMotionEvent {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCMotionEvent#getPointerCount(android.view.MotionEvent)
*/
@Override
public int getPointerCount(MotionEvent evt) {
return 1;
}
}

View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.view.MotionEvent;
/**
* @author Michael A. MacDonald
*
*/
class BCMotionEvent5 implements IBCMotionEvent {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCMotionEvent#getPointerCount(android.view.MotionEvent)
*/
@Override
public int getPointerCount(MotionEvent evt) {
return evt.getPointerCount();
}
}

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2011 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import java.io.File;
import android.content.Context;
import android.os.Environment;
/**
* @author Michael A. MacDonald
*
*/
public class BCStorageContext7 implements IBCStorageContext {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCStorageContext#getExternalStorageDir(android.content.Context, java.lang.String)
*/
@Override
public File getExternalStorageDir(Context context, String type) {
File f = Environment.getExternalStorageDirectory();
f = new File(f, "Android/data/android.androidVNC/files");
if (type != null)
f=new File(f, type);
f.mkdirs();
return f;
}
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import java.io.File;
import android.content.Context;
/**
* @author Michael A. MacDonald
*
*/
class BCStorageContext8 implements IBCStorageContext {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCStorageContext#getExternalStorageDir(android.content.Context, java.lang.String)
*/
@Override
public File getExternalStorageDir(Context context, String type) {
return context.getExternalFilesDir(type);
}
}

View File

@@ -0,0 +1,119 @@
/* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* MODIFIED FOR ANTLERSOFT
*
* Changes for antlersoft/ vnc viewer for android
*
* Copyright (C) 2010 Michael A. MacDonald
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package com.antlersoft.android.bc;
import android.view.MotionEvent;
/**
* Implementation of scale gesture detector interface for devices without multi-touch support; does nothing
* @author Michael A. MacDonald
*
*/
class DummyScaleGestureDetector implements IBCScaleGestureDetector {
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getCurrentSpan()
*/
@Override
public float getCurrentSpan() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getEventTime()
*/
@Override
public long getEventTime() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getFocusX()
*/
@Override
public float getFocusX() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getFocusY()
*/
@Override
public float getFocusY() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getPreviousSpan()
*/
@Override
public float getPreviousSpan() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getScaleFactor()
*/
@Override
public float getScaleFactor() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getTimeDelta()
*/
@Override
public long getTimeDelta() {
return 0;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#isInProgress()
*/
@Override
public boolean isInProgress() {
return false;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#onTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
}

View File

@@ -0,0 +1,13 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.app.ActivityManager;
/**
* @author Michael A. MacDonald
*/
public interface IBCActivityManager {
public int getMemoryClass(ActivityManager am);
}

View File

@@ -0,0 +1,17 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.content.Context;
import android.view.GestureDetector;
/**
* Create a gesture detector in a version friendly way, avoiding incompatible API on older version
* and deprecated API on newer version
*
* @author Michael A. MacDonald
*/
public interface IBCGestureDetector {
public GestureDetector createGestureDetector(Context context, GestureDetector.OnGestureListener listener);
}

View File

@@ -0,0 +1,20 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.view.View;
/**
* Access the Haptic interfaces added in version 3 without breaking compatibility
* @author Michael A. MacDonald
*/
public interface IBCHaptic {
public boolean performLongPressHaptic(View v);
/**
* Set whether haptic feedback is enabled on the view
* @param enabled
* @return Old value of setting
*/
//public boolean setIsHapticEnabled(View v, boolean enabled);
}

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.view.MotionEvent;
/**
* Access to SDK-dependent features of MotionEvent
*
* @see android.view.MotionEvent
*
* @author Michael A. MacDonald
*
*/
public interface IBCMotionEvent {
/**
* Obtain the number of pointers active in the event
* @see android.view.MotionEvent#getPointerCount()
* @param evt
* @return number of pointers
*/
int getPointerCount(MotionEvent evt);
}

View File

@@ -0,0 +1,125 @@
/* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* MODIFIED FOR ANTLERSOFT
*
* Changes for antlersoft/ vnc viewer for android
*
* Copyright (C) 2010 Michael A. MacDonald
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package com.antlersoft.android.bc;
import android.view.MotionEvent;
/**
* Backwards-compatibility interface to the android.view.ScaleGestureDetector introduced in Android SDK 8.
*
* This will be a working implementation of devices with SDK >= 5 (since I backported ScaleGestureDetector
* to 5) and a dummy implementation for older devices.
*
* @author Michael A. MacDonald
*
*/
public interface IBCScaleGestureDetector {
public abstract boolean onTouchEvent(MotionEvent event);
/**
* Returns {@code true} if a two-finger scale gesture is in progress.
* @return {@code true} if a scale gesture is in progress, {@code false} otherwise.
*/
public abstract boolean isInProgress();
/**
* Get the X coordinate of the current gesture's focal point.
* If a gesture is in progress, the focal point is directly between
* the two pointers forming the gesture.
* If a gesture is ending, the focal point is the location of the
* remaining pointer on the screen.
* If {@link #isInProgress()} would return false, the result of this
* function is undefined.
*
* @return X coordinate of the focal point in pixels.
*/
public abstract float getFocusX();
/**
* Get the Y coordinate of the current gesture's focal point.
* If a gesture is in progress, the focal point is directly between
* the two pointers forming the gesture.
* If a gesture is ending, the focal point is the location of the
* remaining pointer on the screen.
* If {@link #isInProgress()} would return false, the result of this
* function is undefined.
*
* @return Y coordinate of the focal point in pixels.
*/
public abstract float getFocusY();
/**
* Return the current distance between the two pointers forming the
* gesture in progress.
*
* @return Distance between pointers in pixels.
*/
public abstract float getCurrentSpan();
/**
* Return the previous distance between the two pointers forming the
* gesture in progress.
*
* @return Previous distance between pointers in pixels.
*/
public abstract float getPreviousSpan();
/**
* Return the scaling factor from the previous scale event to the current
* event. This value is defined as
* ({@link #getCurrentSpan()} / {@link #getPreviousSpan()}).
*
* @return The current scaling factor.
*/
public abstract float getScaleFactor();
/**
* Return the time difference in milliseconds between the previous
* accepted scaling event and the current scaling event.
*
* @return Time difference since the last scaling event in milliseconds.
*/
public abstract long getTimeDelta();
/**
* Return the event time of the current event being processed.
*
* @return Current event time in milliseconds.
*/
public abstract long getEventTime();
}

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2010 Michael A. MacDonald
*/
package com.antlersoft.android.bc;
import android.content.Context;
import java.io.File;
/**
* Provides a way to access the directory on external storage as returned by
* Context.getExternal... added in API 8 that will work with earlier API releases.
* @author Michael A. MacDonald
*
*/
public interface IBCStorageContext {
/**
*
* @param context Context within the application with which the storage will be associated
* @param type May be null; if specified, references a sub-directory within the base directory
* for the app in the external storage
* @return File representing abstract path of storage directory; refer to android.os.Environment to
* see if the path is actually accessible
*/
public File getExternalStorageDir(Context context, String type);
}

View File

@@ -0,0 +1,94 @@
/* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* MODIFIED FOR ANTLERSOFT
*
* Changes for antlersoft/ vnc viewer for android
*
* Copyright (C) 2010 Michael A. MacDonald
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package com.antlersoft.android.bc;
/**
* The listener for receiving notifications when gestures occur.
* If you want to listen for all the different gestures then implement
* this interface. If you only want to listen for a subset it might
* be easier to extend {@link SimpleOnScaleGestureListener}.
*
* An application will receive events in the following order:
* <ul>
* <li>One {@link OnScaleGestureListener#onScaleBegin(ScaleGestureDetector)}
* <li>Zero or more {@link OnScaleGestureListener#onScale(ScaleGestureDetector)}
* <li>One {@link OnScaleGestureListener#onScaleEnd(ScaleGestureDetector)}
* </ul>
*/
public interface OnScaleGestureListener {
/**
* Responds to scaling events for a gesture in progress.
* Reported by pointer motion.
*
* @param detector The detector reporting the event - use this to
* retrieve extended info about event state.
* @return Whether or not the detector should consider this event
* as handled. If an event was not handled, the detector
* will continue to accumulate movement until an event is
* handled. This can be useful if an application, for example,
* only wants to update scaling factors if the change is
* greater than 0.01.
*/
public boolean onScale(IBCScaleGestureDetector detector);
/**
* Responds to the beginning of a scaling gesture. Reported by
* new pointers going down.
*
* @param detector The detector reporting the event - use this to
* retrieve extended info about event state.
* @return Whether or not the detector should continue recognizing
* this gesture. For example, if a gesture is beginning
* with a focal point outside of a region where it makes
* sense, onScaleBegin() may return false to ignore the
* rest of the gesture.
*/
public boolean onScaleBegin(IBCScaleGestureDetector detector);
/**
* Responds to the end of a scale gesture. Reported by existing
* pointers going up.
*
* Once a scale has ended, {@link ScaleGestureDetector#getFocusX()}
* and {@link ScaleGestureDetector#getFocusY()} will return the location
* of the pointer remaining on the screen.
*
* @param detector The detector reporting the event - use this to
* retrieve extended info about event state.
*/
public void onScaleEnd(IBCScaleGestureDetector detector);
}

View File

@@ -0,0 +1,389 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* MODIFIED FOR ANTLERSOFT
*
* Changes for antlersoft/ vnc viewer for android
*
* Copyright (C) 2010 Michael A. MacDonald
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package com.antlersoft.android.bc;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
/**
* Detects transformation gestures involving more than one pointer ("multitouch")
* using the supplied {@link MotionEvent}s. The {@link OnScaleGestureListener}
* callback will notify users when a particular gesture event has occurred.
* This class should only be used with {@link MotionEvent}s reported via touch.
*
* To use this class:
* <ul>
* <li>Create an instance of the {@code ScaleGestureDetector} for your
* {@link View}
* <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
* {@link #onTouchEvent(MotionEvent)}. The methods defined in your
* callback will be executed when the events occur.
* </ul>
*/
class ScaleGestureDetector implements IBCScaleGestureDetector {
/**
* This value is the threshold ratio between our previous combined pressure
* and the current combined pressure. We will only fire an onScale event if
* the computed ratio between the current and previous event pressures is
* greater than this value. When pressure decreases rapidly between events
* the position values can often be imprecise, as it usually indicates
* that the user is in the process of lifting a pointer off of the device.
* Its value was tuned experimentally.
*/
private static final float PRESSURE_THRESHOLD = 0.67f;
private final Context mContext;
private final OnScaleGestureListener mListener;
private boolean mGestureInProgress;
private MotionEvent mPrevEvent;
private MotionEvent mCurrEvent;
private float mFocusX;
private float mFocusY;
private float mPrevFingerDiffX;
private float mPrevFingerDiffY;
private float mCurrFingerDiffX;
private float mCurrFingerDiffY;
private float mCurrLen;
private float mPrevLen;
private float mScaleFactor;
private float mCurrPressure;
private float mPrevPressure;
private long mTimeDelta;
private final float mEdgeSlop;
private float mRightSlopEdge;
private float mBottomSlopEdge;
private boolean mSloppyGesture;
public ScaleGestureDetector(Context context, OnScaleGestureListener listener) {
ViewConfiguration config = ViewConfiguration.get(context);
mContext = context;
mListener = listener;
mEdgeSlop = config.getScaledEdgeSlop();
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#onTouchEvent(android.view.MotionEvent)
*/
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
boolean handled = true;
if (!mGestureInProgress) {
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN: {
// We have a new multi-finger gesture
// as orientation can change, query the metrics in touch down
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
mRightSlopEdge = metrics.widthPixels - mEdgeSlop;
mBottomSlopEdge = metrics.heightPixels - mEdgeSlop;
// Be paranoid in case we missed an event
reset();
mPrevEvent = MotionEvent.obtain(event);
mTimeDelta = 0;
setContext(event);
// Check if we have a sloppy gesture. If so, delay
// the beginning of the gesture until we're sure that's
// what the user wanted. Sloppy gestures can happen if the
// edge of the user's hand is touching the screen, for example.
final float edgeSlop = mEdgeSlop;
final float rightSlop = mRightSlopEdge;
final float bottomSlop = mBottomSlopEdge;
final float x0 = event.getRawX();
final float y0 = event.getRawY();
final float x1 = getRawX(event, 1);
final float y1 = getRawY(event, 1);
boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop
|| x0 > rightSlop || y0 > bottomSlop;
boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop
|| x1 > rightSlop || y1 > bottomSlop;
if (p0sloppy && p1sloppy) {
mFocusX = -1;
mFocusY = -1;
mSloppyGesture = true;
} else if (p0sloppy) {
mFocusX = event.getX(1);
mFocusY = event.getY(1);
mSloppyGesture = true;
} else if (p1sloppy) {
mFocusX = event.getX(0);
mFocusY = event.getY(0);
mSloppyGesture = true;
} else {
mGestureInProgress = mListener.onScaleBegin(this);
}
}
break;
case MotionEvent.ACTION_MOVE:
if (mSloppyGesture) {
// Initiate sloppy gestures if we've moved outside of the slop area.
final float edgeSlop = mEdgeSlop;
final float rightSlop = mRightSlopEdge;
final float bottomSlop = mBottomSlopEdge;
final float x0 = event.getRawX();
final float y0 = event.getRawY();
final float x1 = getRawX(event, 1);
final float y1 = getRawY(event, 1);
boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop
|| x0 > rightSlop || y0 > bottomSlop;
boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop
|| x1 > rightSlop || y1 > bottomSlop;
if(p0sloppy && p1sloppy) {
mFocusX = -1;
mFocusY = -1;
} else if (p0sloppy) {
mFocusX = event.getX(1);
mFocusY = event.getY(1);
} else if (p1sloppy) {
mFocusX = event.getX(0);
mFocusY = event.getY(0);
} else {
mSloppyGesture = false;
mGestureInProgress = mListener.onScaleBegin(this);
}
}
break;
case MotionEvent.ACTION_POINTER_UP:
if (mSloppyGesture) {
// Set focus point to the remaining finger
int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
mFocusX = event.getX(id);
mFocusY = event.getY(id);
}
break;
}
} else {
// Transform gesture in progress - attempt to handle it
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_UP:
// Gesture ended
setContext(event);
// Set focus point to the remaining finger
int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
>> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
mFocusX = event.getX(id);
mFocusY = event.getY(id);
if (!mSloppyGesture) {
mListener.onScaleEnd(this);
}
reset();
break;
case MotionEvent.ACTION_CANCEL:
if (!mSloppyGesture) {
mListener.onScaleEnd(this);
}
reset();
break;
case MotionEvent.ACTION_MOVE:
setContext(event);
// Only accept the event if our relative pressure is within
// a certain limit - this can help filter shaky data as a
// finger is lifted.
if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
final boolean updatePrevious = mListener.onScale(this);
if (updatePrevious) {
mPrevEvent.recycle();
mPrevEvent = MotionEvent.obtain(event);
}
}
break;
}
}
return handled;
}
/**
* MotionEvent has no getRawX(int) method; simulate it pending future API approval.
*/
private static float getRawX(MotionEvent event, int pointerIndex) {
float offset = event.getX() - event.getRawX();
return event.getX(pointerIndex) + offset;
}
/**
* MotionEvent has no getRawY(int) method; simulate it pending future API approval.
*/
private static float getRawY(MotionEvent event, int pointerIndex) {
float offset = event.getY() - event.getRawY();
return event.getY(pointerIndex) + offset;
}
private void setContext(MotionEvent curr) {
if (mCurrEvent != null) {
mCurrEvent.recycle();
}
mCurrEvent = MotionEvent.obtain(curr);
mCurrLen = -1;
mPrevLen = -1;
mScaleFactor = -1;
final MotionEvent prev = mPrevEvent;
final float px0 = prev.getX(0);
final float py0 = prev.getY(0);
final float px1 = prev.getX(1);
final float py1 = prev.getY(1);
final float cx0 = curr.getX(0);
final float cy0 = curr.getY(0);
final float cx1 = curr.getX(1);
final float cy1 = curr.getY(1);
final float pvx = px1 - px0;
final float pvy = py1 - py0;
final float cvx = cx1 - cx0;
final float cvy = cy1 - cy0;
mPrevFingerDiffX = pvx;
mPrevFingerDiffY = pvy;
mCurrFingerDiffX = cvx;
mCurrFingerDiffY = cvy;
mFocusX = cx0 + cvx * 0.5f;
mFocusY = cy0 + cvy * 0.5f;
mTimeDelta = curr.getEventTime() - prev.getEventTime();
mCurrPressure = curr.getPressure(0) + curr.getPressure(1);
mPrevPressure = prev.getPressure(0) + prev.getPressure(1);
}
private void reset() {
if (mPrevEvent != null) {
mPrevEvent.recycle();
mPrevEvent = null;
}
if (mCurrEvent != null) {
mCurrEvent.recycle();
mCurrEvent = null;
}
mSloppyGesture = false;
mGestureInProgress = false;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#isInProgress()
*/
public boolean isInProgress() {
return mGestureInProgress;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getFocusX()
*/
public float getFocusX() {
return mFocusX;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getFocusY()
*/
public float getFocusY() {
return mFocusY;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getCurrentSpan()
*/
public float getCurrentSpan() {
if (mCurrLen == -1) {
final float cvx = mCurrFingerDiffX;
final float cvy = mCurrFingerDiffY;
mCurrLen = FloatMath.sqrt(cvx*cvx + cvy*cvy);
}
return mCurrLen;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getPreviousSpan()
*/
public float getPreviousSpan() {
if (mPrevLen == -1) {
final float pvx = mPrevFingerDiffX;
final float pvy = mPrevFingerDiffY;
mPrevLen = FloatMath.sqrt(pvx*pvx + pvy*pvy);
}
return mPrevLen;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getScaleFactor()
*/
public float getScaleFactor() {
if (mScaleFactor == -1) {
mScaleFactor = getCurrentSpan() / getPreviousSpan();
}
return mScaleFactor;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getTimeDelta()
*/
public long getTimeDelta() {
return mTimeDelta;
}
/* (non-Javadoc)
* @see com.antlersoft.android.bc.IBCScaleGestureDetector#getEventTime()
*/
public long getEventTime() {
return mCurrEvent.getEventTime();
}
}

View File

@@ -0,0 +1,61 @@
/* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* MODIFIED FOR ANTLERSOFT
*
* Changes for antlersoft/ vnc viewer for android
*
* Copyright (C) 2010 Michael A. MacDonald
*
* This 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.
*
* This software 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 this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
package com.antlersoft.android.bc;
/**
* A convenience class to extend when you only want to listen for a subset
* of scaling-related events. This implements all methods in
* {@link OnScaleGestureListener} but does nothing.
* {@link OnScaleGestureListener#onScale(ScaleGestureDetector)} returns
* {@code false} so that a subclass can retrieve the accumulated scale
* factor in an overridden onScaleEnd.
* {@link OnScaleGestureListener#onScaleBegin(ScaleGestureDetector)} returns
* {@code true}.
*/
public class SimpleOnScaleGestureListener implements OnScaleGestureListener {
public boolean onScale(IBCScaleGestureDetector detector) {
return false;
}
public boolean onScaleBegin(IBCScaleGestureDetector detector) {
return true;
}
public void onScaleEnd(IBCScaleGestureDetector detector) {
// Intentionally empty
}
}

View File

@@ -0,0 +1,136 @@
package com.antlersoft.android.drawing;
import com.antlersoft.util.ObjectPool;
import com.antlersoft.util.SafeObjectPool;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
public class OverlappingCopy
{
private static SafeObjectPool<Rect> ocRectPool = new SafeObjectPool<Rect>() {
@Override
protected Rect itemForPool()
{
return new Rect();
}
};
private static void transformRect(Rect source, Rect transformedSource, int deltaX, int deltaY)
{
transformedSource.set(deltaX < 0 ? source.right * -1 : source.left,
deltaY < 0 ? source.bottom * -1 : source.top,
deltaX < 0 ? source.left * -1 : source.right,
deltaY < 0 ? source.top * -1 : source.bottom);
}
private static void copyTransformedRect(Rect stepSourceRect, Rect stepDestRect, int deltaX, int deltaY, Bitmap data, Canvas bitmapBackedCanvas, Paint paint)
{
transformRect(stepSourceRect,stepSourceRect,deltaX,deltaY);
stepDestRect.set(stepSourceRect);
stepDestRect.offset(deltaX,deltaY);
bitmapBackedCanvas.drawBitmap(data, stepSourceRect, stepDestRect, paint);
}
public static void Copy(Bitmap data, Canvas bitmapBackedCanvas, Paint paint, Rect source, int destX, int destY)
{
Copy(data,bitmapBackedCanvas,paint,source,destX,destY,ocRectPool);
}
public static void Copy(Bitmap data, Canvas bitmapBackedCanvas, Paint paint, Rect source, int destX, int destY, ObjectPool<Rect> rectPool)
{
//android.util.Log.i("LBM","Copy "+source.toString()+" to "+destX+","+destY);
int deltaX = destX - source.left;
int deltaY = destY - source.top;
int absDeltaX = deltaX < 0 ? -deltaX : deltaX;
int absDeltaY = deltaY < 0 ? -deltaY : deltaY;
// Look for degenerate case
if (absDeltaX == 0 && absDeltaY == 0)
return;
// Look for non-overlap case
if (absDeltaX >= source.right - source.left || absDeltaY >= source.bottom - source.top)
{
// Non-overlapping copy
ObjectPool.Entry<Rect> entry = rectPool.reserve();
Rect dest = entry.get();
dest.set(source.left + deltaX, source.top + deltaY, source.right + deltaX, source.bottom + deltaY);
bitmapBackedCanvas.drawBitmap(data, source, dest, paint);
rectPool.release(entry);
return;
}
// Determine coordinate transform so that dest rectangle is always down and to the right.
ObjectPool.Entry<Rect> transformedSourceEntry = rectPool.reserve();
Rect transformedSource = transformedSourceEntry.get();
transformRect(source,transformedSource,deltaX,deltaY);
ObjectPool.Entry<Rect> transformedDestEntry = rectPool.reserve();
Rect transformedDest = transformedDestEntry.get();
transformedDest.set(transformedSource);
transformedDest.offset(absDeltaX, absDeltaY);
ObjectPool.Entry<Rect> intersectEntry = rectPool.reserve();
Rect intersect = intersectEntry.get();
intersect.setIntersect(transformedSource, transformedDest);
boolean xStepDone = false;
int xStepWidth;
int yStepHeight;
if (absDeltaX > absDeltaY)
{
xStepWidth = absDeltaX;
yStepHeight = source.bottom - source.top - absDeltaY;
}
else
{
xStepWidth = source.right - source.left - absDeltaX;
yStepHeight = absDeltaY;
}
ObjectPool.Entry<Rect> stepSourceEntry = rectPool.reserve();
Rect stepSourceRect = stepSourceEntry.get();
ObjectPool.Entry<Rect> stepDestEntry = rectPool.reserve();
Rect stepDestRect = stepDestEntry.get();
for (int xStep = 0; ! xStepDone; xStep++)
{
int stepRight = intersect.right - xStep * xStepWidth;
int stepLeft = stepRight - xStepWidth;
if (stepLeft <= intersect.left)
{
stepLeft = intersect.left;
xStepDone = true;
}
boolean yStepDone = false;
for (int yStep = 0; ! yStepDone; yStep++)
{
int stepBottom = intersect.bottom - yStep * yStepHeight;
int stepTop = stepBottom - yStepHeight;
if (stepTop <= intersect.top)
{
stepTop = intersect.top;
yStepDone = true;
}
stepSourceRect.set(stepLeft,stepTop,stepRight,stepBottom);
//android.util.Log.i("LBM","Copy transformed "+stepSourceRect.toString()+" "+deltaX+" "+deltaY);
copyTransformedRect(stepSourceRect, stepDestRect, deltaX, deltaY, data, bitmapBackedCanvas, paint);
}
}
if (absDeltaX>0)
{
// Copy left edge
stepSourceRect.set(transformedSource.left,transformedSource.top,intersect.left,transformedSource.bottom);
copyTransformedRect(stepSourceRect, stepDestRect, deltaX, deltaY, data, bitmapBackedCanvas, paint);
}
if (absDeltaY>0)
{
// Copy top excluding left edge
stepSourceRect.set(intersect.left,transformedSource.top,transformedSource.right,intersect.top);
copyTransformedRect(stepSourceRect, stepDestRect, deltaX, deltaY, data, bitmapBackedCanvas, paint);
}
rectPool.release(stepDestEntry);
rectPool.release(stepSourceEntry);
rectPool.release(intersectEntry);
rectPool.release(transformedDestEntry);
rectPool.release(transformedSourceEntry);
}
}

View File

@@ -0,0 +1,549 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.android.drawing;
import android.graphics.Rect;
import java.util.ArrayList;
import com.antlersoft.util.ObjectPool;
/**
* A list of rectangular regions that together represent an area of interest. Provides
* a set of operations that apply to the whole area, adding, changing and mutating the
* rectangles in the list as required.
* <p>
* Invariants: None of the rectangles in the list overlap; no pair of rectangles in the list
* together make a single rectangle (none share a complete side)
* </p>
* <p>
* Instances of this class are not thread safe
* </p>
* @author Michael A. MacDonald
*
*/
public class RectList {
enum OverlapType {
NONE,
SAME,
CONTAINS,
CONTAINED_BY,
COALESCIBLE,
PARTIAL
}
static final int LEFT = 1;
static final int TOP_LEFT = 2;
static final int TOP = 4;
static final int TOP_RIGHT = 8;
static final int RIGHT = 16;
static final int BOTTOM_RIGHT = 32;
static final int BOTTOM = 64;
static final int BOTTOM_LEFT = 128;
/**
* The part left over when one rectangle is subtracted from another
* @author Michael A. MacDonald
*
*/
static class NonOverlappingPortion
{
Rect leftPortion;
Rect topLeftPortion;
Rect topPortion;
Rect topRightPortion;
Rect rightPortion;
Rect bottomRightPortion;
Rect bottomPortion;
Rect bottomLeftPortion;
int r1Owns;
int r2Owns;
int common;
int adjacent;
boolean horizontalOverlap;
boolean verticalOverlap;
Rect coalesced;
NonOverlappingPortion()
{
leftPortion = new Rect();
topLeftPortion = new Rect();
topPortion = new Rect();
topRightPortion = new Rect();
rightPortion = new Rect();
bottomRightPortion = new Rect();
bottomPortion = new Rect();
bottomLeftPortion = new Rect();
coalesced = new Rect();
}
void setCornerOwnership(int side1, int side2, int corner)
{
int combined = (side1 | side2);
if ((r1Owns & combined) == combined)
r1Owns |= corner;
else if ((r2Owns & combined) == combined)
r2Owns |= corner;
}
void setCornerOwnership()
{
setCornerOwnership(LEFT,TOP,TOP_LEFT);
setCornerOwnership(TOP,RIGHT,TOP_RIGHT);
setCornerOwnership(BOTTOM,RIGHT,BOTTOM_RIGHT);
setCornerOwnership(BOTTOM,LEFT,BOTTOM_LEFT);
}
/**
* Populates with the borders remaining when r2 is subtracted from r1
* @param r1
* @param r2
* @return
*/
OverlapType overlap(Rect r1, Rect r2)
{
r1Owns = 0;
r2Owns = 0;
common = 0;
adjacent = 0;
OverlapType result = OverlapType.NONE;
horizontalOverlap = false;
verticalOverlap = false;
if (r1.left < r2.left)
{
leftPortion.left = topLeftPortion.left = bottomLeftPortion.left = r1.left;
if (r2.left < r1.right) {
leftPortion.right = topLeftPortion.right = bottomLeftPortion.right = topPortion.left = bottomPortion.left = r2.left;
horizontalOverlap = true;
} else {
leftPortion.right = topLeftPortion.right = bottomLeftPortion.right = topPortion.left = bottomPortion.left = r1.right;
if (r2.left == r1.right)
adjacent |= LEFT;
}
r1Owns |= LEFT;
}
else
{
leftPortion.left = topLeftPortion.left = bottomLeftPortion.left = r2.left;
if (r1.left < r2.right) {
leftPortion.right = topLeftPortion.right = bottomLeftPortion.right = topPortion.left = bottomPortion.left = r1.left;
horizontalOverlap = true;
} else {
leftPortion.right = topLeftPortion.right = bottomLeftPortion.right = topPortion.left = bottomPortion.left = r2.right;
if ( r1.left == r2.right)
adjacent |= RIGHT;
}
if (r2.left < r1.left)
r2Owns |= LEFT;
else
common |= LEFT;
}
if (r1.top < r2.top)
{
topPortion.top = topLeftPortion.top = topRightPortion.top = r1.top;
if (r2.top < r1.bottom) {
topPortion.bottom = topLeftPortion.bottom = topRightPortion.bottom = leftPortion.top = rightPortion.top = r2.top;
verticalOverlap = true;
} else {
topPortion.bottom = topLeftPortion.bottom = topRightPortion.bottom = leftPortion.top = rightPortion.top = r1.bottom;
if (r2.top == r1.bottom)
adjacent |= TOP;
}
r1Owns |= TOP;
}
else
{
topPortion.top = topLeftPortion.top = topRightPortion.top = r2.top;
if (r1.top < r2.bottom) {
topPortion.bottom = topLeftPortion.bottom = topRightPortion.bottom = leftPortion.top = rightPortion.top = r1.top;
verticalOverlap = true;
} else {
topPortion.bottom = topLeftPortion.bottom = topRightPortion.bottom = leftPortion.top = rightPortion.top = r2.bottom;
if (r1.top == r2.bottom)
adjacent |= BOTTOM;
}
if (r2.top < r1.top)
r2Owns |= TOP;
else
common |= TOP;
}
if (r1.right > r2.right)
{
rightPortion.right = topRightPortion.right = bottomRightPortion.right = r1.right;
if (r2.right > r1.left) {
rightPortion.left = topRightPortion.left = bottomRightPortion.left = topPortion.right = bottomPortion.right = r2.right;
horizontalOverlap = true;
} else {
rightPortion.left = topRightPortion.left = bottomRightPortion.left = topPortion.right = bottomPortion.right = r1.left;
if (r2.right == r1.left)
adjacent |= RIGHT;
}
r1Owns |= RIGHT;
}
else
{
rightPortion.right = topRightPortion.right = bottomRightPortion.right = r2.right;
if (r1.right > r2.left) {
rightPortion.left = topRightPortion.left = bottomRightPortion.left = topPortion.right = bottomPortion.right = r1.right;
horizontalOverlap = true;
} else {
rightPortion.left = topRightPortion.left = bottomRightPortion.left = topPortion.right = bottomPortion.right = r2.left;
if (r1.right==r2.left)
adjacent |= LEFT;
}
if (r2.right > r1.right)
r2Owns |= RIGHT;
else
common |= RIGHT;
}
if (r1.bottom > r2.bottom)
{
bottomPortion.bottom = bottomLeftPortion.bottom = bottomRightPortion.bottom = r1.bottom;
if (r2.bottom > r1.top) {
bottomPortion.top = bottomLeftPortion.top = bottomRightPortion.top = leftPortion.bottom = rightPortion.bottom = r2.bottom;
verticalOverlap = true;
} else {
bottomPortion.top = bottomLeftPortion.top = bottomRightPortion.top = leftPortion.bottom = rightPortion.bottom = r1.top;
if (r2.bottom==r1.top)
adjacent |= BOTTOM;
}
r1Owns |= BOTTOM;
}
else
{
bottomPortion.bottom = bottomLeftPortion.bottom = bottomRightPortion.bottom = r2.bottom;
if (r1.bottom > r2.top) {
bottomPortion.top = bottomLeftPortion.top = bottomRightPortion.top = leftPortion.bottom = rightPortion.bottom = r1.bottom;
verticalOverlap = true;
} else {
bottomPortion.top = bottomLeftPortion.top = bottomRightPortion.top = leftPortion.bottom = rightPortion.bottom = r2.top;
if (r1.bottom==r2.top)
adjacent |= TOP;
}
if (r2.bottom > r1.bottom)
r2Owns |= BOTTOM;
else
common |= BOTTOM;
}
if ( common == (LEFT|RIGHT|TOP|BOTTOM))
{
result = OverlapType.SAME;
}
else if ((common & (LEFT|RIGHT)) == (LEFT | RIGHT) && (verticalOverlap || (adjacent & (TOP | BOTTOM)) != 0))
{
result = OverlapType.COALESCIBLE;
coalesced.left = r1.left;
coalesced.right = r1.right;
coalesced.top = topPortion.top;
coalesced.bottom = bottomPortion.bottom;
}
else if ((common & (TOP | BOTTOM)) == (TOP | BOTTOM) && (horizontalOverlap || (adjacent & (LEFT | RIGHT)) != 0))
{
result = OverlapType.COALESCIBLE;
coalesced.left = leftPortion.left;
coalesced.right = rightPortion.right;
coalesced.top = r1.top;
coalesced.bottom = r1.bottom;
}
else if (verticalOverlap && horizontalOverlap) {
if (r2Owns == 0)
{
result = OverlapType.CONTAINED_BY;
}
else if (r1Owns == 0)
{
result = OverlapType.CONTAINS;
}
else
{
// Partial overlap, non coalescible case
result = OverlapType.PARTIAL;
setCornerOwnership();
}
}
return result;
}
}
/**
* Up to 8 Rect objects
* @author Michael A. MacDonald
*
*/
static class NonOverlappingRects
{
ObjectPool.Entry<Rect>[] rectEntries;
int count;
static final int MAX_RECTS = 8;
NonOverlappingRects()
{
rectEntries = new ObjectPool.Entry[MAX_RECTS];
}
private void addOwnedRect(int owner, int direction, ObjectPool<Rect> pool, Rect r)
{
if ((owner & direction)==direction)
{
ObjectPool.Entry<Rect> entry = pool.reserve();
rectEntries[count++] = entry;
entry.get().set(r);
}
}
void Populate(NonOverlappingPortion p, ObjectPool<Rect> pool, int owner)
{
count = 0;
for (int i=0; i<MAX_RECTS; i++)
rectEntries[i] = null;
addOwnedRect(owner,BOTTOM_LEFT,pool,p.bottomLeftPortion);
addOwnedRect(owner,BOTTOM,pool,p.bottomPortion);
addOwnedRect(owner,BOTTOM_RIGHT,pool,p.bottomRightPortion);
addOwnedRect(owner,BOTTOM,pool,p.bottomPortion);
addOwnedRect(owner,TOP_RIGHT,pool,p.topRightPortion);
addOwnedRect(owner,TOP,pool,p.topPortion);
addOwnedRect(owner,TOP_LEFT,pool,p.topLeftPortion);
addOwnedRect(owner,LEFT,pool,p.leftPortion);
}
}
private ArrayList<ObjectPool.Entry<Rect>> list;
private ObjectPool<Rect> pool;
private ObjectPool<NonOverlappingRects> nonOverlappingRectsPool = new ObjectPool<NonOverlappingRects>() {
/* (non-Javadoc)
* @see com.antlersoft.util.ObjectPool#itemForPool()
*/
@Override
protected NonOverlappingRects itemForPool() {
return new NonOverlappingRects();
}
};
private ObjectPool<ArrayList<ObjectPool.Entry<Rect>>> listRectsPool = new ObjectPool<ArrayList<ObjectPool.Entry<Rect>>>() {
/* (non-Javadoc)
* @see com.antlersoft.util.ObjectPool#itemForPool()
*/
@Override
protected ArrayList<Entry<Rect>> itemForPool() {
return new ArrayList<Entry<Rect>>(NonOverlappingRects.MAX_RECTS);
}
};
private NonOverlappingPortion nonOverlappingPortion;
public RectList(ObjectPool<Rect> pool)
{
this.pool = pool;
list = new ArrayList<ObjectPool.Entry<Rect>>();
nonOverlappingPortion = new NonOverlappingPortion();
}
public int getSize()
{
return list.size();
}
public Rect get(int i)
{
return list.get(i).get();
}
/**
* Remove all rectangles from the list and release them from the pool
*/
public void clear()
{
for (int i=list.size()-1; i>=0; i--)
{
ObjectPool.Entry<Rect> r = list.get(i);
pool.release(r);
}
list.clear();
}
private void recursiveAdd(ObjectPool.Entry<Rect> toAdd, int level)
{
if (level>=list.size())
{
list.add(toAdd);
return;
}
Rect addRect = toAdd.get();
ObjectPool.Entry<Rect> thisEntry = list.get(level);
Rect thisRect = thisEntry.get();
switch (nonOverlappingPortion.overlap(thisRect, addRect))
{
case NONE :
recursiveAdd(toAdd,level + 1);
break;
case SAME :
case CONTAINS :
pool.release(toAdd);
break;
case CONTAINED_BY :
pool.release(thisEntry);
list.remove(level);
recursiveAdd(toAdd,level);
break;
case COALESCIBLE :
pool.release(thisEntry);
list.remove(level);
addRect.set(nonOverlappingPortion.coalesced);
recursiveAdd(toAdd,0);
break;
case PARTIAL :
pool.release(toAdd);
ObjectPool.Entry<NonOverlappingRects> rectsEntry = nonOverlappingRectsPool.reserve();
NonOverlappingRects rects = rectsEntry.get();
rects.Populate(nonOverlappingPortion,pool,nonOverlappingPortion.r2Owns);
for (int i=0; i<rects.count; i++)
{
recursiveAdd(rects.rectEntries[i],0);
}
nonOverlappingRectsPool.release(rectsEntry);
break;
}
}
/**
* Add a rectangle to the region of interest
* @param toAdd
*/
public void add(Rect toAdd)
{
// Create a copy of the rect to work with
ObjectPool.Entry<Rect> entry = pool.reserve();
Rect r = entry.get();
r.set(toAdd);
recursiveAdd(entry,0);
}
/**
* Change the rectangle of interest to include only those portions
* that fall inside bounds.
* @param bounds
*/
public void intersect(Rect bounds)
{
int size = list.size();
ObjectPool.Entry<ArrayList<ObjectPool.Entry<Rect>>> listEntry = listRectsPool.reserve();
ArrayList<ObjectPool.Entry<Rect>> newList = listEntry.get();
newList.clear();
for (int i=0; i<size; i++)
{
ObjectPool.Entry<Rect> entry = list.get(i);
Rect rect = entry.get();
if (rect.intersect(bounds))
{
newList.add(entry);
}
else
pool.release(entry);
}
list.clear();
size = newList.size();
for (int i=0; i<size; i++)
{
recursiveAdd(newList.get(i),0);
}
listRectsPool.release(listEntry);
}
/**
* Determines if a rectangle intersects any part of the area of interest
* @param r
* @return True if r intersects any rectangle in the list
*/
public boolean testIntersect(Rect r)
{
int l = list.size();
for (int i = 0; i<l; i++)
{
if (list.get(i).get().intersects(r.left, r.top, r.right, r.bottom))
return true;
}
return false;
}
/**
* Remove the rectangle from the area of interest.
* @param toSubtract
*/
public void subtract(Rect toSubtract)
{
int size = list.size();
ObjectPool.Entry<ArrayList<ObjectPool.Entry<Rect>>> listEntry = listRectsPool.reserve();
ArrayList<ObjectPool.Entry<Rect>> newList = listEntry.get();
newList.clear();
for (int i=0; i<size; i++)
{
ObjectPool.Entry<Rect> entry = list.get(i);
Rect rect = entry.get();
switch (nonOverlappingPortion.overlap(rect, toSubtract))
{
case SAME:
pool.release(entry);
newList.clear();
list.remove(i);
return;
case CONTAINED_BY:
pool.release(entry);
list.remove(i);
i--;
size--;
break;
case NONE:
break;
case COALESCIBLE:
if (!nonOverlappingPortion.verticalOverlap || ! nonOverlappingPortion.horizontalOverlap)
break;
case CONTAINS :
nonOverlappingPortion.setCornerOwnership();
case PARTIAL :
{
ObjectPool.Entry<NonOverlappingRects> rectsEntry = nonOverlappingRectsPool.reserve();
NonOverlappingRects rects = rectsEntry.get();
rects.Populate(nonOverlappingPortion, pool, nonOverlappingPortion.r1Owns);
pool.release(entry);
list.remove(i);
i--;
size--;
for (int j=0; j<rects.count; j++)
{
newList.add(rects.rectEntries[j]);
}
nonOverlappingRectsPool.release(rectsEntry);
}
}
}
size = newList.size();
for (int i=0; i<size; i++)
{
recursiveAdd(newList.get(i),0);
}
listRectsPool.release(listEntry);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("{\n");
for (int i=0; i<getSize(); i++)
{
sb.append(get(i).toString());
sb.append("\n");
}
sb.append("}");
return sb.toString();
}
}

View File

@@ -0,0 +1,83 @@
/**
*
*/
package com.antlersoft.util;
/**
* @author Michael A. MacDonald
*
*/
public class ByteBufferStack {
private byte[] m_buffer;
private int[] m_offsets;
private int m_depth;
private int m_max_depth;
private int m_max_size;
public static final int MAX_DEPTH = 20;
public static final int MAX_SIZE = 1048;
public ByteBufferStack(int maxDepth, int maxSize)
{
m_depth = 0;
m_max_depth = maxDepth;
m_max_size = maxSize;
m_offsets= new int[maxDepth];
m_buffer = new byte[maxSize];
}
public ByteBufferStack()
{
this(MAX_DEPTH, MAX_SIZE);
}
/**
*
* @return Start of the buffer; this value is valid at least until the next call of reserve()
*/
public byte[] getBuffer()
{
return m_buffer;
}
/**
*
* @return Offset in getBuffer() of last reserved region
*/
public int getOffset()
{
return m_offsets[m_depth];
}
public int reserve(int count)
{
if (count < 0 || (count + m_max_size < 0))
throw new IllegalArgumentException("Count must by greater than 0");
if (m_depth == m_max_depth)
{
m_max_depth *= 2;
int[] new_offsets = new int[m_max_depth];
System.arraycopy(m_offsets, 0, new_offsets, 0, m_depth);
m_offsets = new_offsets;
}
int result = m_offsets[m_depth];
int new_size = result + count;
m_offsets[m_depth++] = new_size;
if (new_size > m_max_size)
{
m_max_size = Math.max(2 * m_max_size, new_size);
byte[] new_buffer = new byte[m_max_size];
System.arraycopy(m_buffer, 0, new_buffer, 0, result);
m_buffer = new_buffer;
}
return result;
}
public void release()
{
if (m_depth<1)
{
throw new IllegalStateException("release() without reserve()");
}
m_depth--;
}
}

View File

@@ -0,0 +1,58 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.util;
/**
* A pool of reusable object of a given type. You get the object from a Entry, which you get
* by calling reserve(). When you are done with the object, you call release() passing the Entry.
* <p>
* Failing to call release() does not leak memory--but you will not get the benefits
* of reusing the object. You will run into contention issues if you
* call release() while still holding a reference to the pool object.
* @author Michael A. MacDonald
*
*/
public abstract class ObjectPool<R> {
public static class Entry<S> {
S item;
Entry<S> nextEntry;
Entry(S i, Entry<S> n)
{
item = i;
nextEntry = n;
}
public S get() {
return item;
}
}
private Entry<R> next;
public ObjectPool()
{
next = null;
}
public Entry<R> reserve()
{
if (next == null)
{
next = new Entry<R>(itemForPool(), null);
}
Entry<R> result = next;
next = result.nextEntry;
result.nextEntry = null;
return result;
}
public void release(Entry<R> entry)
{
entry.nextEntry = next;
next = entry;
}
protected abstract R itemForPool();
}

View File

@@ -0,0 +1,29 @@
/**
* Copyright (C) 2009 Michael A. MacDonald
*/
package com.antlersoft.util;
/**
* Synchronized object pool
* @author Michael A. MacDonald
*
*/
public abstract class SafeObjectPool<R> extends ObjectPool<R> {
/* (non-Javadoc)
* @see com.antlersoft.util.ObjectPool#release(com.antlersoft.util.ObjectPool.Entry)
*/
@Override
public synchronized void release(com.antlersoft.util.ObjectPool.Entry<R> entry) {
super.release(entry);
}
/* (non-Javadoc)
* @see com.antlersoft.util.ObjectPool#reserve()
*/
@Override
public synchronized com.antlersoft.util.ObjectPool.Entry<R> reserve() {
return super.reserve();
}
}

View File

@@ -0,0 +1,8 @@
/**
* Dummy package
*/
/**
* @author nito
*
*/
package com.theqvd.android.client;

View File

@@ -0,0 +1,352 @@
/**
* Singleton Class to hold all the configuration strings
*
* Copyright 2009-2014 by Qindel Formacion y Servicios S.L.
*
* xvncpro 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 3 of the License, or
* (at your option) any later version.
*
* xvncpro 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.
*
*/
package com.theqvd.android.xpro;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import net.kdt.pojavlaunch.*;
/**
*
* Class to hold all the configuration strings + the persistent configuration
* of the application stored in the property files
*
* @author nito
*
*/
public class Config {
public final static String specialAndroid22Extension = ".ogg";
public final static String assetscopydir = "xserver";
public final static String vnccmd = "vnc://localhost:5900/C24bit/ben1to";
public final static String x11cmd = "x11://localhost:6000";
private static String targetdir;
public static String xvnc;
public static String xvnccmd;
public static String pocketvncconfigfullpath;
// public final static String xvnc = targetdir + "/usr/X11R6/bin/" + xvncbinary;
// public final static String xvnccmd = xvnc + " :0 -br -localhost -nolisten local -PasswordFile="+targetdir+"/etc/vncpasswd";
public static String xvncbinary = L.xvncbinary;
public final static String notAllowRemoteVncConns = "-localhost";
public final static String psxvnccmd = "/system/bin/ps "+L.xvncbinary;
public final static String serverstartedstring = "^.*?created VNC server for screen 0";
public final static String vncdisconnectedstring = ".*?Connections: closed: 127.0.0.1.*";
// Connections: closed: 127.0.0.1::51506
// Property strings in the property file
public final static String props_hasbeencopied = "hasbeencopied";
public final static String props_pocketconfigcopied = "pocketconfigcopied";
public final static String props_forcexresolution = "forcexresolution";
public final static String props_widthpixels = "widthpixels";
public final static String props_heightpixels = "heightpixels";
public final static String props_keep_x_running = "keepxrunning";
public final static String props_use_android_vnc = "useandroidvnc";
public final static String props_remote_vnc = "useremotevnc";
public final static String props_render = "userender";
public final static String props_xinerama = "usexinerama";
public final static String helpurl = "http://docs.theqvd.com/";
public final static int minPixels = 32;
public final static int maxPixels = 10000;
public final static boolean debug = false;
public final static int notifycopy = 1;
public final static int notifystartx = 2;
public final static int notifynovncinstalled = 3;
public final static int xvncsizerequired = 40; /* 37 MB required */
public final static long xvncsizerequiredinkbytes = xvncsizerequired * 1024L;
public final static String pocketvncconfig = "xvnc.vnc";
// public static String pocketvncconfigfullpath = targetdir + Config.pocketvncconfig;
public final static int INSTALLPACKAGE=1;
public final static int SENDALERT=0;
public final static int SETCOPYPROGRESS=1;
public final static int SETPROGRESSVISIBILITY=2;
public final static int UPDATEBUTTONS=3;
public final static int PRERREQUISITEINSTALLED=4;
public final static int[] messageType = {
SENDALERT, // uses messageTitle and messageText in the setData
SETCOPYPROGRESS, // uses progress in the setData
SETPROGRESSVISIBILITY, // uses progressvisibility in the setData
UPDATEBUTTONS, // no parameters
PRERREQUISITEINSTALLED, // no parameters
};
public final static String messageTitle = "title";
public final static String messageText = "text";
public final static String copyProgress = "progress";
public final static String progressVisibility = "progressVisibility";
// StartActivityForResult codes
public final static int vncActivityRequestCode = 11;
public static String getAbout(String version) {
return "XVnc\nLicense: Licensed under the GPLv3.\nAuthor: support@theqvd.com\nSponsored: http://theqvd.com\nVersion: "+version+"\nRevision: $Revision: 26639 $\nDate: $Date: 2015-03-31 11:51:02 +0200 (Tue, 31 Mar 2015) $";
}
// Class info
static final String tag = L.xvncbinary + "-Config-" +java.util.Map.Entry.class.getSimpleName();
private static Context context;
private static Activity activity;
private static boolean appConfig_force_x_geometry = false,
appConfig_keep_x_running = false,
appConfig_remote_vnc_allowed = false,
appConfig_render = true,
appConfig_xinerama = false;
private static int appConfig_height_pixels = 0, appConfig_width_pixels = 0,
appConfig_defaultHeightPixels = 0, appconfig_defaultWidthPixels = 0;
private static VncViewerAndroid androidvncviewer;
private static Handler uiHandler;
// private Prerrequisite[] prerrequisites;
// Set installPrerrequisitesOnStart to true if you want to finish the activity
// after installation
private static boolean installPrerrequisitesOnStart = false;
private void init() {
Log.i(tag, "The CPU type from CPU_ABI is "+android.os.Build.CPU_ABI);
setTargetdir(Tools.datapath + "/xvncfiles");
pocketvncconfigfullpath = getTargetdir() + "/" + Config.pocketvncconfig;
xvnc = getTargetdir() + "/usr/X11R6/bin/" + L.xvncbinary;
if (android.os.Build.CPU_ABI.equals("x86")) {
xvnc += "i386";
} else if (android.os.Build.CPU_ABI.startsWith("arm")) {
// do not do anything
} else {
Log.e(tag, "Unknown CPU_ABI is neither x86 and not arm*");
// TODO throw error here?
}
//xvnc += specialAndroid22Extension;
xvnccmd = xvnc + " :0 -br -nolisten local -pixelformat rgb888 -pixdepths 1 4 8 15 16 24 32 -PasswordFile="+getTargetdir()+"/etc/vncpasswd";
setHeightAndWidth();
load_properties();
}
public Config(Context c) {
context = c;
init();
}
public Config(Activity a) {
context = a;
activity = a;
init();
}
private void setHeightAndWidth() {
// Set height and width
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
Log.d(tag, "setHeightAndWidth:The Build.VERSION is:"+Build.VERSION.SDK_INT+
" and the initial width and height is:"+widthPixels+","+heightPixels);
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
Log.d(tag, "setHeightAndWidth:The Build.VERSION is greater than 17:"+Build.VERSION.SDK_INT);
Point realSize = new Point();
Display.class.getMethod("getSize", Point.class).invoke(d, realSize); //getRealSize gets full screen without decorations
// Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
widthPixels = realSize.x;
heightPixels = realSize.y;
Log.d(tag, "setHeightAndWidth:The Build.VERSION is greater than 17:"+Build.VERSION.SDK_INT+
" and the width and height is:"+widthPixels+","+heightPixels);
} catch (Exception ignored) {
}
// force landscape hack
appConfig_height_pixels = appConfig_defaultHeightPixels = (heightPixels > widthPixels) ? widthPixels : heightPixels;
appConfig_width_pixels = appconfig_defaultWidthPixels = (heightPixels > widthPixels) ? heightPixels : widthPixels;
Log.d(tag, "setHeightAndWidth: The final and the end width and height is:"+
appconfig_defaultWidthPixels+","+appConfig_defaultHeightPixels);
}
private void load_properties() {
// Use default settings
// appConfig_force_x_geometry = true;
// appConfig_keep_x_running = true;
/*
SharedPreferences prefsPrivate;
prefsPrivate = context.getSharedPreferences("PREFS_PRIVATE", Context.MODE_PRIVATE);
appConfig_force_x_geometry = prefsPrivate.getBoolean(Config.props_forcexresolution, appConfig_force_x_geometry);
appConfig_keep_x_running = prefsPrivate.getBoolean(Config.props_keep_x_running, appConfig_keep_x_running);
appConfig_run_androidvnc_client = prefsPrivate.getBoolean(Config.props_use_android_vnc, appConfig_run_androidvnc_client);
appConfig_xvncbinary_copied = prefsPrivate.getBoolean(Config.props_hasbeencopied, appConfig_xvncbinary_copied);
appConfig_height_pixels = prefsPrivate.getInt(Config.props_heightpixels, appConfig_defaultHeightPixels);
appConfig_width_pixels = prefsPrivate.getInt(Config.props_widthpixels, appconfig_defaultWidthPixels);
appConfig_pocketconfig_copied = prefsPrivate.getBoolean(Config.props_pocketconfigcopied, appConfig_pocketconfig_copied);
appConfig_remote_vnc_allowed = prefsPrivate.getBoolean(Config.props_remote_vnc, appConfig_remote_vnc_allowed);
appConfig_render = prefsPrivate.getBoolean(Config.props_render, appConfig_render);
appConfig_xinerama = prefsPrivate.getBoolean(Config.props_xinerama, appConfig_xinerama);
*/
}
private void save_properties() {
/*
SharedPreferences prefsPrivate;
prefsPrivate = context.getSharedPreferences("PREFS_PRIVATE", Context.MODE_PRIVATE);
Editor prefsPrivateEditor = prefsPrivate.edit();
prefsPrivateEditor.putBoolean(Config.props_forcexresolution, appConfig_force_x_geometry);
prefsPrivateEditor.putBoolean(Config.props_keep_x_running, appConfig_keep_x_running);
prefsPrivateEditor.putBoolean(Config.props_use_android_vnc, appConfig_run_androidvnc_client);
prefsPrivateEditor.putBoolean(Config.props_hasbeencopied, appConfig_xvncbinary_copied);
prefsPrivateEditor.putBoolean(Config.props_pocketconfigcopied, appConfig_pocketconfig_copied);
prefsPrivateEditor.putBoolean(Config.props_remote_vnc, appConfig_remote_vnc_allowed);
prefsPrivateEditor.putBoolean(Config.props_render, appConfig_render);
prefsPrivateEditor.putBoolean(Config.props_xinerama, appConfig_xinerama);
prefsPrivateEditor.putInt(Config.props_heightpixels, appConfig_height_pixels);
prefsPrivateEditor.putInt(Config.props_widthpixels, appConfig_width_pixels);
prefsPrivateEditor.commit();
*/
}
public VncViewer getVncViewer() throws XvncproException {
return this.getAndroidvncviewer(); // : this.getPocketcloudvncviewer();
}
public boolean is_force_x_geometry() {
return appConfig_force_x_geometry;
}
public void set_force_x_geometry(
boolean appConfig_force_x_geometry) {
Config.appConfig_force_x_geometry = appConfig_force_x_geometry;
save_properties();
}
public boolean is_keep_x_running() {
return appConfig_keep_x_running;
}
public void set_keep_x_running(boolean appConfig_keep_x_running) {
Config.appConfig_keep_x_running = appConfig_keep_x_running;
save_properties();
}
public boolean isAppConfig_remote_vnc_allowed() {
return appConfig_remote_vnc_allowed;
}
public void setAppConfig_remote_vnc_allowed(
boolean appConfig_remote_vnc_allowed) {
Config.appConfig_remote_vnc_allowed = appConfig_remote_vnc_allowed;
save_properties();
}
public int get_height_pixels() {
return appConfig_height_pixels;
}
public void set_height_pixels(int appConfig_height_pixels) {
Config.appConfig_height_pixels = appConfig_height_pixels;
save_properties();
}
public int get_width_pixels() {
return appConfig_width_pixels;
}
public void set_width_pixels(int appConfig_width_pixels) {
Config.appConfig_width_pixels = appConfig_width_pixels;
save_properties();
}
public int getAppConfig_defaultHeightPixels() {
return appConfig_defaultHeightPixels;
}
public int getAppconfig_defaultWidthPixels() {
return appconfig_defaultWidthPixels;
}
public boolean isAppConfig_render() {
return appConfig_render;
}
public void setAppConfig_render(boolean appConfig_render) {
Config.appConfig_render = appConfig_render;
save_properties();
}
public boolean isAppConfig_xinerama() {
return appConfig_xinerama;
}
public void setAppConfig_xinerama(boolean appConfig_xinerama) {
Config.appConfig_xinerama = appConfig_xinerama;
save_properties();
}
public VncViewerAndroid getAndroidvncviewer() throws XvncproException {
if (activity == null) {
throw new XvncproException(context.getString(L.r_xvncpro_activity_notdefined));
}
androidvncviewer = (androidvncviewer == null) ? new VncViewerAndroid(activity) : androidvncviewer;
return androidvncviewer;
}
public Handler getUiHandler() {
return uiHandler;
}
public void setUiHandler(Handler mHandler) {
Config.uiHandler = mHandler;
// getXvnccopy().setuiHandler(mHandler);
}
public boolean packageInstalled(String packagename) {
ApplicationInfo info;
try{
info = context.getPackageManager().getApplicationInfo(packagename, 0);
} catch( PackageManager.NameNotFoundException e ){
Log.i(tag, packagename + " is not installed");
return false;
}
Log.i(tag, packagename+" is already installed" + info);
return true;
}
public void installPackage(String packagename) {
Log.i(tag, "Requesting installation of "+packagename);
Intent goToMarket = new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id="+packagename));
// goToMarket.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (activity == null) {
Log.i(tag, "Calling installPackage withouth startActivityForResult because activity is null");
context.startActivity(goToMarket);
} else {
Log.d(tag, "Calling installPackage with startActivityForResult because activity is non null");
activity.startActivityForResult(goToMarket, INSTALLPACKAGE);
}
Log.d(tag, "package is installed sending prerrequisite installed for " + packagename);
Message m = getUiHandler().obtainMessage(Config.PRERREQUISITEINSTALLED);
getUiHandler().sendMessage(m);
}
public String getTargetdir() {
return targetdir;
}
public void setTargetdir(String targetdir) {
Config.targetdir = targetdir;
}
public static Activity getActivity() {
return activity;
}
public static void setActivity(Activity activity) {
Config.activity = activity;
}
public static boolean isInstallPrerrequisitesOnStart() {
return installPrerrequisitesOnStart;
}
public static void setInstallPrerrequisitesOnStart(
boolean finishAfterInstallingPrerrequisites) {
Config.installPrerrequisitesOnStart = finishAfterInstallingPrerrequisites;
}
}

View File

@@ -0,0 +1,80 @@
package com.theqvd.android.xpro;
//import android.content.Context;
//import com.theqvd.android.client.R;
/**
*
* This class exists only to highlight the differences between xvncpro and qvdclient
*
* Copyright 2009-2014 by Qindel Formacion y Servicios S.L.
*
* xvncpro 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 3 of the License, or
* (at your option) any later version.
*
* xvncpro 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.
*
*
* @author Nito@Qindel.ES
*
*/
import net.kdt.pojavlaunch.*;
public final class L
{
public final static String xvncbinary = "Xvncpro";
// here is double effort by rewriting R again,
public static final int r_dummylayout = R.layout.dummylayout;
public static final int r_xvncpromain = R.layout.xvncpromain;
public static final int r_xvncmenu = R.menu.xvncmenu;
public static final int r_xvncpro_activity_notdefined = R.string.xvncpro_activity_notdefined;
public static final int r_errorincopytitle = R.string.errorincopytitle;
public static final int r_errorincopy = R.string.errorincopy;
public static final int r_xvnccopy_not_enough_space = R.string.xvnccopy_not_enough_space;
public static final int r_xvnccopy_button_string = R.string.xvnccopy_button_string;
public static final int r_xvnccopy_install_string = R.string.xvnccopy_install_string;
public static final int r_androidvnc_button_string = R.string.androidvnc_button_string;
public static final int r_androidvnc_install_string = R.string.androidvnc_install_string;
public static final int r_pocketvnc_button_string = R.string.pocketvnc_button_string;
public static final int r_pocketvnc_install_string = R.string.pocketvnc_install_string;
public static final int r_installprereqs = R.string.installprereqs;
public static final int r_x11_error = R.string.x11_error;
public static final int r_x11_is_running = R.string.x11_is_running;
public static final int r_ic_xvnc = R.drawable.ic_xvnc;
public static final int r_connectionStartButton = R.id.connectionStartButton;
public static final int r_stopButton = R.id.stopButton;
public static final int r_editText1 = R.id.editText1;
public static final int r_editText2 = R.id.editText2;
public static final int r_consoletext = R.id.consoletext;
public static final int r_toggleForceResolutionButton = R.id.toggleForceResolutionButton;
public static final int r_stopOnVncDisconnectButton = R.id.stopOnVncDisconnectButton;
public static final int r_vncChoiceButton = R.id.vncChoiceButton;
public static final int r_allowRemoteVNCButton = R.id.allowRemoteVNCButton;
public static final int r_renderButton = R.id.renderButton;
public static final int r_xineramaButton = R.id.xineramaButton;
public static final int r_progressbar1 = R.id.progressbar1;
public static final int r_helpitem = R.id.helpitem;
public static final int r_aboutitem = R.id.aboutitem;
public static final int r_changelogitem = R.id.changelogitem;
public static final int r_exititem = R.id.exititem;
public static final int r_error_handler_message = R.string.error_handler_message;
public static final int r_copying = R.string.copying;
public static final int r_checkingfiles = R.string.checkingfiles;
public static final int r_connect_to_x = R.string.connect_to_x;
public static final int r_stopx = R.string.stopx;
public static final int r_launchx = R.string.launchx;
public static final int r_stopdisabled_not_running = R.string.stopdisabled_not_running;
public static final int r_xncpro_helpurl = R.string.xncpro_helpurl;
public static final int r_xvncpro_versionName = R.string.xvncpro_versionName;
public static final int r_xvncpro_changelogtitle = R.string.xvncpro_changelogtitle;
public static final int r_xvncpro_changelog = R.string.xvncpro_changelog;
}

View File

@@ -0,0 +1,25 @@
package com.theqvd.android.xpro;
/**
* Copyright 2009-2014 by Qindel Formacion y Servicios S.L.
*
* xvncpro 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 3 of the License, or
* (at your option) any later version.
*
* xvncpro 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.
*
*/
import android.app.Activity;
import android.app.PendingIntent;
public interface VncViewer /* extends Prerrequisite */ {
public void launchVncViewer() throws XvncproException;
public PendingIntent getContentVncIntent();
public Activity getActivity();
public void stopVncViewer();
}

View File

@@ -0,0 +1,83 @@
package com.theqvd.android.xpro;
/**
* Copyright 2009-2014 by Qindel Formacion y Servicios S.L.
*
* xvncpro 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 3 of the License, or
* (at your option) any later version.
*
* xvncpro 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.
*
*/
import android.app.*;
import android.content.*;
import android.graphics.*;
import android.net.*;
import android.util.*;
import net.kdt.pojavlaunch.prefs.*;
import android.support.v4.app.*;
import android.androidVNC.*;
public class VncViewerAndroid implements VncViewer {
static final String tag = L.xvncbinary + "-VncViewerAndroid-" +java.util.Map.Entry.class.getSimpleName();
final static String vncpackage = "android.androidVNC";
private static Activity activity;
private Config config;
PendingIntent contentVncIntent;
Intent vncIntent;
VncViewerAndroid(Activity a) {
activity = a;
config = new Config(activity);
String cmd = Config.vnccmd;
vncIntent = new Intent(a, VncCanvasActivity.class);
vncIntent.putExtra("x11", Uri.parse(cmd));
// multiple tasks
vncIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
vncIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
// Remove old Create new task
// vncIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contentVncIntent = PendingIntent.getActivity(activity, 0, vncIntent, 0);
}
@Override
public void launchVncViewer() {
Log.i(tag, "launching vncviewer androidvnc with activity="+activity+"; vncIntent="+vncIntent);
Intent intent = (Intent) vncIntent.clone();
if (LauncherPreferences.PREF_FREEFORM) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
ActivityOptionsCompat options = ActivityOptionsCompat.makeBasic();
Rect freeformRect = new Rect(0, 0, dm.widthPixels / 2, dm.heightPixels / 2);
options.setLaunchBounds(freeformRect);
activity.startActivityForResult(intent, Config.vncActivityRequestCode, options.toBundle());
} else {
activity.startActivityForResult(intent, Config.vncActivityRequestCode);
}
// activity.startActivityForResult(intent, Config.vncActivityRequestCode);
}
@Override
public void stopVncViewer() {
Log.i(tag, "Stopping activity with activity code " + Config.vncActivityRequestCode);
activity.finishActivity(Config.vncActivityRequestCode);
}
@Override
public PendingIntent getContentVncIntent() {
return contentVncIntent;
}
@Override
public Activity getActivity() {
return activity;
}
}

View File

@@ -0,0 +1,331 @@
package com.theqvd.android.xpro;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
/**
*
* This class represents an XserverService
*
*
* Copyright 2009-2014 by Qindel Formacion y Servicios S.L.
*
* xvncpro 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 3 of the License, or
* (at your option) any later version.
*
* xvncpro 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.
*
* @author nito
*
*/
public class XserverService extends Service
implements Runnable
{
final static String tag = L.xvncbinary + "-XserverService-" +java.util.Map.Entry.class.getSimpleName();
private Thread aThread;
private static Process process;
static private boolean xserverrunning = false;
static private int pid = -1;
private Config config;
static private XserverService instance = null;
@Override
public void onCreate() {
Log.i(tag, "onCreate");
super.onCreate();
config = new Config(this);
instance = this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(tag, "Received start id " + startId + ": " + intent);
super.onStartCommand(intent, flags, startId);
if (isRunning()) {
launchVNC();
return START_STICKY;
}
aThread = new Thread (this);
aThread.start();
return START_STICKY;
}
private void stopXvnc() {
if (isRunning()) {
Log.i(tag, "stop pid " + getPid());
process.destroy();
android.os.Process.killProcess(getPid());
setRunning(false);
setPid(-1);
android.os.Process.sendSignal(getPid(), android.os.Process.SIGNAL_QUIT);
updateButtons();
}
}
@Override
public void onDestroy() {
Log.i(tag, "onDestroy");
stopVNC();
if (isRunning()) {
Log.i(tag, "onDestroy xserverrunning destroy " + getPid());
stopXvnc();
}
cancelNotify();
updateButtons();
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
Log.i(tag, "onBind");
return null;
}
private void launchVNC() {
VncViewer v;
try {
v = config.getVncViewer();
v.launchVncViewer();
} catch (XvncproException e) {
sendNotify(getString(L.r_x11_error), "Pid:"+e.toString());
}
}
private void stopVNC() {
VncViewer v;
try {
v = config.getVncViewer();
v.stopVncViewer();
} catch (XvncproException e) {
sendNotify(getString(L.r_x11_error), "Pid:"+e.toString());
}
}
@Override
public void run() {
String cmd = Config.xvnccmd+" -geometry "+ config.get_width_pixels() + "x" + config.get_height_pixels();
cmd += config.isAppConfig_remote_vnc_allowed() ? "" : " " + Config.notAllowRemoteVncConns;
cmd += config.isAppConfig_render() ? " +render" : "";
cmd += config.isAppConfig_xinerama() ? " +xinerama" : "";
Log.i(tag, "launching:"+cmd);
String cmdList[] = cmd.split("[ ]+");
try {
process = new ProcessBuilder().command(cmdList).redirectErrorStream(true).start();
setPid(parsePid(process));
setRunning(true);
isRunning();
Log.i(tag, "after launch:<"+cmd+"> = "+process.toString() + "," + process.hashCode() + "," + process.getClass());
InputStream in = process.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr, 128);
String line;
while ((line = br.readLine()) != null) {
Log.d(tag, "Read string <"+line+">");
if (line.matches(Config.serverstartedstring)) {
Log.i(tag, "Found string <"+line+"> launching VNC client");
launchVNC();
updateButtons();
}
// For AndroidVNC error see
// See http://code.google.com/p/android-vnc-viewer/issues/detail?id=299
if (line.matches(Config.vncdisconnectedstring)) {
Log.i(tag, "Found string <"+line+">");
stopVNC();
if (!config.is_keep_x_running()) {
Log.i(tag, "Stopping Xvnc service");
stopXvnc();
this.stopSelf();
}
}
}
process.waitFor();
Log.i(tag, "Xvnc Process has died");
} catch (IOException e) {
Log.e(tag, "IOException:"+e.toString());
sendNotify(getString(L.r_x11_error), "Pid:"+e.toString());
} catch (InterruptedException e) {
Log.e(tag, "InterruptedException:"+e.toString());
sendNotify(getString(L.r_x11_error), "Pid:"+e.toString());
} finally {
if (!config.is_keep_x_running()) {
Log.i(tag, "Stopping Xvnc service (step 2)");
stopXvnc();
stopVNC();
stopSelf();
}
}
}
private static int parsePid(Process p) {
int pid;
String s = p.toString();
Log.d(tag, "parsePid for process String <"+s+">");
Pattern pattern = Pattern.compile("id=([0-9]+)[^0-9].*$");
Matcher m = pattern.matcher(s);
if (m.find()) {
Log.d(tag, "Pattern <"+pattern+"> found in string " + s + " with matching part "+m.group(1));
pid = Integer.parseInt(m.group(1));
} else
{
Log.e(tag, "Pattern <"+pattern+"> not found in string " + s + ". Trouble ahead when stopping");
pid = -1;
}
return pid;
}
public int getPid() {
return pid;
}
private void setPid(int pid) {
Log.d(tag, "Setting pid to " + pid);
XserverService.pid = pid;
}
private static int searchForXvncPid() {
String psoutput = "";
int pidfound = -1;
String cmd = Config.psxvnccmd;
String cmdList[] = cmd.split("[ ]+");
try {
process = new ProcessBuilder().command(cmdList).redirectErrorStream(true).start();
Log.i(tag, "after launch:<"+cmd+"> = "+process.toString() + "," + process.hashCode() + "," + process.getClass());
InputStream in = process.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
psoutput += line + "\n";
Log.d(tag, "Read string <"+line+">");
}
} catch (IOException e) {
Log.e(tag, "Error executing <"+cmd+"> "+e.toString());
return pidfound;
}
Pattern pattern = Pattern.compile("(?m)^\\S+\\s+(\\d+)\\s+.*?"+L.xvncbinary+"$");
Matcher m = pattern.matcher(psoutput);
if (m.find()) {
Log.d(tag, "Pattern <"+pattern+"> found in string <" + psoutput + "> with matching part "+m.group(1));
pidfound = Integer.parseInt(m.group(1));
} else
{
Log.d(tag, "Pattern <"+pattern+"> not found in string <" + psoutput + ">");
}
return pidfound;
}
public boolean isRunning() {
Log.d(tag, "Running is "+xserverrunning + " pid="+pid);
if (XserverService.xserverrunning) {
File file=new File("/proc/" + pid);
boolean exists = file.exists();
if (exists) {
sendNotify(getString(L.r_x11_is_running), "Pid:"+XserverService.pid);
return XserverService.xserverrunning;
}
// Pid no longer there
Log.i(tag, "The process was supposed to be running but pid "+pid+" is no longer there, setting running to false");
}
XserverService.pid=searchForXvncPid();
XserverService.xserverrunning = (XserverService.pid != -1);
if (XserverService.xserverrunning) {
sendNotify(getString(L.r_x11_is_running), "Pid:"+XserverService.pid);
} else {
cancelNotify();
}
return XserverService.xserverrunning;
}
private void setRunning(boolean value) {
Log.d(tag, "Setting xserverrunning to "+value);
XserverService.xserverrunning = value;
updateButtons();
}
private void updateButtons() {
Log.d(tag, "message updateButtons");
if (config.getUiHandler() == null) {
Log.d(tag, "message updateButtons not sent because uiHandler is null");
return;
}
Message m = config.getUiHandler().obtainMessage(Config.UPDATEBUTTONS);
config.getUiHandler().sendMessage(m);
}
private void sendAlert(String title, String text) {
Log.d(tag, "message sendAlert");
if (config.getUiHandler() == null) {
Log.d(tag, "message sendAlert not sent because uiHandler is null");
return;
}
Message m = config.getUiHandler().obtainMessage(Config.SENDALERT);
Bundle b = new Bundle();
b.putString(Config.messageTitle, title);
b.putString(Config.messageText, text);
m.setData(b);
config.getUiHandler().sendMessage(m);
}
public static XserverService getInstance() {
return instance;
}
//@SuppressWarnings("deprecation")
private void sendNotify(CharSequence title, CharSequence text) {
Context c = this.getApplicationContext();
// TODO try to set the DummyActivity as the intent
// Intent dummyactivity = new Intent(this, DummyActivity.class);
// dummyactivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// PendingIntent i = PendingIntent.getActivity(c, 0, new Intent(), 0);
// End of TODO
PendingIntent i = null;
if (config == null) {
Log.i(tag, "Not sending notify because config is null. This should not happen");
return;
}
try {
i = config.getVncViewer().getContentVncIntent();
Log.i(tag, "activity is "+c+" intent is "+i);
} catch (XvncproException e) {
Log.e(tag, "Vnc intent error "+e.toString());
}
if (config == null) {
Log.i(tag, "Not sending notify because config, vncViewer, or context is null");
return;
}
if (i == null) {
Log.e(tag, "PendingIntent is null creating empty PendingIntent");
i = PendingIntent.getActivity(c, 0, new Intent(), 0);
}
Notification notification = new Notification(L.r_ic_xvnc, title, System.currentTimeMillis());
notification.setLatestEventInfo(c, title, text, i);
NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(Config.notifystartx, notification);
Log.i(tag, "Sent notify with id <"+Config.notifystartx+">title <" +title+"> and text <" + text +">");
}
public void cancelNotify() {
NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel(Config.notifystartx);
Log.i(tag, "Cancelled notify with id <" +Config.notifystartx+">");
}
}

View File

@@ -0,0 +1,26 @@
package com.theqvd.android.xpro;
/**
* Copyright 2009-2014 by Qindel Formacion y Servicios S.L.
*
* xvncpro 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 3 of the License, or
* (at your option) any later version.
*
* xvncpro 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.
*
*/
public class XvncproException extends Exception {
private static final long serialVersionUID = 1L;
public XvncproException(String s) {
super(s);
}
}

View File

@@ -7,7 +7,8 @@ import android.support.design.widget.*;
import android.support.v4.app.*;
import android.support.v4.view.*;
import android.support.v7.app.*;
import android.util.*;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.*;
import android.widget.*;
import android.widget.AdapterView.*;
@@ -34,6 +35,8 @@ import android.graphics.*;
import android.content.pm.*;
import android.text.*;
import com.kdt.mcgui.*;
import com.theqvd.android.xpro.*;
import android.net.*;
public class MCLauncherActivity extends AppCompatActivity
{
@@ -620,26 +623,29 @@ public class MCLauncherActivity extends AppCompatActivity
crashView.setLastCrash("");
try {
/*
List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
jvmArgs.add("-Xms128M");
jvmArgs.add("-Xmx1G");
*/
Intent mainIntent = new Intent(MCLauncherActivity.this, MainConsoleActivity.class);
// mainIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
Intent vncIntent = new Intent(MCLauncherActivity.this, android.androidVNC.VncCanvasActivity.class);
vncIntent.putExtra("x11", Uri.parse(Config.vnccmd));
// multiple tasks
vncIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
vncIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
if (LauncherPreferences.PREF_FREEFORM) {
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
ActivityOptions options = (ActivityOptions) ActivityOptions.class.getMethod("makeBasic").invoke(null);
ActivityOptionsCompat options = ActivityOptionsCompat.makeBasic();
Rect freeformRect = new Rect(0, 0, dm.widthPixels / 2, dm.heightPixels / 2);
options.getClass().getDeclaredMethod("setLaunchBounds", Rect.class).invoke(options, freeformRect);
startActivity(mainIntent, options.toBundle());
options.setLaunchBounds(freeformRect);
startActivityForResult(vncIntent, Config.vncActivityRequestCode, options.toBundle());
} else {
startActivity(mainIntent);
startActivityForResult(vncIntent, Config.vncActivityRequestCode);
}
// Intent mainIntent = new Intent(MCLauncherActivity.this, MainConsoleActivity.class);
// mainIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
}
catch (Throwable e) {
Tools.showError(MCLauncherActivity.this, e);
@@ -654,12 +660,11 @@ public class MCLauncherActivity extends AppCompatActivity
mTask = null;
}
private Gson gsonss = gson;
public static final String MINECRAFT_RES = "http://resources.download.minecraft.net/";
public JAssets downloadIndex(String versionName, File output) throws Exception {
String versionJson = DownloadUtils.downloadString("http://s3.amazonaws.com/Minecraft.Download/indexes/" + versionName + ".json");
JAssets version = gsonss.fromJson(versionJson, JAssets.class);
JAssets version = gson.fromJson(versionJson, JAssets.class);
output.getParentFile().mkdirs();
Tools.write(output.getAbsolutePath(), versionJson.getBytes(Charset.forName("UTF-8")));
return version;

View File

@@ -17,6 +17,7 @@ import android.graphics.*;
import android.view.*;
import android.text.method.*;
import net.kdt.pojavlaunch.prefs.*;
import net.kdt.pojavlaunch.value.*;
public class MainConsoleActivity extends AppCompatActivity
{
@@ -83,6 +84,13 @@ public class MainConsoleActivity extends AppCompatActivity
private void launchJava(String modPath) {
try {
/*
* 17w43a and above change Minecraf arguments from
* `minecraftArguments` to `arguments` so check if
* selected version requires LWJGL 3 or not is easy.
*/
boolean isLwjgl3 = mVersionInfo.arguments != null;
List<String> mJreArgs = new ArrayList<String>();
mJreArgs.add("java");
mJreArgs.add("-Duser.home=" + Tools.MAIN_PATH);
@@ -111,6 +119,7 @@ public class MainConsoleActivity extends AppCompatActivity
* Useful if enable root mode */
process.writeToProcess("chmod -R 700 " + Tools.homeJreDir);
process.writeToProcess("cd " + Tools.MAIN_PATH);
process.writeToProcess("export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/minecraft_lib/lwjgl" + (isLwjgl3 ? "3" : "2"));
process.writeToProcess(mJreArgs.toArray(new String[0]));
} catch (Throwable th) {
th.printStackTrace();

View File

@@ -445,9 +445,12 @@ public class PojavLoginActivity extends MineActivity
// Extract launcher_profiles.json
// TODO: Remove after implement.
Tools.copyAssetFile(this, "launcher_profiles.json", Tools.MAIN_PATH, false);
Tools.copyAssetFile(this, "ClassWrapper.jar", Tools.libraries, true);
try {
Os.symlink(Tools.homeJreDir, Tools.datapath + "/xvncfiles");
} catch (Throwable ignored) {}
// Yep, the codebase from v1.0.3:
//FileAccess.copyAssetToFolderIfNonExist(this, "1.0.jar", Tools.versnDir + "/1.0");
//FileAccess.copyAssetToFolderIfNonExist(this, "1.7.3.jar", Tools.versnDir + "/1.7.3");

View File

@@ -20,6 +20,10 @@ public class SimpleShellProcess
); //"/system/bin/sh -c \"" + command + "\"");
}
public void terminate() {
process.destroy();
}
public void writeToProcess(String[] args) throws IOException {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < args.length; i++) {

View File

@@ -14,11 +14,6 @@ public class LauncherPreferenceFragment extends PreferenceFragmentCompat
// Disable freeform mode in Android 6.0 or below.
findPreference("freeform").setEnabled(Build.VERSION.SDK_INT >= 24);
SeekBarPreference seek1 = (SeekBarPreference) findPreference("maxDxRefs");
seek1.setMin(0xFFF);
seek1.setMax(0xFFFF);
seek1.setValue(0xFFF);
SeekBarPreference seek2 = (SeekBarPreference) findPreference("timeLongPressTrigger");
seek2.setMin(100);
seek2.setMax(1000);

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Some files were not shown because too many files have changed in this diff Show More