[[project @ 6] james.moger**20081205165724 Ignore-this: f08e547be03be7ae4e54e9a96833fbf8 Major Update * Ported all other encodings except Tight. * Implemented key events. * Implemnted mouse events. * Implemented several color models. * Added password field. * Implemented repeater connection support. * Changed from composited SurfaceView to ImageView which alleges less resource use and also yields built-in scaling. * Force orientation to landscape and prevent responding to configuration (orientation) changes. (configuration changes will reset the VNC connection because onCreate gets called). * Added protocol support for UltraVNC chat mode, although I did not write a chat UI. In 1:1 scaling mode, use the DPAD center key/trackball down button to toggle between "panning" and "mouse control" modes. Other DPAD keys will pan in "panning mode" OR will be cursor keys in "mouse control mode". KNOWN ISSUES: 1. Right click. I have not formulated a plan for that. 2. Ctrl key. I have not formulated a plan for that. 3. CopyRect. Implemented but not working properly. This is likely a problem that may be solved with double buffers, but that will consume too much ram so maybe no CopyRect for Android. (There is a 16MB ram limit per app. Viewing a 1280x800 consumes about 9 MB of RAM.) ] addfile ./androidVNC/src/android/androidVNC/COLORMODEL.java addfile ./androidVNC/src/android/androidVNC/ColorModel256.java addfile ./androidVNC/src/android/androidVNC/ColorModel64.java addfile ./androidVNC/src/android/androidVNC/ColorModel8.java addfile ./androidVNC/src/android/androidVNC/Utils.java addfile ./androidVNC/src/android/androidVNC/VncCanvasActivity.java addfile ./androidVNC/src/android/androidVNC/ZlibInStream.java binary ./androidVNC/src/android/androidVNC/CanvasView.java oldhex *2f2a200a202a2054686973206973206672656520736f6674776172653b20796f752063616e2072 *656469737472696275746520697420616e642f6f72206d6f646966790a202a20697420756e6465 *7220746865207465726d73206f662074686520474e552047656e6572616c205075626c6963204c *6963656e7365206173207075626c69736865642062790a202a20746865204672656520536f6674 *7761726520466f756e646174696f6e3b206569746865722076657273696f6e2032206f66207468 *65204c6963656e73652c206f720a202a2028617420796f7572206f7074696f6e2920616e79206c *617465722076657273696f6e2e0a202a200a202a205468697320736f6674776172652069732064 *6973747269627574656420696e2074686520686f706520746861742069742077696c6c20626520 *75736566756c2c0a202a2062757420574954484f555420414e592057415252414e54593b207769 *74686f7574206576656e2074686520696d706c6965642077617272616e7479206f660a202a204d *45524348414e544142494c495459206f72204649544e45535320464f5220412050415254494355 *4c415220505552504f53452e2020536565207468650a202a20474e552047656e6572616c205075 *626c6963204c6963656e736520666f72206d6f72652064657461696c732e0a202a200a202a2059 *6f752073686f756c642068617665207265636569766564206120636f7079206f66207468652047 *4e552047656e6572616c205075626c6963204c6963656e73650a202a20616c6f6e672077697468 *207468697320736f6674776172653b206966206e6f742c20777269746520746f20746865204672 *656520536f6674776172650a202a20466f756e646174696f6e2c20496e632e2c2035392054656d *706c6520506c616365202d205375697465203333302c20426f73746f6e2c204d41202030323131 *312d313330372c0a202a205553412e0a202a2f0a0a2f2f0a2f2f2043616e766173566965772069 *732074686520416374697669747920666f722073686f77696e6720564e43204465736b746f702e *0a2f2f0a0a7061636b61676520616e64726f69642e616e64726f6964564e433b0a0a696d706f72 *7420616e64726f69642e6f732e42756e646c653b0a696d706f727420616e64726f69642e766965 *772e57696e646f773b0a696d706f727420616e64726f69642e6170702e41637469766974793b0a *2f2f696d706f727420616e64726f69642e7574696c2e4c6f673b0a0a7075626c696320636c6173 *732043616e7661735669657720657874656e6473204163746976697479207b0a0a097072697661 *746520566e6343616e76617320766e6363616e7661733b0a090a20202020404f76657272696465 *0a202020207075626c696320766f6964206f6e4372656174652842756e646c6520696369636c65 *29207b0a0a202020200973757065722e6f6e43726561746528696369636c65293b0a2020202009 *7265717565737457696e646f77466561747572652857696e646f772e464541545552455f4e4f5f *5449544c45293b0a20202020090a202020200942756e646c6520657874726173203d2067657449 *6e74656e7428292e67657445787472617328293b20202020090a2020202009537472696e672069 *70203d206578747261732e676574537472696e672822495022293b0a2020202009696e7420706f *7274203d206578747261732e676574496e742822504f525422293b0a20202020090a2020202020 *202020766e6363616e766173203d206e657720566e6343616e76617328746869732c2069702c20 *706f7274293b0a2020202020202020736574436f6e74656e745669657728766e6363616e766173 *293b0a2020202020202020090a202020207d0a090a7d0a newhex * rmfile ./androidVNC/src/android/androidVNC/CanvasView.java binary ./androidVNC/src/android/androidVNC/HTTPConnectSocket.java oldhex *2f2f0a2f2f2020436f7079726967687420284329203230303220436f6e7374616e74696e204b61 *706c696e736b792c20496e632e2020416c6c205269676874732052657365727665642e0a2f2f0a *2f2f202054686973206973206672656520736f6674776172653b20796f752063616e2072656469 *737472696275746520697420616e642f6f72206d6f646966790a2f2f2020697420756e64657220 *746865207465726d73206f662074686520474e552047656e6572616c205075626c6963204c6963 *656e7365206173207075626c69736865642062790a2f2f2020746865204672656520536f667477 *61726520466f756e646174696f6e3b206569746865722076657273696f6e2032206f6620746865 *204c6963656e73652c206f720a2f2f202028617420796f7572206f7074696f6e2920616e79206c *617465722076657273696f6e2e0a2f2f0a2f2f20205468697320736f6674776172652069732064 *6973747269627574656420696e2074686520686f706520746861742069742077696c6c20626520 *75736566756c2c0a2f2f202062757420574954484f555420414e592057415252414e54593b2077 *6974686f7574206576656e2074686520696d706c6965642077617272616e7479206f660a2f2f20 *204d45524348414e544142494c495459206f72204649544e45535320464f522041205041525449 *43554c415220505552504f53452e2020536565207468650a2f2f2020474e552047656e6572616c *205075626c6963204c6963656e736520666f72206d6f72652064657461696c732e0a2f2f0a2f2f *2020596f752073686f756c642068617665207265636569766564206120636f7079206f66207468 *6520474e552047656e6572616c205075626c6963204c6963656e73650a2f2f2020616c6f6e6720 *77697468207468697320736f6674776172653b206966206e6f742c20777269746520746f207468 *65204672656520536f6674776172650a2f2f2020466f756e646174696f6e2c20496e632e2c2035 *392054656d706c6520506c616365202d205375697465203333302c20426f73746f6e2c204d4120 *2030323131312d313330372c0a2f2f20205553412e0a2f2f0a0a2f2f0a2f2f2048545450436f6e *6e656374536f636b65742e6a61766120746f67657468657220776974682048545450436f6e6e65 *6374536f636b6574466163746f72792e6a6176610a2f2f20696d706c656d656e7420616e20616c *7465726e6174652077617920746f20636f6e6e65637420746f20564e4320736572766572732076 *6961206f6e65206f722074776f0a2f2f20485454502070726f7869657320737570706f7274696e *6720746865204854545020434f4e4e454354206d6574686f642e0a2f2f0a7061636b6167652061 *6e64726f69642e616e64726f6964564e433b0a0a696d706f7274206a6176612e6e65742e2a3b0a *696d706f7274206a6176612e696f2e2a3b0a0a636c6173732048545450436f6e6e656374536f63 *6b657420657874656e647320536f636b6574207b0a0a20207075626c69632048545450436f6e6e *656374536f636b657428537472696e6720686f73742c20696e7420706f72742c0a090909202020 *537472696e672070726f7879486f73742c20696e742070726f7879506f7274290a202020207468 *726f777320494f457863657074696f6e207b0a0a202020202f2f20436f6e6e65637420746f2074 *68652073706563696669656420485454502070726f78790a2020202073757065722870726f7879 *486f73742c2070726f7879506f7274293b0a0a202020202f2f2053656e642074686520434f4e4e *45435420726571756573740a202020206765744f757470757453747265616d28292e7772697465 *282822434f4e4e4543542022202b20686f7374202b20223a22202b20706f7274202b0a09090920 *202020202220485454502f312e305c725c6e5c725c6e22292e67657442797465732829293b0a0a *202020202f2f205265616420746865206669727374206c696e65206f662074686520726573706f *6e73650a2020202044617461496e70757453747265616d206973203d206e65772044617461496e *70757453747265616d28676574496e70757453747265616d2829293b0a20202020427566666572 *656452656164657220696e203d206e6577204275666665726564526561646572286e657720496e *70757453747265616d52656164657228697329293b0a202020200a202020202f2f2d2053747269 *6e6720737472203d2069732e726561644c696e6528293b0a20202020537472696e672073747220 *3d20696e2e726561644c696e6528293b200a202020200a202020202f2f20436865636b20746865 *2048545450206572726f7220636f6465202d2d2069742073686f756c6420626520223230302220 *6f6e20737563636573730a2020202069662028217374722e737461727473576974682822485454 *502f312e302032303020222929207b0a202020202020696620287374722e737461727473576974 *682822485454502f312e30202229290a09737472203d207374722e737562737472696e67283929 *3b0a2020202020207468726f77206e657720494f457863657074696f6e282250726f7879207265 *706f727473205c2222202b20737472202b20225c2222293b0a202020207d0a0a202020202f2f20 *53756363657373202d2d20736b69702072656d61696e696e67204854545020686561646572730a *20202020646f207b0a2020202020202f2f2d20737472203d2069732e726561644c696e6528293b *0a2020202009737472203d20696e2e726561644c696e6528293b0a202020207d207768696c6520 *287374722e6c656e677468282920213d2030293b0a20207d0a7d0a0a newhex * rmfile ./androidVNC/src/android/androidVNC/HTTPConnectSocket.java binary ./androidVNC/src/android/androidVNC/HTTPConnectSocketFactory.java oldhex *2f2f0a2f2f2020436f7079726967687420284329203230303220436f6e7374616e74696e204b61 *706c696e736b792c20496e632e2020416c6c205269676874732052657365727665642e0a2f2f0a *2f2f202054686973206973206672656520736f6674776172653b20796f752063616e2072656469 *737472696275746520697420616e642f6f72206d6f646966790a2f2f2020697420756e64657220 *746865207465726d73206f662074686520474e552047656e6572616c205075626c6963204c6963 *656e7365206173207075626c69736865642062790a2f2f2020746865204672656520536f667477 *61726520466f756e646174696f6e3b206569746865722076657273696f6e2032206f6620746865 *204c6963656e73652c206f720a2f2f202028617420796f7572206f7074696f6e2920616e79206c *617465722076657273696f6e2e0a2f2f0a2f2f20205468697320736f6674776172652069732064 *6973747269627574656420696e2074686520686f706520746861742069742077696c6c20626520 *75736566756c2c0a2f2f202062757420574954484f555420414e592057415252414e54593b2077 *6974686f7574206576656e2074686520696d706c6965642077617272616e7479206f660a2f2f20 *204d45524348414e544142494c495459206f72204649544e45535320464f522041205041525449 *43554c415220505552504f53452e2020536565207468650a2f2f2020474e552047656e6572616c *205075626c6963204c6963656e736520666f72206d6f72652064657461696c732e0a2f2f0a2f2f *2020596f752073686f756c642068617665207265636569766564206120636f7079206f66207468 *6520474e552047656e6572616c205075626c6963204c6963656e73650a2f2f2020616c6f6e6720 *77697468207468697320736f6674776172653b206966206e6f742c20777269746520746f207468 *65204672656520536f6674776172650a2f2f2020466f756e646174696f6e2c20496e632e2c2035 *392054656d706c6520506c616365202d205375697465203333302c20426f73746f6e2c204d4120 *2030323131312d313330372c0a2f2f20205553412e0a2f2f0a0a2f2f0a2f2f2048545450436f6e *6e656374536f636b6574466163746f72792e6a61766120746f6765746865722077697468204854 *5450436f6e6e656374536f636b65742e6a6176610a2f2f20696d706c656d656e7420616e20616c *7465726e6174652077617920746f20636f6e6e65637420746f20564e4320736572766572732076 *6961206f6e65206f722074776f0a2f2f20485454502070726f7869657320737570706f7274696e *6720746865204854545020434f4e4e454354206d6574686f642e0a2f2f0a7061636b6167652061 *6e64726f69642e616e64726f6964564e433b0a0a2f2f2d20696d706f7274206a6176612e617070 *6c65742e2a3b0a696d706f7274206a6176612e6e65742e2a3b0a696d706f7274206a6176612e69 *6f2e2a3b0a0a636c6173732048545450436f6e6e656374536f636b6574466163746f727920696d *706c656d656e747320536f636b6574466163746f7279207b0a0a20202f2a2d0a20207075626c69 *6320536f636b657420637265617465536f636b657428537472696e6720686f73742c20696e7420 *706f72742c204170706c6574206170706c6574290a202020207468726f777320494f4578636570 *74696f6e207b0a0a2020202072657475726e20637265617465536f636b657428686f73742c2070 *6f72742c0a0909096170706c65742e676574506172616d65746572282250524f5859484f535431 *22292c0a0909096170706c65742e676574506172616d65746572282250524f5859504f52543122 *29293b0a20207d0a20202a2f0a0a20207075626c696320536f636b657420637265617465536f63 *6b657428537472696e6720686f73742c20696e7420706f72742c20537472696e675b5d20617267 *73290a202020207468726f777320494f457863657074696f6e207b0a0a2020202072657475726e *20637265617465536f636b657428686f73742c20706f72742c0a09090972656164417267286172 *67732c202250524f5859484f53543122292c0a0909097265616441726728617267732c20225052 *4f5859504f5254312229293b0a20207d0a0a20207075626c696320536f636b6574206372656174 *65536f636b657428537472696e6720686f73742c20696e7420706f72742c0a0909092020202020 *537472696e672070726f7879486f73742c20537472696e672070726f7879506f7274537472290a *202020207468726f777320494f457863657074696f6e207b0a0a20202020696e742070726f7879 *506f7274203d20303b0a202020206966202870726f7879506f727453747220213d206e756c6c29 *207b0a202020202020747279207b0a0970726f7879506f7274203d20496e74656765722e706172 *7365496e742870726f7879506f7274537472293b0a2020202020207d20636174636820284e756d *626572466f726d6174457863657074696f6e206529207b207d0a202020207d0a0a202020206966 *202870726f7879486f7374203d3d206e756c6c207c7c2070726f7879506f7274203d3d20302920 *7b0a20202020202053797374656d2e6f75742e7072696e746c6e2822496e636f6d706c65746520 *706172616d65746572206c69737420666f722048545450436f6e6e656374536f636b657422293b *0a20202020202072657475726e206e657720536f636b657428686f73742c20706f7274293b0a20 *2020207d0a0a2020202053797374656d2e6f75742e7072696e746c6e28224854545020434f4e4e *454354207669612070726f78792022202b2070726f7879486f7374202b0a090920202020202020 *2220706f72742022202b2070726f7879506f7274293b0a2020202048545450436f6e6e65637453 *6f636b65742073203d0a2020202020206e65772048545450436f6e6e656374536f636b65742868 *6f73742c20706f72742c2070726f7879486f73742c2070726f7879506f7274293b0a0a20202020 *72657475726e2028536f636b657429733b0a20207d0a0a20207072697661746520537472696e67 *207265616441726728537472696e675b5d20617267732c20537472696e67206e616d6529207b0a *0a20202020666f722028696e742069203d20303b2069203c20617267732e6c656e6774683b2069 *202b3d203229207b0a20202020202069662028617267735b695d2e657175616c7349676e6f7265 *43617365286e616d652929207b0a09747279207b0a09202072657475726e20617267735b692b31 *5d3b0a097d2063617463682028457863657074696f6e206529207b0a09202072657475726e206e *756c6c3b0a097d0a2020202020207d0a202020207d0a2020202072657475726e206e756c6c3b0a *20207d0a7d0a0a newhex * rmfile ./androidVNC/src/android/androidVNC/HTTPConnectSocketFactory.java binary ./androidVNC/src/android/androidVNC/SocketFactory.java oldhex *2f2f0a2f2f2020436f7079726967687420284329203230303220486f72697a6f6e4c6976652e63 *6f6d2c20496e632e2020416c6c205269676874732052657365727665642e0a2f2f0a2f2f202054 *686973206973206672656520736f6674776172653b20796f752063616e20726564697374726962 *75746520697420616e642f6f72206d6f646966790a2f2f2020697420756e646572207468652074 *65726d73206f662074686520474e552047656e6572616c205075626c6963204c6963656e736520 *6173207075626c69736865642062790a2f2f2020746865204672656520536f6674776172652046 *6f756e646174696f6e3b206569746865722076657273696f6e2032206f6620746865204c696365 *6e73652c206f720a2f2f202028617420796f7572206f7074696f6e2920616e79206c6174657220 *76657273696f6e2e0a2f2f0a2f2f20205468697320736f66747761726520697320646973747269 *627574656420696e2074686520686f706520746861742069742077696c6c206265207573656675 *6c2c0a2f2f202062757420574954484f555420414e592057415252414e54593b20776974686f75 *74206576656e2074686520696d706c6965642077617272616e7479206f660a2f2f20204d455243 *48414e544142494c495459206f72204649544e45535320464f52204120504152544943554c4152 *20505552504f53452e2020536565207468650a2f2f2020474e552047656e6572616c205075626c *6963204c6963656e736520666f72206d6f72652064657461696c732e0a2f2f0a2f2f2020596f75 *2073686f756c642068617665207265636569766564206120636f7079206f662074686520474e55 *2047656e6572616c205075626c6963204c6963656e73650a2f2f2020616c6f6e67207769746820 *7468697320736f6674776172653b206966206e6f742c20777269746520746f2074686520467265 *6520536f6674776172650a2f2f2020466f756e646174696f6e2c20496e632e2c2035392054656d *706c6520506c616365202d205375697465203333302c20426f73746f6e2c204d41202030323131 *312d313330372c0a2f2f20205553412e0a2f2f0a0a2f2f0a2f2f20536f636b6574466163746f72 *792e6a6176612064657363726962657320616e20696e74657266616365207573656420746f2073 *756273746974757465207468650a2f2f207374616e6461726420536f636b657420636c61737320 *62792069747320616c7465726e617469766520696d706c656d656e746174696f6e732e0a2f2f0a *0a7061636b61676520616e64726f69642e616e64726f6964564e433b0a0a2f2f2d20696d706f72 *74206a6176612e6170706c65742e2a3b0a696d706f7274206a6176612e6e65742e2a3b0a696d70 *6f7274206a6176612e696f2e2a3b0a0a7075626c696320696e7465726661636520536f636b6574 *466163746f7279207b0a0a20202f2a2d0a20207075626c696320536f636b657420637265617465 *536f636b657428537472696e6720686f73742c20696e7420706f72742c204170706c6574206170 *706c6574290a202020207468726f777320494f457863657074696f6e3b0a20202a2f0a20207075 *626c696320536f636b657420637265617465536f636b657428537472696e6720686f73742c2069 *6e7420706f72742c20537472696e675b5d2061726773290a202020207468726f777320494f4578 *63657074696f6e3b0a7d0a newhex * rmfile ./androidVNC/src/android/androidVNC/SocketFactory.java hunk ./androidVNC/AndroidManifest.xml 5 - - - - - - - - + + + + + + + + + + + + hunk ./androidVNC/res/layout/main.xml 14 - android:layout_x="45px" hunk ./androidVNC/res/layout/main.xml 15 - /> + android:layout_x="35px"/> hunk ./androidVNC/res/layout/main.xml 23 - android:layout_x="115px" hunk ./androidVNC/res/layout/main.xml 24 - /> + android:layout_x="120px"/> hunk ./androidVNC/res/layout/main.xml 32 - android:layout_x="45px" - android:layout_y="115px" - - /> + android:layout_x="45px" android:layout_y="115px"/> hunk ./androidVNC/res/layout/main.xml 36 - android:layout_width="60px" hunk ./androidVNC/res/layout/main.xml 39 - android:layout_x="115px" - android:layout_y="100px" - /> + android:layout_x="120px" android:layout_width="70px" android:layout_y="100px"/> hunk ./androidVNC/res/layout/main.xml 41 + + + hunk ./androidVNC/res/layout/main.xml 62 - android:layout_x="190px" - android:layout_y="100px" - /> + android:layout_x="195px" android:layout_y="210px"/> hunk ./androidVNC/src/android/androidVNC/COLORMODEL.java 1 +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 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)"; + } + } +} hunk ./androidVNC/src/android/androidVNC/ColorModel256.java 1 +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; + } +} hunk ./androidVNC/src/android/androidVNC/ColorModel64.java 1 +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; + + } +} hunk ./androidVNC/src/android/androidVNC/ColorModel8.java 1 +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; + } +} hunk ./androidVNC/src/android/androidVNC/RfbProto.java 35 +import android.view.KeyEvent; +import android.view.MotionEvent; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 87 - ServerCutText = 3; + ServerCutText = 3, + TextChat = 11; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 155 + // Constants used for UltraVNC chat extension + final static int + CHAT_OPEN = -1, + CHAT_CLOSE = -2, + CHAT_FINISHED = -3; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 893 - int redShift, int greenShift, int blueShift) + int redShift, int greenShift, int blueShift, boolean fGreyScale) // sf@2005) hunk ./androidVNC/src/android/androidVNC/RfbProto.java 912 + b[17] = (byte) (fGreyScale ? 1 : 0); // sf@2005 hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1000 - hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1002 - //- final static int CTRL_MASK = InputEvent.CTRL_MASK; - //- final static int SHIFT_MASK = InputEvent.SHIFT_MASK; - //- final static int META_MASK = InputEvent.META_MASK; - //- final static int ALT_MASK = InputEvent.ALT_MASK; + final static int CTRL_MASK = KeyEvent.META_SYM_ON; + final static int SHIFT_MASK = KeyEvent.META_SHIFT_ON; + final static int META_MASK = 0; + final static int ALT_MASK = KeyEvent.META_ALT_ON; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1012 - /*- hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1014 - void writePointerEvent(MouseEvent evt) throws IOException { - int modifiers = evt.getModifiers(); + void writePointerEvent(MotionEvent evt) throws IOException { + int modifiers = evt.getMetaState(); hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1018 - int mask3 = 4; - if (viewer.options.reverseMouseButtons2And3) { - mask2 = 4; - mask3 = 2; - } - - // Note: For some reason, AWT does not set BUTTON1_MASK on left - // button presses. Here we think that it was the left button if - // modifiers do not include BUTTON2_MASK or BUTTON3_MASK. +// int mask3 = 4; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1020 - if (evt.getID() == MouseEvent.MOUSE_PRESSED) { - if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { + if (evt.getAction() == MotionEvent.ACTION_DOWN) { + if ((modifiers & KeyEvent.META_ALT_ON) != 0) { hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1024 - } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { - pointerMask = mask3; - modifiers &= ~META_MASK; +// } else if ((modifiers & KeyEvent.META_SYM_ON) != 0) { +// pointerMask = mask3; +// modifiers &= ~META_MASK; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1030 - } else if (evt.getID() == MouseEvent.MOUSE_RELEASED) { + } else if (evt.getAction() == MotionEvent.ACTION_UP) { hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1032 - if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { + if ((modifiers & KeyEvent.META_ALT_ON) != 0) { hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1034 - } else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { - modifiers &= ~META_MASK; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1035 +// else if ((modifiers & KeyEvent.META_SYM_ON) != 0) { +// modifiers &= ~META_MASK; +// } hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1043 - int x = evt.getX(); - int y = evt.getY(); + int x = (int) evt.getX(); + int y = (int) evt.getY(); hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1066 - */ hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1072 - /*- - void writeKeyEvent(KeyEvent evt) throws IOException { - - int keyChar = evt.getKeyChar(); - - // - // Ignore event if only modifiers were pressed. - // + boolean writeKeyEvent(int keyCode, KeyEvent evt) throws IOException { hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1074 - // Some JVMs return 0 instead of CHAR_UNDEFINED in getKeyChar(). - if (keyChar == 0) - keyChar = KeyEvent.CHAR_UNDEFINED; - - if (keyChar == KeyEvent.CHAR_UNDEFINED) { - int code = evt.getKeyCode(); - if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_SHIFT || - code == KeyEvent.VK_META || code == KeyEvent.VK_ALT) - return; - } - - // - // Key press or key release? - // - - boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); - - int key; - if (evt.isActionKey()) { - - // - // An action key should be one of the following. - // If not then just ignore the event. - // - - switch(evt.getKeyCode()) { - case KeyEvent.VK_HOME: key = 0xff50; break; - case KeyEvent.VK_LEFT: key = 0xff51; break; - case KeyEvent.VK_UP: key = 0xff52; break; - case KeyEvent.VK_RIGHT: key = 0xff53; break; - case KeyEvent.VK_DOWN: key = 0xff54; break; - case KeyEvent.VK_PAGE_UP: key = 0xff55; break; - case KeyEvent.VK_PAGE_DOWN: key = 0xff56; break; - case KeyEvent.VK_END: key = 0xff57; break; - case KeyEvent.VK_INSERT: key = 0xff63; break; - case KeyEvent.VK_F1: key = 0xffbe; break; - case KeyEvent.VK_F2: key = 0xffbf; break; - case KeyEvent.VK_F3: key = 0xffc0; break; - case KeyEvent.VK_F4: key = 0xffc1; break; - case KeyEvent.VK_F5: key = 0xffc2; break; - case KeyEvent.VK_F6: key = 0xffc3; break; - case KeyEvent.VK_F7: key = 0xffc4; break; - case KeyEvent.VK_F8: key = 0xffc5; break; - case KeyEvent.VK_F9: key = 0xffc6; break; - case KeyEvent.VK_F10: key = 0xffc7; break; - case KeyEvent.VK_F11: key = 0xffc8; break; - case KeyEvent.VK_F12: key = 0xffc9; break; - default: - return; - } - - } else { - - // - // A "normal" key press. Ordinary ASCII characters go straight through. - // For CTRL-, CTRL is sent separately so just send . - // Backspace, tab, return, escape and delete have special keysyms. - // Anything else we ignore. - // - - key = keyChar; - - if (key < 0x20) { - if (evt.isControlDown()) { - key += 0x60; - } else { - switch(key) { - case KeyEvent.VK_BACK_SPACE: key = 0xff08; break; - case KeyEvent.VK_TAB: key = 0xff09; break; - case KeyEvent.VK_ENTER: key = 0xff0d; break; - case KeyEvent.VK_ESCAPE: key = 0xff1b; break; - } - } - } else if (key == 0x7f) { - // Delete - key = 0xffff; - } else if (key > 0xff) { - // JDK1.1 on X incorrectly passes some keysyms straight through, - // so we do too. JDK1.1.4 seems to have fixed this. - // The keysyms passed are 0xff00 .. XK_BackSpace .. XK_Delete - // Also, we pass through foreign currency keysyms (0x20a0..0x20af). - if ((key < 0xff00 || key > 0xffff) && - !(key >= 0x20a0 && key <= 0x20af)) - return; - } - } - - // Fake keyPresses for keys that only generates keyRelease events - if ((key == 0xe5) || (key == 0xc5) || // XK_aring / XK_Aring - (key == 0xe4) || (key == 0xc4) || // XK_adiaeresis / XK_Adiaeresis - (key == 0xf6) || (key == 0xd6) || // XK_odiaeresis / XK_Odiaeresis - (key == 0xa7) || (key == 0xbd) || // XK_section / XK_onehalf - (key == 0xa3)) { // XK_sterling - // Make sure we do not send keypress events twice on platforms - // with correct JVMs (those that actually report KeyPress for all - // keys) - if (down) - brokenKeyPressed = true; - - if (!down && !brokenKeyPressed) { - // We've got a release event for this key, but haven't received - // a press. Fake it. - eventBufLen = 0; - writeModifierKeyEvents(evt.getModifiers()); - writeKeyEvent(key, true); - os.write(eventBuf, 0, eventBufLen); - } - - if (!down) - brokenKeyPressed = false; + boolean down = (evt.getAction() == KeyEvent.ACTION_DOWN); + int key = evt.getDisplayLabel(); + + switch(keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: key = 0xff51; break; + case KeyEvent.KEYCODE_DPAD_UP: key = 0xff52; break; + case KeyEvent.KEYCODE_DPAD_RIGHT: key = 0xff53; break; + case KeyEvent.KEYCODE_DPAD_DOWN: key = 0xff54; break; + case KeyEvent.KEYCODE_DEL: key = 0xff08; break; + case KeyEvent.KEYCODE_ENTER: key = 0xff0d; break; + case KeyEvent.KEYCODE_DPAD_CENTER: key = 0xff0d; break; + default: key = evt.getUnicodeChar(); break; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1089 - writeModifierKeyEvents(evt.getModifiers()); + writeModifierKeyEvents(evt.getMetaState()); hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1097 + return true; hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1138 - */ - hunk ./androidVNC/src/android/androidVNC/RfbProto.java 1234 + void writeOpenChat() throws Exception { + os.write(TextChat); // byte type + os.write(0); // byte pad 1 + os.write(0); // byte pad 2 + os.write(0); // byte pad 2 + writeInt(CHAT_OPEN); // int message length + } + + void writeCloseChat() throws Exception { + os.write(TextChat); // byte type + os.write(0); // byte pad 1 + os.write(0); // byte pad 2 + os.write(0); // byte pad 2 + writeInt(CHAT_CLOSE); // int message length + } + + void writeFinishedChat() throws Exception { + os.write(TextChat); // byte type + os.write(0); // byte pad 1 + os.write(0); // byte pad 2 + os.write(0); // byte pad 2 + writeInt(CHAT_FINISHED); // int message length + } + + String readTextChatMsg() throws Exception { + byte[] pad = new byte[3]; + readFully(pad); + int len = is.readInt(); + if (len == CHAT_OPEN) { + // Remote user requests chat + ///viewer.openChat(); + // Respond to chat request + writeOpenChat(); + return null; + } else if (len == CHAT_CLOSE) { + // Remote user ends chat + ///viewer.closeChat(); + return null; + } else if (len == CHAT_FINISHED) { + // Remote user says chat finished. + // Not sure why I should care about this state. + return null; + } else { + // Remote user sends message!! + if (len > 0) { + byte[] msg = new byte[len]; + readFully(msg); + return new String(msg); + } + } + return null; + } + + public void writeChatMessage(String msg) throws Exception { + os.write(TextChat); // byte type + os.write(0); // byte pad 1 + os.write(0); // byte pad 2 + os.write(0); // byte pad 2 + byte [] bytes = msg.getBytes("8859_1"); + byte [] outgoing = bytes; + if (bytes.length > 4096) { + outgoing = new byte[4096]; + System.arraycopy(bytes, 0, outgoing, 0, 4096); + } + writeInt(outgoing.length); // int message length + os.write(outgoing); // message + } hunk ./androidVNC/src/android/androidVNC/Utils.java 1 +package android.androidVNC; + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.AlertDialog; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.ActivityManager.MemoryInfo; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; + +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(); + } + + public static MemoryInfo getMemoryInfo(Context _context) { + try { + MemoryInfo info = new MemoryInfo(); + ActivityManager manager = (ActivityManager) _context.getSystemService(Context.ACTIVITY_SERVICE); + manager.getMemoryInfo(info); + return info; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static int nextNoticeID = 0; + public static int nextNoticeID() { + nextNoticeID++; + return nextNoticeID; + } + + public static void notify(Context _context, String tickerText) { + NotificationManager manager = (NotificationManager) _context.getSystemService(Context.NOTIFICATION_SERVICE); + Notification n = new Notification(); + n.defaults = Notification.DEFAULT_ALL; + n.tickerText = tickerText; + n.icon = android.R.drawable.stat_sys_warning; + manager.notify(nextNoticeID(), n); + } + + 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, "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(message); + builder.setCancelable(false); + builder.setPositiveButton("Acknowledged", ackHandler); + builder.setIcon(icon); + builder.show(); + } +} hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 24 +// +// VncCanvas is a subclass of android.view.ImageView which draws a VNC +// desktop on it. +// + +// +// Copyright (C) 2004 Horizon Wimba. All Rights Reserved. +// Copyright (C) 2001-2003 HorizonLive.com, Inc. All Rights Reserved. +// Copyright (C) 2001,2002 Constantin Kaplinsky. All Rights Reserved. +// Copyright (C) 2000 Tridia Corporation. All Rights Reserved. +// Copyright (C) 1999 AT&T Laboratories Cambridge. 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. +// + hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 59 +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.util.zip.Inflater; + +import android.app.ProgressDialog; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 66 -import android.graphics.*; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 74 -import android.view.SurfaceView; -import android.view.SurfaceHolder; - -import java.io.IOException; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.widget.ImageView; +import android.widget.Toast; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 79 -public class VncCanvas extends SurfaceView implements SurfaceHolder.Callback{ - SurfaceHolder holder; - private boolean hasSurface; - - private final static String TAG = "AndroidVNC"; +public class VncCanvas extends ImageView { + private final static String TAG = "VncCanvas"; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 82 + // User-provided connection settings hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 85 - - private RfbProto rfb; + private String password; + private String repeaterID; + + // Runtime control flags + private boolean maintainConnection = true; + private boolean showDesktopInfo = true; + private boolean repaintsEnabled = true; + + // Color Model settings + private COLORMODEL pendingColorModel = COLORMODEL.C64; + private COLORMODEL colorModel = null; + private int bytesPerPixel = 0; + private int[] colorPalette = null; + + // VNC protocol connection + public RfbProto rfb; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 102 - private int bytesPerPixel = 4; + // Internal bitmap data hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 104 - private int pixels24[]; - - - public Handler handler = new Handler(); - final Runnable notifyFinished = new Runnable() - { - public void run(){ + private int bitmapPixels[]; + private Canvas memGraphics; + public Handler handler = new Handler(); + + // VNC Encoding parameters + private boolean useCopyRect = false; // TODO CopyRect is not working + private int preferredEncoding = -1; + + // Unimplemented VNC encoding parameters + private boolean requestCursorUpdates = false; + private boolean ignoreCursorUpdates = true; + + // Unimplemented TIGHT encoding parameters + private int compressLevel = -1; + private int jpegQuality = -1; + + // Used to determine if encoding update is necessary + private int[] encodingsSaved = new int[20]; + private int nEncodingsSaved = 0; + + // ZRLE encoder's data. + private byte[] zrleBuf; + private int zrleBufLen = 0; + private int[] zrleTilePixels; + private ZlibInStream zrleInStream; + + // Zlib encoder's data. + private byte[] zlibBuf; + private int zlibBufLen = 0; + private Inflater zlibInflater; + + public VncCanvas(final Context context, String serverIP, int serverPort, String serverPassword, String repeaterid) { + super(context); + this.server = serverIP; + this.port = serverPort; + this.password = serverPassword; + this.repeaterID = repeaterid; + + // Startup the RFB thread with a nifty progess dialog + final ProgressDialog pd = ProgressDialog.show(context, "Connecting...", "Establishing handshake.\nPlease wait...", true, true, new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + closeConnection(); + handler.post(new Runnable() { + public void run() { + Utils.showErrorMessage(context, "VNC connection aborted!"); + } + }); + } + }); + Thread t = new Thread() { + public void run() { + try { + if (repeaterID != null && !repeaterID.equals("")) { + // Connect to Repeater Session + // Passwords are irrelevant. + connectAndAuthenticate(""); + } else { + connectAndAuthenticate(password); + } + doProtocolInitialisation(); + handler.post(new Runnable() { + public void run() { + pd.setMessage("Downloading first frame.\nPlease wait..."); + } + }); + processNormalProtocol(context, pd); + } catch (Throwable e) { + if (maintainConnection) { + Log.v(TAG, e.toString()); + e.printStackTrace(); + // Ensure we dismiss the progress dialog + // before we fatal error finish + if (pd.isShowing()) + pd.dismiss(); + if (e instanceof OutOfMemoryError) { + // TODO Not sure if this will happen but... + // figure out how to gracefully notify the user + // Instantiating an alert dialog here doesn't work + // because we are ouf of memory. :( + } else { + if (e.getMessage().indexOf("authentication") > -1) { + handler.post(new Runnable() { + public void run() { + Utils.showFatalErrorMessage(context, "VNC authentication failed!"); + } + }); + } else { + handler.post(new Runnable() { + public void run() { + Utils.showFatalErrorMessage(context, "VNC connection failed!"); + } + }); + } + } + } + } + } + }; + t.start(); + } + + void connectAndAuthenticate(String pw) throws Exception { + Log.v(TAG, "Connecting to " + server + ", port " + port + "..."); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 209 - Canvas canvas = holder.lockCanvas(); - if(canvas == null) - Log.v(TAG, "canvas is null in handler"); - canvas.drawColor(Color.BLACK); - - Paint textFormat = new Paint(1); - textFormat.setColor(Color.LTGRAY); - canvas.drawText("Connecting. Please wait...", 20, 30, textFormat); - - holder.unlockCanvasAndPost(canvas); + rfb = new RfbProto(server, port); + Log.v(TAG, "Connected to server"); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 212 - try { - connectAndAuthenticate(); - doProtocolInitialisation(); - processNormalProtocol(); - } - catch (Exception e){ - Log.v(TAG, e.toString()); - } - + // + if (repeaterID != null && !repeaterID.equals("")) { + Log.v(TAG, "Negotiating repeater/proxy connection"); + byte[] protocolMsg = new byte[12]; + rfb.is.read(protocolMsg); + byte[] buffer = new byte[250]; + System.arraycopy(repeaterID.getBytes(), 0, buffer, 0, repeaterID.length()); + rfb.os.write(buffer); + } + // + + rfb.readVersionMsg(); + Log.v(TAG, "RFB server supports protocol version " + rfb.serverMajor + "." + rfb.serverMinor); + + rfb.writeVersionMsg(); + Log.v(TAG, "Using RFB protocol version " + rfb.clientMajor + "." + rfb.clientMinor); + + int secType = rfb.negotiateSecurity(); + int authType; + if (secType == RfbProto.SecTypeTight) { + rfb.initCapabilities(); + rfb.setupTunneling(); + authType = rfb.negotiateAuthenticationTight(); + } else { + authType = secType; + } + + switch (authType) { + case RfbProto.AuthNone: + Log.v(TAG, "No authentication needed"); + rfb.authenticateNone(); + break; + case RfbProto.AuthVNC: + Log.v(TAG, "VNC authentication needed"); + rfb.authenticateVNC(pw); + break; + default: + throw new Exception("Unknown authentication scheme " + authType); + } + } + + void doProtocolInitialisation() throws IOException { + rfb.writeClientInit(); + rfb.readServerInit(); + + Log.v(TAG, "Desktop name is " + rfb.desktopName); + Log.v(TAG, "Desktop size is " + rfb.framebufferWidth + " x " + rfb.framebufferHeight); + + mbitmap = Bitmap.createBitmap(rfb.framebufferWidth, rfb.framebufferHeight, Bitmap.Config.RGB_565); + memGraphics = new Canvas(mbitmap); + bitmapPixels = new int[rfb.framebufferWidth * rfb.framebufferHeight]; + + setPixelFormat(); + } + + private void setPixelFormat() throws IOException { + pendingColorModel.setPixelFormat(rfb); + bytesPerPixel = pendingColorModel.bpp(); + colorPalette = pendingColorModel.palette(); + colorModel = pendingColorModel; + pendingColorModel = null; + } + + public void setColorModel(COLORMODEL cm) { + // Only update if color model changes + if (colorModel == null || !colorModel.equals(cm)) + pendingColorModel = cm; + } + + public boolean isColorModel(COLORMODEL cm) { + return (colorModel != null) && colorModel.equals(cm); + } + + public void processNormalProtocol(Context context, ProgressDialog pd) throws Exception { + try { + rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, rfb.framebufferHeight, false); + + // + // main dispatch loop + // + while (maintainConnection) { + + // Read message type from the server. + int msgType = rfb.readServerMessageType(); + + // Process the message depending on its type. + switch (msgType) { + case RfbProto.FramebufferUpdate: + rfb.readFramebufferUpdate(); + @SuppressWarnings("unused") + boolean cursorPosReceived = false; + + for (int i = 0; i < rfb.updateNRects; i++) { + rfb.readFramebufferUpdateRectHdr(); + int rx = rfb.updateRectX, ry = rfb.updateRectY; + int rw = rfb.updateRectW, rh = rfb.updateRectH; + + if (rfb.updateRectEncoding == RfbProto.EncodingLastRect) { + Log.v(TAG, "rfb.EncodingLastRect"); + break; + } + + if (rfb.updateRectEncoding == RfbProto.EncodingNewFBSize) { + rfb.setFramebufferSize(rw, rh); + // - updateFramebufferSize(); + Log.v(TAG, "rfb.EncodingNewFBSize"); + break; + } + + if (rfb.updateRectEncoding == RfbProto.EncodingXCursor || rfb.updateRectEncoding == RfbProto.EncodingRichCursor) { + // - handleCursorShapeUpdate(rfb.updateRectEncoding, + // rx, + // ry, rw, rh); + Log.v(TAG, "rfb.EncodingCursor"); + continue; + + } + + if (rfb.updateRectEncoding == RfbProto.EncodingPointerPos) { + // - softCursorMove(rx, ry); + cursorPosReceived = true; + Log.v(TAG, "rfb.EncodingPointerPos"); + continue; + } + + rfb.startTiming(); + + switch (rfb.updateRectEncoding) { + case RfbProto.EncodingRaw: + handleRawRect(rx, ry, rw, rh); + break; + case RfbProto.EncodingCopyRect: + handleCopyRect(rx, ry, rw, rh); + Log.v(TAG, "CopyRect is Buggy!"); + break; + case RfbProto.EncodingRRE: + handleRRERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingCoRRE: + handleCoRRERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingHextile: + handleHextileRect(rx, ry, rw, rh); + break; + case RfbProto.EncodingZRLE: + handleZRLERect(rx, ry, rw, rh); + break; + case RfbProto.EncodingZlib: + handleZlibRect(rx, ry, rw, rh); + break; + default: + Log.e(TAG, "Unknown RFB rectangle encoding " + rfb.updateRectEncoding + " (0x" + Integer.toHexString(rfb.updateRectEncoding) + ")"); + } + + rfb.stopTiming(); + + // Hide progress dialog + if (pd.isShowing()) + pd.dismiss(); + } + + boolean fullUpdateNeeded = false; + + if (pendingColorModel != null) { + setPixelFormat(); + fullUpdateNeeded = true; + } + + setEncodings(true); + rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, rfb.framebufferHeight, !fullUpdateNeeded); + + break; + + case RfbProto.SetColourMapEntries: + throw new Exception("Can't handle SetColourMapEntries message"); + + case RfbProto.Bell: + Utils.notify(context, "VNC Beep!"); + break; + + case RfbProto.ServerCutText: + String s = rfb.readServerCutText(); + if (s != null && s.length() > 0) { + // TODO implement cut & paste + } + break; + + case RfbProto.TextChat: + // UltraVNC extension + String msg = rfb.readTextChatMsg(); + if (msg != null && msg.length() > 0) { + // TODO implement chat interface + } + break; + + default: + throw new Exception("Unknown RFB message type " + msgType); + } + } + } catch (Exception e) { + throw e; + } finally { + Log.v(TAG, "Closing VNC Connection"); + rfb.close(); + } + } + + public void onDestroy() { + Log.v(TAG, "Cleaning up resources"); + mbitmap.recycle(); + memGraphics = null; + bitmapPixels = null; + } + + void handleRawRect(int x, int y, int w, int h) throws IOException { + handleRawRect(x, y, w, h, true); + } + + void handleRawRect(int x, int y, int w, int h, boolean paint) throws IOException { + int firstoffset = y * rfb.framebufferWidth + x; + if (bytesPerPixel == 1) { + // 1 byte per pixel. Use palette lookup table. + byte[] buf = new byte[w]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + rfb.readFully(buf); + + offset = dy * rfb.framebufferWidth + x; + for (i = 0; i < w; i++) { + bitmapPixels[offset + i] = colorPalette[0xFF & buf[i]]; + } + } + } else { + // 4 bytes per pixel (argb) 24-bit color + byte[] buf = new byte[w * 4]; + int i, offset; + for (int dy = y; dy < y + h; dy++) { + rfb.readFully(buf); + + offset = dy * rfb.framebufferWidth + x; + for (i = 0; i < w; i++) { + bitmapPixels[offset + i] = // 0xFF << 24 | + (buf[i * 4 + 2] & 0xff) << 16 | (buf[i * 4 + 1] & 0xff) << 8 | (buf[i * 4] & 0xff); + } + } + } + + mbitmap.setPixels(bitmapPixels, firstoffset, rfb.framebufferWidth, x, y, w, h); + + if (paint) + reDraw(); + } + + private Runnable reDraw = new Runnable() { + public void run() { + if (showDesktopInfo) { + // Show a Toast with the desktop info on first frame draw. + showDesktopInfo = false; + showConnectionInfo(); + } + setImageBitmap(mbitmap); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 475 - - - public VncCanvas(Context context, String serverIP, int serverPort){ - super(context); - server = serverIP; - port = serverPort; - init(); + + private void reDraw() { + if (repaintsEnabled) + handler.post(reDraw); + } + + public void disableRepaints() { + repaintsEnabled = false; + } + + public void enableRepaints() { + repaintsEnabled = true; + } + + public void showConnectionInfo() { + String msg = rfb.desktopName; + int idx = rfb.desktopName.indexOf("("); + if (idx > -1) { + // Breakup actual desktop name from IP addresses for improved + // readability + String dn = rfb.desktopName.substring(0, idx).trim(); + String ip = rfb.desktopName.substring(idx).trim(); + msg = dn + "\n" + ip; + } + msg += "\n" + rfb.framebufferWidth + "x" + rfb.framebufferHeight; + String enc = getEncoding(); + // Encoding might not be set when we display this message + if (enc != null && !enc.equals("")) + msg += ", " + getEncoding() + " encoding, " + colorModel.toString(); + else + msg += ", " + colorModel.toString(); + Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show(); + } + + private String getEncoding() { + switch (preferredEncoding) { + case RfbProto.EncodingRaw: + return "RAW"; + case RfbProto.EncodingTight: + return "TIGHT"; + case RfbProto.EncodingCoRRE: + return "CoRRE"; + case RfbProto.EncodingHextile: + return "HEXTILE"; + case RfbProto.EncodingRRE: + return "RRE"; + case RfbProto.EncodingZlib: + return "ZLIB"; + case RfbProto.EncodingZRLE: + return "ZRLE"; + } + return ""; + } + + public boolean processPointerEvent(MotionEvent evt) { + if (rfb != null && rfb.inNormalProtocol) { + synchronized (rfb) { + try { + rfb.writePointerEvent(evt); + } catch (Exception e) { + e.printStackTrace(); + } + rfb.notify(); + } + return true; + } + return false; + } + + public boolean processLocalKeyEvent(int keyCode, KeyEvent evt) { + if (keyCode == KeyEvent.KEYCODE_MENU) + // Ignore menu key + return true; + if (rfb != null && rfb.inNormalProtocol) { + boolean result = false; + synchronized (rfb) { + try { + result = rfb.writeKeyEvent(keyCode, evt); + } catch (Exception e) { + e.printStackTrace(); + } + rfb.notify(); + } + return result; + } + return false; + } + + public void closeConnection() { + maintainConnection = false; + } + + public int getImageWidth() { + return mbitmap.getWidth(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 570 - - /* - public VncCanvas(Context context, AttributeSet attrs, Map inflateParams){ - super(context, attrs, inflateParams); - init(); + + public int getImageHeight() { + return mbitmap.getHeight(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 575 - public VncCanvas(Context context, AttributeSet attrs, Map inflateParams, int defStyle){ - super(context, attrs, inflateParams, defStyle); - init(); + public int getCenteredXOffset() { + int xoffset = (mbitmap.getWidth() - getWidth()) / 2; + return xoffset; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 579 - */ - - void init(){ - holder = getHolder(); - holder.addCallback(this); - hasSurface = false; + + public int getCenteredYOffset() { + int yoffset = (mbitmap.getHeight() - getHeight()) / 2; + return yoffset; + } + + /** + * Additional Encodings + * + */ + + private void setEncodings(boolean autoSelectOnly) { + if (rfb == null || !rfb.inNormalProtocol) + return; + + if (preferredEncoding == -1) { + // Preferred format is ZRLE + preferredEncoding = RfbProto.EncodingZRLE; + } else { + // Auto encoder selection is not enabled. + if (autoSelectOnly) + return; + } + + int[] encodings = new int[20]; + int nEncodings = 0; + + encodings[nEncodings++] = preferredEncoding; + if (useCopyRect) + encodings[nEncodings++] = RfbProto.EncodingCopyRect; + // if (preferredEncoding != RfbProto.EncodingTight) + // encodings[nEncodings++] = RfbProto.EncodingTight; + if (preferredEncoding != RfbProto.EncodingZRLE) + encodings[nEncodings++] = RfbProto.EncodingZRLE; + if (preferredEncoding != RfbProto.EncodingHextile) + encodings[nEncodings++] = RfbProto.EncodingHextile; + if (preferredEncoding != RfbProto.EncodingZlib) + encodings[nEncodings++] = RfbProto.EncodingZlib; + if (preferredEncoding != RfbProto.EncodingCoRRE) + encodings[nEncodings++] = RfbProto.EncodingCoRRE; + if (preferredEncoding != RfbProto.EncodingRRE) + encodings[nEncodings++] = RfbProto.EncodingRRE; + + if (compressLevel >= 0 && compressLevel <= 9) + encodings[nEncodings++] = RfbProto.EncodingCompressLevel0 + compressLevel; + if (jpegQuality >= 0 && jpegQuality <= 9) + encodings[nEncodings++] = RfbProto.EncodingQualityLevel0 + jpegQuality; + + if (requestCursorUpdates) { + encodings[nEncodings++] = RfbProto.EncodingXCursor; + encodings[nEncodings++] = RfbProto.EncodingRichCursor; + if (!ignoreCursorUpdates) + encodings[nEncodings++] = RfbProto.EncodingPointerPos; + } + + encodings[nEncodings++] = RfbProto.EncodingLastRect; + encodings[nEncodings++] = RfbProto.EncodingNewFBSize; + + boolean encodingsWereChanged = false; + if (nEncodings != nEncodingsSaved) { + encodingsWereChanged = true; + } else { + for (int i = 0; i < nEncodings; i++) { + if (encodings[i] != encodingsSaved[i]) { + encodingsWereChanged = true; + break; + } + } + } + + if (encodingsWereChanged) { + try { + rfb.writeSetEncodings(encodings, nEncodings); + } catch (Exception e) { + e.printStackTrace(); + } + encodingsSaved = encodings; + nEncodingsSaved = nEncodings; + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 659 - - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ - ; + + // + // Handle a CopyRect rectangle. + // + + private void handleCopyRect(int x, int y, int w, int h) throws IOException { + + /** + * This does not work properly yet. + */ + + rfb.readCopyRect(); + Paint paint = new Paint(); + // Source Coordinates + int leftSrc = rfb.copyRectSrcX; + int topSrc = rfb.copyRectSrcY; + int rightSrc = topSrc + w; + int bottomSrc = topSrc + h; + + // Change + int dx = x - rfb.copyRectSrcX; + int dy = y - rfb.copyRectSrcY; + + // Destination Coordinates + int leftDest = leftSrc + dx; + int topDest = topSrc + dy; + int rightDest = rightSrc + dx; + int bottomDest = bottomSrc + dy; + + memGraphics.drawBitmap(mbitmap, new Rect(leftSrc, topSrc, rightSrc, bottomSrc), new Rect(leftDest, topDest, rightDest, bottomDest), paint); + + reDraw(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 692 - - public void surfaceCreated(SurfaceHolder holder){ - hasSurface = true; - handler.post(notifyFinished); - } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 693 - public void surfaceDestroyed(SurfaceHolder holder){ - hasSurface = false; + // + // Handle an RRE-encoded rectangle. + // + + private void handleRRERect(int x, int y, int w, int h) throws IOException { + + int nSubrects = rfb.is.readInt(); + + byte[] bg_buf = new byte[bytesPerPixel]; + rfb.readFully(bg_buf); + int pixel; + if (bytesPerPixel == 1) { + pixel = colorPalette[0xFF & bg_buf[0]]; + } else { + pixel = Color.rgb(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF); + } + Paint paint = new Paint(); + paint.setColor(pixel); + paint.setStyle(Paint.Style.FILL); + memGraphics.drawRect(x, y, x + w, y + h, paint); + + byte[] buf = new byte[nSubrects * (bytesPerPixel + 8)]; + rfb.readFully(buf); + DataInputStream ds = new DataInputStream(new ByteArrayInputStream(buf)); + + int sx, sy, sw, sh; + + for (int j = 0; j < nSubrects; j++) { + if (bytesPerPixel == 1) { + pixel = colorPalette[0xFF & ds.readUnsignedByte()]; + } else { + ds.skip(4); + pixel = Color.rgb(buf[j * 12 + 2] & 0xFF, buf[j * 12 + 1] & 0xFF, buf[j * 12] & 0xFF); + } + sx = x + ds.readUnsignedShort(); + sy = y + ds.readUnsignedShort(); + sw = ds.readUnsignedShort(); + sh = ds.readUnsignedShort(); + + paint.setColor(pixel); + memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint); + } + + reDraw(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 739 - - void connectAndAuthenticate() throws Exception - { + // + // Handle a CoRRE-encoded rectangle. + // + + private void handleCoRRERect(int x, int y, int w, int h) throws IOException { + int nSubrects = rfb.is.readInt(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 746 - // Log.v(TAG, "Initializing..."); - + byte[] bg_buf = new byte[bytesPerPixel]; + rfb.readFully(bg_buf); + int pixel; + if (bytesPerPixel == 1) { + pixel = colorPalette[0xFF & bg_buf[0]]; + } else { + pixel = Color.rgb(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF); + } + Paint paint = new Paint(); + paint.setColor(pixel); + paint.setStyle(Paint.Style.FILL); + memGraphics.drawRect(x, y, x + w, y + h, paint); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 759 - Log.v(TAG, "Connecting to " + server + ", port " + port + "..."); - - rfb = new RfbProto(server, port); - Log.v(TAG, "Connected to server"); - - rfb.readVersionMsg(); - Log.v(TAG, "RFB server supports protocol version " + - rfb.serverMajor + "." + rfb.serverMinor); - - rfb.writeVersionMsg(); - Log.v(TAG, "Using RFB protocol version " + - rfb.clientMajor + "." + rfb.clientMinor); - - int secType = rfb.negotiateSecurity(); - int authType; - if (secType == RfbProto.SecTypeTight) { - //showConnectionStatus("Enabling TightVNC protocol extensions"); - rfb.initCapabilities(); - rfb.setupTunneling(); - authType = rfb.negotiateAuthenticationTight(); - } else { - authType = secType; - } + byte[] buf = new byte[nSubrects * (bytesPerPixel + 4)]; + rfb.readFully(buf); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 762 - switch (authType) { - case RfbProto.AuthNone: - Log.v(TAG, "No authentication needed"); - rfb.authenticateNone(); - break; - case RfbProto.AuthVNC: - /* - showConnectionStatus("Performing standard VNC authentication"); - if (passwordParam != null) { - rfb.authenticateVNC(passwordParam); - } else { - String pw = askPassword(); - rfb.authenticateVNC(pw); - } - */ - Log.v(TAG, "VNC authentication needed"); - break; - default: - throw new Exception("Unknown authentication scheme " + authType); - } - } + int sx, sy, sw, sh; + int i = 0; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 765 - void doProtocolInitialisation() throws IOException - { - rfb.writeClientInit(); - rfb.readServerInit(); - - Log.v(TAG, "Desktop name is " + rfb.desktopName); - Log.v(TAG, "Desktop size is " + rfb.framebufferWidth + " x " + rfb.framebufferHeight); - - mbitmap = Bitmap.createBitmap(rfb.framebufferWidth, rfb.framebufferHeight, Bitmap.Config.RGB_565); - - if(bytesPerPixel == 4) - pixels24 = new int [rfb.framebufferWidth * rfb.framebufferHeight]; - - //- setEncodings(); - // force using true color now - if(bytesPerPixel == 4) - rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0); - // else if(bytesPerPixel == 2) - // rfb.writeSetPixelFormat(16, 16, false, true, 31, 31, 31, 0, 5, 10); + for (int j = 0; j < nSubrects; j++) { + if (bytesPerPixel == 1) { + pixel = colorPalette[0xFF & buf[i++]]; + } else { + pixel = Color.rgb(buf[i + 2] & 0xFF, buf[i + 1] & 0xFF, buf[i] & 0xFF); + i += 4; + } + sx = x + (buf[i++] & 0xFF); + sy = y + (buf[i++] & 0xFF); + sw = buf[i++] & 0xFF; + sh = buf[i++] & 0xFF; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 777 - - - //- showConnectionStatus(null); - } + paint.setColor(pixel); + memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint); + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 781 - // - // Send current encoding list to the RFB server. - // - /* - int[] encodingsSaved; - int nEncodingsSaved; + reDraw(); + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 784 - void setEncodings() { setEncodings(false); } - void autoSelectEncodings() { setEncodings(true); } + // + // Handle a Hextile-encoded rectangle. + // hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 788 - void setEncodings(boolean autoSelectOnly) { - if (options == null || rfb == null || !rfb.inNormalProtocol) - return; + // These colors should be kept between handleHextileSubrect() calls. + private int hextile_bg, hextile_fg; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 791 - int preferredEncoding = options.preferredEncoding; - if (preferredEncoding == -1) { - long kbitsPerSecond = rfb.kbitsPerSecond(); - if (nEncodingsSaved < 1) { - // Choose Tight or ZRLE encoding for the very first update. - System.out.println("Using Tight/ZRLE encodings"); - preferredEncoding = RfbProto.EncodingTight; - } else if (kbitsPerSecond > 2000 && - encodingsSaved[0] != RfbProto.EncodingHextile) { - // Switch to Hextile if the connection speed is above 2Mbps. - System.out.println("Throughput " + kbitsPerSecond + - " kbit/s - changing to Hextile encoding"); - preferredEncoding = RfbProto.EncodingHextile; - } else if (kbitsPerSecond < 1000 && - encodingsSaved[0] != RfbProto.EncodingTight) { - // Switch to Tight/ZRLE if the connection speed is below 1Mbps. - System.out.println("Throughput " + kbitsPerSecond + - " kbit/s - changing to Tight/ZRLE encodings"); - preferredEncoding = RfbProto.EncodingTight; - } else { - // Don't change the encoder. - if (autoSelectOnly) - return; - preferredEncoding = encodingsSaved[0]; - } - } else { - // Auto encoder selection is not enabled. - if (autoSelectOnly) - return; - } + private void handleHextileRect(int x, int y, int w, int h) throws IOException { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 793 - int[] encodings = new int[20]; - int nEncodings = 0; + hextile_bg = Color.BLACK; + hextile_fg = Color.BLACK; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 796 - encodings[nEncodings++] = preferredEncoding; - if (options.useCopyRect) { - encodings[nEncodings++] = RfbProto.EncodingCopyRect; - } + for (int ty = y; ty < y + h; ty += 16) { + int th = 16; + if (y + h - ty < 16) + th = y + h - ty; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 801 - if (preferredEncoding != RfbProto.EncodingTight) { - encodings[nEncodings++] = RfbProto.EncodingTight; - } - if (preferredEncoding != RfbProto.EncodingZRLE) { - encodings[nEncodings++] = RfbProto.EncodingZRLE; - } - if (preferredEncoding != RfbProto.EncodingHextile) { - encodings[nEncodings++] = RfbProto.EncodingHextile; - } - if (preferredEncoding != RfbProto.EncodingZlib) { - encodings[nEncodings++] = RfbProto.EncodingZlib; - } - if (preferredEncoding != RfbProto.EncodingCoRRE) { - encodings[nEncodings++] = RfbProto.EncodingCoRRE; - } - if (preferredEncoding != RfbProto.EncodingRRE) { - encodings[nEncodings++] = RfbProto.EncodingRRE; - } + for (int tx = x; tx < x + w; tx += 16) { + int tw = 16; + if (x + w - tx < 16) + tw = x + w - tx; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 806 - if (options.compressLevel >= 0 && options.compressLevel <= 9) { - encodings[nEncodings++] = - RfbProto.EncodingCompressLevel0 + options.compressLevel; - } - if (options.jpegQuality >= 0 && options.jpegQuality <= 9) { - encodings[nEncodings++] = - RfbProto.EncodingQualityLevel0 + options.jpegQuality; - } + handleHextileSubrect(tx, ty, tw, th); + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 809 - if (options.requestCursorUpdates) { - encodings[nEncodings++] = RfbProto.EncodingXCursor; - encodings[nEncodings++] = RfbProto.EncodingRichCursor; - if (!options.ignoreCursorUpdates) - encodings[nEncodings++] = RfbProto.EncodingPointerPos; - } + // Finished with a row of tiles, now let's show it. + reDraw(); + } + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 814 - encodings[nEncodings++] = RfbProto.EncodingLastRect; - encodings[nEncodings++] = RfbProto.EncodingNewFBSize; + // + // Handle one tile in the Hextile-encoded data. + // hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 818 - boolean encodingsWereChanged = false; - if (nEncodings != nEncodingsSaved) { - encodingsWereChanged = true; - } else { - for (int i = 0; i < nEncodings; i++) { - if (encodings[i] != encodingsSaved[i]) { - encodingsWereChanged = true; - break; - } - } - } + private void handleHextileSubrect(int tx, int ty, int tw, int th) throws IOException { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 820 - if (encodingsWereChanged) { - try { - rfb.writeSetEncodings(encodings, nEncodings); - if (vc != null) { - vc.softCursorFree(); - } - } catch (Exception e) { - e.printStackTrace(); - } - encodingsSaved = encodings; - nEncodingsSaved = nEncodings; - } - } - */ - - public void processNormalProtocol() throws Exception { + int subencoding = rfb.is.readUnsignedByte(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 822 - // Start/stop session recording if necessary. - //- viewer.checkRecordingStatus(); + // Is it a raw-encoded sub-rectangle? + if ((subencoding & RfbProto.HextileRaw) != 0) { + handleRawRect(tx, ty, tw, th, false); + return; + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 828 - rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, - rfb.framebufferHeight, false); + // Read and draw the background if specified. + byte[] cbuf = new byte[bytesPerPixel]; + if ((subencoding & RfbProto.HextileBackgroundSpecified) != 0) { + rfb.readFully(cbuf); + if (bytesPerPixel == 1) { + hextile_bg = colorPalette[0xFF & cbuf[0]]; + } else { + hextile_bg = Color.rgb(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF); + } + } + Paint paint = new Paint(); + paint.setColor(hextile_bg); + paint.setStyle(Paint.Style.FILL); + memGraphics.drawRect(tx, ty, tx + tw, ty + th, paint); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 843 - // - // main dispatch loop - // + // Read the foreground color if specified. + if ((subencoding & RfbProto.HextileForegroundSpecified) != 0) { + rfb.readFully(cbuf); + if (bytesPerPixel == 1) { + hextile_fg = colorPalette[0xFF & cbuf[0]]; + } else { + hextile_fg = Color.rgb(cbuf[2] & 0xFF, cbuf[1] & 0xFF, cbuf[0] & 0xFF); + } + } + + // Done with this tile if there is no sub-rectangles. + if ((subencoding & RfbProto.HextileAnySubrects) == 0) + return; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 857 - while (true) { + int nSubrects = rfb.is.readUnsignedByte(); + int bufsize = nSubrects * 2; + if ((subencoding & RfbProto.HextileSubrectsColoured) != 0) { + bufsize += nSubrects * bytesPerPixel; + } + byte[] buf = new byte[bufsize]; + rfb.readFully(buf); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 865 - // Read message type from the server. - int msgType = rfb.readServerMessageType(); - - // Process the message depending on its type. - switch (msgType) { - case RfbProto.FramebufferUpdate: - // Log.v(TAG, "FrameBuffer Update..."); - rfb.readFramebufferUpdate(); - //boolean cursorPosReceived = false; + int b1, b2, sx, sy, sw, sh; + int i = 0; + if ((subencoding & RfbProto.HextileSubrectsColoured) == 0) { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 869 - for (int i = 0; i < rfb.updateNRects; i++) { - rfb.readFramebufferUpdateRectHdr(); - // Log.v(TAG, "readFramebufferUpdateRectHdr"); - int rx = rfb.updateRectX, ry = rfb.updateRectY; - int rw = rfb.updateRectW, rh = rfb.updateRectH; + // Sub-rectangles are all of the same color. + paint.setColor(hextile_fg); + for (int j = 0; j < nSubrects; j++) { + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint); + } + } else if (bytesPerPixel == 1) { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 882 - if (rfb.updateRectEncoding == RfbProto.EncodingLastRect){ - Log.v(TAG, "rfb.EncodingLastRect"); - break; - } - - if (rfb.updateRectEncoding == RfbProto.EncodingNewFBSize) { - rfb.setFramebufferSize(rw, rh); - //- updateFramebufferSize(); - Log.v(TAG, "rfb.EncodingNewFBSize"); - break; - } + // BGR233 (8-bit color) version for colored sub-rectangles. + for (int j = 0; j < nSubrects; j++) { + hextile_fg = colorPalette[0xFF & buf[i++]]; + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + paint.setColor(hextile_fg); + memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint); + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 895 - if (rfb.updateRectEncoding == RfbProto.EncodingXCursor || - rfb.updateRectEncoding == RfbProto.EncodingRichCursor) { - //- handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh); - Log.v(TAG, "rfb.EncodingCursor"); - continue; - - } + } else { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 897 - if (rfb.updateRectEncoding == RfbProto.EncodingPointerPos) { - //- softCursorMove(rx, ry); - //cursorPosReceived = true; - Log.v(TAG, "rfb.EncodingPointerPos"); - continue; - } + // Full-color (24-bit) version for colored sub-rectangles. + for (int j = 0; j < nSubrects; j++) { + hextile_fg = Color.rgb(buf[i + 2] & 0xFF, buf[i + 1] & 0xFF, buf[i] & 0xFF); + i += 4; + b1 = buf[i++] & 0xFF; + b2 = buf[i++] & 0xFF; + sx = tx + (b1 >> 4); + sy = ty + (b1 & 0xf); + sw = (b2 >> 4) + 1; + sh = (b2 & 0xf) + 1; + paint.setColor(hextile_fg); + memGraphics.drawRect(sx, sy, sx + sw, sy + sh, paint); + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 911 - rfb.startTiming(); + } + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 914 - switch (rfb.updateRectEncoding) { - case RfbProto.EncodingRaw: - handleRawRect(rx, ry, rw, rh); - // Log.v(TAG, "EncodingRaw"); - break; - case RfbProto.EncodingCopyRect: - //- handleCopyRect(rx, ry, rw, rh); - break; - case RfbProto.EncodingRRE: - //- handleRRERect(rx, ry, rw, rh); - break; - case RfbProto.EncodingCoRRE: - //- handleCoRRERect(rx, ry, rw, rh); - break; - case RfbProto.EncodingHextile: - //- handleHextileRect(rx, ry, rw, rh); - Log.v(TAG, "EncodingHextile"); - break; - case RfbProto.EncodingZRLE: - //- handleZRLERect(rx, ry, rw, rh); - Log.v(TAG, "EncodingZRLE"); - break; - case RfbProto.EncodingZlib: - //- handleZlibRect(rx, ry, rw, rh); - Log.v(TAG, "EncodingZlib"); - break; - case RfbProto.EncodingTight: - //- handleTightRect(rx, ry, rw, rh); - Log.v(TAG, "EncodingTight"); - break; - default: - // Log.v(TAG, "Unknown RFB encoding"); - throw new Exception("Unknown RFB rectangle encoding " + - rfb.updateRectEncoding); - } + // + // Handle a ZRLE-encoded rectangle. + // hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 918 - rfb.stopTiming(); - } + private void handleZRLERect(int x, int y, int w, int h) throws Exception { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 920 - boolean fullUpdateNeeded = false; + if (zrleInStream == null) + zrleInStream = new ZlibInStream(); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 923 + int nBytes = rfb.is.readInt(); + if (nBytes > 64 * 1024 * 1024) + throw new Exception("ZRLE decoder: illegal compressed data size"); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 927 - // Defer framebuffer update request if necessary. But wake up - // immediately on keyboard or mouse event. Also, don't sleep - // if there is some data to receive, or if the last update - // included a PointerPos message. - /* - if (viewer.deferUpdateRequests > 0 && - rfb.is.available() == 0 && !cursorPosReceived) { - synchronized(rfb) { - try { - rfb.wait(viewer.deferUpdateRequests); - } catch (InterruptedException e) { - } - } - } - */ - // Before requesting framebuffer update, check if the pixel - // format should be changed. If it should, request full update - // instead of an incremental one. - /* - if (viewer.options.eightBitColors != (bytesPixel == 1)) { - setPixelFormat(); - fullUpdateNeeded = true; - } - - viewer.autoSelectEncodings(); - */ - rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth, - rfb.framebufferHeight, - !fullUpdateNeeded); + if (zrleBuf == null || zrleBufLen < nBytes) { + zrleBufLen = nBytes + 4096; + zrleBuf = new byte[zrleBufLen]; + } hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 932 - break; + rfb.readFully(zrleBuf, 0, nBytes); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 934 - case RfbProto.SetColourMapEntries: - throw new Exception("Can't handle SetColourMapEntries message"); + zrleInStream.setUnderlying(new MemInStream(zrleBuf, 0, nBytes), nBytes); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 936 - case RfbProto.Bell: - //- Toolkit.getDefaultToolkit().beep(); - Log.v(TAG, "Bell"); - break; + for (int ty = y; ty < y + h; ty += 64) { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 938 - case RfbProto.ServerCutText: - Log.v(TAG, "ServerCutText"); - //String s = rfb.readServerCutText(); - //- viewer.clipboard.setCutText(s); - break; + int th = Math.min(y + h - ty, 64); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 940 - default: - throw new Exception("Unknown RFB message type " + msgType); - } - } - } + for (int tx = x; tx < x + w; tx += 64) { hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 942 - - void handleRawRect(int x, int y, int w, int h) throws IOException { - handleRawRect(x, y, w, h, true); - } + int tw = Math.min(x + w - tx, 64); hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 944 - void handleRawRect(int x, int y, int w, int h, boolean paint) throws IOException { - // Log.v(TAG, "handleRawRect"); - - byte[] buf = new byte[w * 4]; - int i, offset; - int firstoffset = y * rfb.framebufferWidth + x; - - - if(bytesPerPixel == 4){ - for (int dy = y; dy < y + h; dy++) { + int mode = zrleInStream.readU8(); + boolean rle = (mode & 128) != 0; + int palSize = mode & 127; + int[] palette = new int[128]; hunk ./androidVNC/src/android/androidVNC/VncCanvas.java 949 - rfb.readFully(buf); - - offset = dy * rfb.framebufferWidth + x; - for(i =0; i 16) ? 8 : ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1))); + int ptr = 0; + int len = tw * th; + if (zrleTilePixels == null || zrleTilePixels.length != len) + zrleTilePixels = new int[len]; + + for (int i = 0; i < th; i++) { + int eol = ptr + tw; + int b = 0; + int nbits = 0; + + while (ptr < eol) { + if (nbits == 0) { + b = zrleInStream.readU8(); + nbits = 8; + } + nbits -= bppp; + int index = (b >> nbits) & ((1 << bppp) - 1) & 127; + if (bytesPerPixel == 1) { + if (index >= colorPalette.length) + Log.e(TAG, "zrlePlainRLEPixels palette lookup out of bounds " + index + " (0x" + Integer.toHexString(index) + ")"); + zrleTilePixels[ptr++] = colorPalette[0xFF & palette[index]]; + } else { + zrleTilePixels[ptr++] = palette[index]; + } + } + } + } + + private void readZrlePlainRLEPixels(int tw, int th) throws Exception { + int ptr = 0; + int end = ptr + tw * th; + if (zrleTilePixels == null || zrleTilePixels.length != end) + zrleTilePixels = new int[end]; + while (ptr < end) { + int pix = readPixel(zrleInStream); + int len = 1; + int b; + do { + b = zrleInStream.readU8(); + len += b; + } while (b == 255); + + if (!(len <= end - ptr)) + throw new Exception("ZRLE decoder: assertion failed" + " (len <= end-ptr)"); + + if (bytesPerPixel == 1) { + while (len-- > 0) + zrleTilePixels[ptr++] = colorPalette[0xFF & pix]; + } else { + while (len-- > 0) + zrleTilePixels[ptr++] = pix; + } + } + } + + private void readZrlePackedRLEPixels(int tw, int th, int[] palette) throws Exception { + + int ptr = 0; + int end = ptr + tw * th; + if (zrleTilePixels == null || zrleTilePixels.length != end) + zrleTilePixels = new int[end]; + while (ptr < end) { + int index = zrleInStream.readU8(); + int len = 1; + if ((index & 128) != 0) { + int b; + do { + b = zrleInStream.readU8(); + len += b; + } while (b == 255); + + if (!(len <= end - ptr)) + throw new Exception("ZRLE decoder: assertion failed" + " (len <= end - ptr)"); + } + + index &= 127; + int pix = palette[index]; + + if (bytesPerPixel == 1) { + while (len-- > 0) + zrleTilePixels[ptr++] = colorPalette[0xFF & pix]; + } else { + while (len-- > 0) + zrleTilePixels[ptr++] = pix; + } + } + } + + // + // Copy pixels from zrleTilePixels8 or zrleTilePixels24, then update. + // + + private void handleUpdatedZrleTile(int x, int y, int w, int h) { + int offsetSrc = 0; + int offsetDst = (y * rfb.framebufferWidth + x); + for (int j = 0; j < h; j++) { + System.arraycopy(zrleTilePixels, offsetSrc, bitmapPixels, offsetDst, w); + offsetSrc += w; + offsetDst += rfb.framebufferWidth; + } + + int firstoffset = y * rfb.framebufferWidth + x; + mbitmap.setPixels(bitmapPixels, firstoffset, rfb.framebufferWidth, x, y, w, h); + } hunk ./androidVNC/src/android/androidVNC/VncCanvasActivity.java 1 +/* + * 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. + */ + +// +// CanvasView is the Activity for showing VNC Desktop. +// +package android.androidVNC; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.Toast; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ImageView.ScaleType; + +public class VncCanvasActivity extends Activity { + private final static String TAG = "VncCanvasActivity"; + + private boolean panningMode = true; + + private VncCanvas vncCanvas; + + private final static int MENU_ITEM_INFO = Menu.FIRST; + private final static int MENU_ITEM_SETTINGS = Menu.FIRST + 1; + private final static int MENU_ITEM_ONE2ONE = Menu.FIRST + 2; + private final static int MENU_ITEM_FITSCREEN = Menu.FIRST + 3; + private final static int MENU_ITEM_DISCONNECT = Menu.FIRST + 4; + + @Override + public void onCreate(Bundle icicle) { + + super.onCreate(icicle); + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + Bundle extras = getIntent().getExtras(); + String host = extras.getString("HOST"); + if (host == null) + host = extras.getString("IP"); + int port = extras.getInt("PORT"); + if (port == 0) + port = 5900; + + // Parse a HOST:PORT entry + if (host.indexOf(':') > -1) { + String p = host.substring(host.indexOf(':') + 1); + try { + port = Integer.parseInt(p); + } catch (Exception e) { + } + host = host.substring(0, host.indexOf(':')); + } + + String password = extras.getString("PASSWORD"); + String repeaterID = extras.getString("ID"); + + vncCanvas = new VncCanvas(this, host, port, password, repeaterID); + setContentView(vncCanvas); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + // ignore orientation/keyboard change + super.onConfigurationChanged(newConfig); + } + + @Override + protected void onPause() { + vncCanvas.disableRepaints(); + super.onPause(); + } + + @Override + protected void onResume() { + vncCanvas.enableRepaints(); + super.onResume(); + } + + /** {@inheritDoc} */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + menu.add(Menu.NONE, MENU_ITEM_INFO, 0, "Info").setShortcut('1', 'i').setIcon(android.R.drawable.ic_menu_info_details); + menu.add(Menu.NONE, MENU_ITEM_SETTINGS, 0, "Settings").setShortcut('2', 's').setIcon(android.R.drawable.ic_menu_preferences); + menu.add(Menu.NONE, MENU_ITEM_ONE2ONE, 0, "1:1").setShortcut('3', 'r').setIcon(android.R.drawable.ic_menu_zoom); + menu.add(Menu.NONE, MENU_ITEM_FITSCREEN, 0, "Fit-to-Screen").setShortcut('4', 'c').setIcon(android.R.drawable.ic_menu_zoom); + menu.add(Menu.NONE, MENU_ITEM_DISCONNECT, 0, "Disconnect").setShortcut('5', 'd').setIcon(android.R.drawable.ic_menu_close_clear_cancel); + return super.onCreateOptionsMenu(menu); + } + + int absoluteXPosition = 0, absoluteYPosition = 0; + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_ITEM_INFO: + vncCanvas.showConnectionInfo(); + return true; + case MENU_ITEM_SETTINGS: + selectColorModel(); + return true; + case MENU_ITEM_ONE2ONE: + panningMode = true; + showPanningState(); + // Change to 1:1 scaling (which auto-centers) + vncCanvas.setScaleType(ScaleType.CENTER); + + // Reset the pan position to (0,0) + absoluteXPosition = vncCanvas.getCenteredXOffset(); + absoluteYPosition = vncCanvas.getCenteredYOffset(); + vncCanvas.scrollBy(-1 * absoluteXPosition, -1 * absoluteYPosition); + absoluteXPosition = 0; + absoluteYPosition = 0; + return true; + case MENU_ITEM_FITSCREEN: + vncCanvas.setScaleType(ScaleType.FIT_CENTER); + absoluteXPosition = 0; + absoluteYPosition = 0; + vncCanvas.scrollTo(absoluteXPosition, absoluteYPosition); + return true; + case MENU_ITEM_DISCONNECT: + vncCanvas.closeConnection(); + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (isFinishing()) + vncCanvas.onDestroy(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent evt) { + switch (keyCode) { + case KeyEvent.KEYCODE_MENU: + return super.onKeyDown(keyCode, evt); + case KeyEvent.KEYCODE_DPAD_CENTER: + return true; + } + if (panningMode) { + // DPAD KeyDown events are move MotionEvents in Panning Mode + final int dPos = 100; + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: + onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX + dPos, panTouchY, 0)); + return true; + case KeyEvent.KEYCODE_DPAD_RIGHT: + onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX - dPos, panTouchY, 0)); + return true; + case KeyEvent.KEYCODE_DPAD_UP: + onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX, panTouchY + dPos, 0)); + return true; + case KeyEvent.KEYCODE_DPAD_DOWN: + onTouchEvent(MotionEvent.obtain(1, System.currentTimeMillis(), MotionEvent.ACTION_MOVE, panTouchX, panTouchY - dPos, 0)); + return true; + } + } + if (vncCanvas.processLocalKeyEvent(keyCode, evt)) + return true; + return super.onKeyDown(keyCode, evt); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent evt) { + switch (keyCode) { + case KeyEvent.KEYCODE_MENU: + return super.onKeyUp(keyCode, evt); + case KeyEvent.KEYCODE_DPAD_CENTER: + if (isFitToScreen()) + // Do nothing in Fit-to-Screen mode + return super.onKeyUp(keyCode, evt); + panningMode = !panningMode; + showPanningState(); + return true; + } + if (panningMode) { + // Ignore KeyUp events for DPAD keys in Panning Mode + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_LEFT: + return true; + case KeyEvent.KEYCODE_DPAD_RIGHT: + return true; + case KeyEvent.KEYCODE_DPAD_UP: + return true; + case KeyEvent.KEYCODE_DPAD_DOWN: + return true; + } + } + if (vncCanvas.processLocalKeyEvent(keyCode, evt)) + return true; + return super.onKeyDown(keyCode, evt); + } + + public void showPanningState() { + String msg = "Desktop Panning Mode"; + if (!panningMode) + msg = "Mouse Pointer Control Mode"; + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + private boolean isFitToScreen() { + return vncCanvas.getScaleType() == ScaleType.FIT_CENTER; + } + + private float panTouchX, panTouchY; + + @Override + public boolean onTouchEvent(MotionEvent event) { + // Ignore touches for fit-to-screen scaling + if (isFitToScreen()) + return super.onTouchEvent(event); + + if (panningMode) { + // Panning Mode + // User may move view of desktop. + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + panTouchX = event.getX(); + panTouchY = event.getY(); + return true; + case MotionEvent.ACTION_MOVE: + pan(event); + panTouchX = event.getX(); + panTouchY = event.getY(); + return true; + case MotionEvent.ACTION_UP: + pan(event); + return true; + } + } else { + // Mouse Pointer Control Mode + // Pointer event is absolute coordinates. + + // Adjust coordinates for Android notification bar. + event.offsetLocation(0, -1f * vncCanvas.getTop()); + + // Adjust coordinates for panning position. + event.offsetLocation(absoluteXPosition, absoluteYPosition); + if (vncCanvas.processPointerEvent(event)) + return true; + } + return super.onTouchEvent(event); + } + + private void pan(MotionEvent event) { + float curX = event.getX(); + float curY = event.getY(); + int dX = (int) (panTouchX - curX); + int dY = (int) (panTouchY - curY); + + // Prevent panning left or above desktop image + if (absoluteXPosition + dX < 0) + // dX = diff to 0 + dX = absoluteXPosition * -1; + if (absoluteYPosition + dY < 0) + // dY = diff to 0 + dY = absoluteYPosition * -1; + + // Prevent panning right or below desktop image + if (absoluteXPosition + vncCanvas.getWidth() + dX > vncCanvas.getImageWidth()) + dX = 0; + if (absoluteYPosition + vncCanvas.getHeight() + dY > vncCanvas.getImageHeight()) + dY = 0; + + absoluteXPosition += dX; + absoluteYPosition += dY; + vncCanvas.scrollBy(dX, dY); + } + + @Override + public void onStop() { + vncCanvas.closeConnection(); + super.onStop(); + } + + private void selectColorModel() { + // Stop repainting the desktop + // because the display is composited! + vncCanvas.disableRepaints(); + + String[] choices = new String[COLORMODEL.values().length]; + int currentSelection = -1; + for (int i = 0; i < choices.length; i++) { + COLORMODEL cm = COLORMODEL.values()[i]; + choices[i] = cm.toString(); + if (vncCanvas.isColorModel(cm)) + currentSelection = i; + } + + final Dialog dialog = new Dialog(this); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + ListView list = new ListView(this); + list.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_checked, choices)); + list.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + list.setItemChecked(currentSelection, true); + list.setOnItemClickListener(new OnItemClickListener() { + public void onItemClick(AdapterView arg0, View arg1, int arg2, long arg3) { + dialog.dismiss(); + COLORMODEL cm = COLORMODEL.values()[arg2]; + vncCanvas.setColorModel(cm); + Toast.makeText(VncCanvasActivity.this, "Updating Color Model to " + cm.toString(), Toast.LENGTH_SHORT).show(); + } + }); + dialog.setOnDismissListener(new OnDismissListener() { + @Override + public void onDismiss(DialogInterface arg0) { + Log.i(TAG, "Color Model Selector dismissed"); + // Restore desktop repaints + vncCanvas.enableRepaints(); + } + }); + dialog.setContentView(list); + dialog.show(); + } +} hunk ./androidVNC/src/android/androidVNC/ZlibInStream.java 1 +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; +} hunk ./androidVNC/src/android/androidVNC/androidVNC.java 25 +import android.app.ActivityManager.MemoryInfo; +import android.content.Context; +import android.content.DialogInterface; hunk ./androidVNC/src/android/androidVNC/androidVNC.java 30 -import android.view.Window; hunk ./androidVNC/src/android/androidVNC/androidVNC.java 31 -import android.widget.EditText; hunk ./androidVNC/src/android/androidVNC/androidVNC.java 32 +import android.widget.EditText; hunk ./androidVNC/src/android/androidVNC/androidVNC.java 35 - hunk ./androidVNC/src/android/androidVNC/androidVNC.java 37 + private EditText passwordText; hunk ./androidVNC/src/android/androidVNC/androidVNC.java 39 - - public androidVNC() { - } - + hunk ./androidVNC/src/android/androidVNC/androidVNC.java 41 - public void onCreate(Bundle icicle) { + public void onCreate(Bundle icicle) { hunk ./androidVNC/src/android/androidVNC/androidVNC.java 43 - super.onCreate(icicle); - requestWindowFeature(Window.FEATURE_NO_TITLE); - setContentView(R.layout.main); - - ipText = (EditText) findViewById(R.id.textIP); - portText = (EditText) findViewById(R.id.textPORT); - goButton = (Button) findViewById(R.id.buttonGO); - - goButton.setOnClickListener(new View.OnClickListener(){ - public void onClick(View view){ - canvasStart(); - } - }); - - } - - private void canvasStart(){ - String ip = ipText.getText().toString(); - int port = Integer.parseInt(portText.getText().toString()); - - Intent intent = new Intent(androidVNC.this, CanvasView.class); - intent.putExtra("IP", ip); - intent.putExtra("PORT", port); - startActivity(intent); - - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - protected void onPause() { - super.onPause(); - } - + super.onCreate(icicle); + setContentView(R.layout.main); hunk ./androidVNC/src/android/androidVNC/androidVNC.java 46 + ipText = (EditText) findViewById(R.id.textIP); + portText = (EditText) findViewById(R.id.textPORT); + passwordText = (EditText) findViewById(R.id.textPASSWORD); + goButton = (Button) findViewById(R.id.buttonGO); + + goButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + canvasStart(); + } + }); + } + + private void canvasStart() { + String ip = ipText.getText().toString(); + int port = Integer.parseInt(portText.getText().toString()); + String password = passwordText.getText().toString(); + vnc(this, ip, port, password, null); + } + + + private void vnc(final Context _context, final String host, final int port, final String password, final String repeaterID) { + MemoryInfo info = Utils.getMemoryInfo(_context); + if (info.lowMemory) { + // Low Memory situation. Prompt. + Utils.showYesNoPrompt(_context, "Continue?", "Android reports low system memory.\nContinue with VNC connection?", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + vnc_(_context, host, port, password, repeaterID); + } + }, null); + } else + vnc_(_context, host, port, password, repeaterID); + } + + private void vnc_(Context _context, String host, int port, String password, String repeaterID) { + Intent intent = new Intent(_context, VncCanvasActivity.class); + intent.putExtra("HOST", host); + intent.putExtra("PORT", port); + intent.putExtra("PASSWORD", password); + intent.putExtra("ID", repeaterID); + _context.startActivity(intent); + }