diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /tools/qvfb | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'tools/qvfb')
96 files changed, 9740 insertions, 0 deletions
diff --git a/tools/qvfb/ClamshellPhone.qrc b/tools/qvfb/ClamshellPhone.qrc new file mode 100644 index 0000000..39cd422 --- /dev/null +++ b/tools/qvfb/ClamshellPhone.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>ClamshellPhone.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin new file mode 100644 index 0000000..cb24a8e --- /dev/null +++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin @@ -0,0 +1,30 @@ +[SkinFile] +Up=ClamshellPhone1-5.png +Down=ClamshellPhone1-5-pressed.png +Closed=ClamshellPhone1-5-closed.png +Screen=72 84 176 208 +Areas=22 +HasMouseHover=false + +"Power" 0x0100000a 205 563 249 586 +"1" 0x0031 62 414 119 438 +"2" 0x0032 130 414 189 438 +"3" 0x0033 198 413 257 438 +"4" 0x0034 54 444 117 470 +"5" 0x0035 128 444 189 471 +"6" 0x0036 202 444 264 471 +"7" 0x0037 47 477 113 507 +"8" 0x0038 126 477 190 507 +"9" 0x0039 205 478 270 509 +"*" 0x002a 39 515 110 552 +"0" 0x0030 122 515 195 553 +"#" 0x0023 207 516 280 553 +"Context1" 0x01100000 137 360 108 383 123 410 90 409 60 387 63 378 100 362 +"Back" 0x01000061 184 361 206 376 213 387 197 410 226 410 256 392 258 381 244 369 +"Backspace" 0x01000003 68 563 113 587 +"Select" 0x01010000 160 391 172 390 181 386 184 381 180 377 173 373 165 372 155 372 145 375 138 378 136 382 138 387 147 390 +"Left" 0x1000012 141 390 136 385 136 381 143 375 132 371 120 380 121 393 129 401 +"Down" 0x1000015 143 389 130 402 162 412 191 404 175 390 +"Right" 0x1000014 186 370 176 375 184 382 182 387 175 390 190 404 201 396 202 375 +"Up" 0x1000013 133 370 143 374 176 374 185 370 169 362 149 362 +"Flip" 0x01100006 98 325 225 353 diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png Binary files differnew file mode 100644 index 0000000..88ba3a1 --- /dev/null +++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png Binary files differnew file mode 100644 index 0000000..971cdef --- /dev/null +++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png Binary files differnew file mode 100644 index 0000000..f3550ee --- /dev/null +++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png diff --git a/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf b/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf new file mode 100644 index 0000000..e349dbc --- /dev/null +++ b/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf @@ -0,0 +1,78 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Select +Key2=Back +Key3=Flip +Key4=Backspace +[TextButtons] +Buttons=0123456789*# +Hold0='0 +Hold1='1 +Hold2='2 +Hold3='3 +Hold4='4 +Hold5='5 +Hold6='6 +Hold7='7 +Hold8='8 +Hold9='9 +Hold*=symbol +Hold#=mode +Tap0=space +Tap1="\".,'?!-@:1" +Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32" +Tap3="\"de\xe8\xe9\xea\x66\x33" +Tap4="\"ghi\xec\xed\xee\x34" +Tap5="\"jkl5" +Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36" +Tap7="\"pqrs\xdf\x37" +Tap8="\"tu\xfc\xf9\xfav8" +Tap9="\"wxyz9" +Tap*=modify +Tap#=shift +[LocaleTextButtons] +Buttons=23456789 +Tap2[]='abc +Tap3[]='def +Tap4[]='ghi +Tap5[]='jkl +Tap6[]='mno +Tap7[]='pqrs +Tap8[]='tuv +Tap9[]='wxyz +[PhoneTextButtons] +Buttons=*# +Tap*='*+pw +Hold*=+ +Tap#=# +Hold#=mode +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png b/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png Binary files differnew file mode 100644 index 0000000..d62ef4a --- /dev/null +++ b/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreen.png b/tools/qvfb/DualScreenPhone.skin/DualScreen.png Binary files differnew file mode 100644 index 0000000..cb3d1a7 --- /dev/null +++ b/tools/qvfb/DualScreenPhone.skin/DualScreen.png diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin b/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin new file mode 100644 index 0000000..a82ef23 --- /dev/null +++ b/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin @@ -0,0 +1,29 @@ +[SkinFile] +Up=DualScreen.png +Down=DualScreen-pressed.png +Screen=128 155 176 208 +BackScreen=18 44 98 119 +Areas=21 +HasMouseHover=false + +"Context1" 0x1100000 144 368 189 368 168 396 176 427 150 398 +"Back" 0x1000061 245 365 291 366 283 398 258 424 265 394 +"Select" 0x1010000 202 401 210 389 224 388 233 402 224 415 208 415 +"Up" 0x1000013 202 381 196 374 218 363 239 373 229 382 +"Left" 0x1000012 199 385 189 375 176 403 185 426 197 415 194 401 +"Right" 0x1000014 235 390 248 379 253 402 246 421 238 413 +"Down" 0x1000015 204 421 233 422 241 432 214 443 191 430 +"Call" 0x1100004 163 452 137 450 125 465 136 484 159 485 169 467 +"Hangup" 0x1100005 266 475 279 448 295 447 309 460 301 480 289 487 +"1" 0x31 175 514 147 504 133 518 161 532 180 534 +"2" 0x32 199 515 229 519 238 533 222 540 195 538 +"2" 0x32 260 512 286 506 299 513 284 527 264 535 248 525 +"4" 0x34 164 541 177 546 182 560 164 565 146 560 135 545 154 539 +"5" 0x35 204 546 225 546 243 560 231 574 205 573 191 558 +"6" 0x36 257 547 281 537 294 540 287 555 274 566 254 561 +"7" 0x37 145 569 176 578 177 595 156 597 138 584 +"8" 0x38 197 582 229 584 241 593 226 604 201 603 189 594 +"9" 0x39 253 577 288 564 301 578 283 593 259 597 251 586 +"*" 0x2a 145 598 181 611 182 623 163 632 144 623 138 607 +"0" 0x30 196 611 233 613 240 630 220 642 193 637 191 622 +"#" 0x23 255 610 286 600 302 615 279 625 258 629 247 616 diff --git a/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf b/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf new file mode 100644 index 0000000..1103350 --- /dev/null +++ b/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf @@ -0,0 +1,78 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Select +Key2=Back +Key3=Call +Key4=Hangup +[TextButtons] +Buttons=0123456789*# +Hold0='0 +Hold1='1 +Hold2='2 +Hold3='3 +Hold4='4 +Hold5='5 +Hold6='6 +Hold7='7 +Hold8='8 +Hold9='9 +Hold*=symbol +Hold#=mode +Tap0=space +Tap1="\".,'?!-@:1" +Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32" +Tap3="\"de\xe8\xe9\xea\x66\x33" +Tap4="\"ghi\xec\xed\xee\x34" +Tap5="\"jkl5" +Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36" +Tap7="\"pqrs\xdf\x37" +Tap8="\"tu\xfc\xf9\xfav8" +Tap9="\"wxyz9" +Tap*=modify +Tap#=shift +[LocaleTextButtons] +Buttons=23456789 +Tap2[]='abc +Tap3[]='def +Tap4[]='ghi +Tap5[]='jkl +Tap6[]='mno +Tap7[]='pqrs +Tap8[]='tuv +Tap9[]='wxyz +[PhoneTextButtons] +Buttons=*# +Tap*='*+pw +Hold*=+ +Tap#='# +Hold#=mode +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/LICENSE.GPL b/tools/qvfb/LICENSE.GPL new file mode 100644 index 0000000..b6e1c33 --- /dev/null +++ b/tools/qvfb/LICENSE.GPL @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/tools/qvfb/PDAPhone.qrc b/tools/qvfb/PDAPhone.qrc new file mode 100644 index 0000000..1a1c35a --- /dev/null +++ b/tools/qvfb/PDAPhone.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>PDAPhone.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/PDAPhone.skin/PDAPhone.skin b/tools/qvfb/PDAPhone.skin/PDAPhone.skin new file mode 100644 index 0000000..d6a1966 --- /dev/null +++ b/tools/qvfb/PDAPhone.skin/PDAPhone.skin @@ -0,0 +1,18 @@ +[SkinFile] +Up=pda_up.png +Down=pda_down.png +Screen=42 59 176 220 +Cursor=finger.png 20 20 +Areas=10 +HasMouseHover=false + +"Power" 0x0100000a 117 21 141 42 +"Context1" 0x01100000 43 284 74 315 +"Call" 0x01100004 74 284 104 315 +"Hangup" 0x01100005 154 284 184 315 +"Back" 0x01000061 184 284 214 315 +"Left" 0x1000012 123 315 110 326 106 307 113 288 123 300 120 307 +"Down" 0x1000015 123 315 130 318 138 315 150 326 129 335 111 325 +"Right" 0x1000014 137 301 149 290 155 308 150 324 138 315 140 308 +"Up" 0x1000013 123 300 112 289 130 282 149 290 137 300 130 298 +"Select" 0x01010000 131 298 137 300 140 307 138 315 130 318 123 316 120 307 123 300 diff --git a/tools/qvfb/PDAPhone.skin/defaultbuttons.conf b/tools/qvfb/PDAPhone.skin/defaultbuttons.conf new file mode 100644 index 0000000..e3ae813 --- /dev/null +++ b/tools/qvfb/PDAPhone.skin/defaultbuttons.conf @@ -0,0 +1,36 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Back +Key2=Select +Key3=Call +Key4=Hangup +[Device] +PrimaryInput=Touchscreen diff --git a/tools/qvfb/PDAPhone.skin/finger.png b/tools/qvfb/PDAPhone.skin/finger.png Binary files differnew file mode 100644 index 0000000..24cf0cb --- /dev/null +++ b/tools/qvfb/PDAPhone.skin/finger.png diff --git a/tools/qvfb/PDAPhone.skin/pda_down.png b/tools/qvfb/PDAPhone.skin/pda_down.png Binary files differnew file mode 100644 index 0000000..f65c059 --- /dev/null +++ b/tools/qvfb/PDAPhone.skin/pda_down.png diff --git a/tools/qvfb/PDAPhone.skin/pda_up.png b/tools/qvfb/PDAPhone.skin/pda_up.png Binary files differnew file mode 100644 index 0000000..541e3c4 --- /dev/null +++ b/tools/qvfb/PDAPhone.skin/pda_up.png diff --git a/tools/qvfb/PortableMedia.qrc b/tools/qvfb/PortableMedia.qrc new file mode 100644 index 0000000..a902f1a --- /dev/null +++ b/tools/qvfb/PortableMedia.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>PortableMedia.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/PortableMedia.skin/PortableMedia.skin b/tools/qvfb/PortableMedia.skin/PortableMedia.skin new file mode 100644 index 0000000..b76e5cf --- /dev/null +++ b/tools/qvfb/PortableMedia.skin/PortableMedia.skin @@ -0,0 +1,14 @@ +[SkinFile] +Up=portablemedia.png +Down=portablemedia-pressed.png +Screen=18 20 480 272 +Areas=7 +HasMouseHover=false + +"Context1" 0x01100000 530 192 565 223 +"Back" 0x01000061 530 138 565 173 +"Select" 0x01010000 530 65 565 98 +"Left" 0x1000012 529 67 519 57 511 65 511 104 519 110 529 100 529 98 +"Down" 0x1000015 530 102 520 111 529 120 569 120 577 114 566 103 564 103 +"Right" 0x1000014 565 65 576 52 585 67 585 102 578 113 567 104 +"Up" 0x1000013 530 65 519 55 528 48 567 48 573 51 564 66 diff --git a/tools/qvfb/PortableMedia.skin/defaultbuttons.conf b/tools/qvfb/PortableMedia.skin/defaultbuttons.conf new file mode 100644 index 0000000..514e881 --- /dev/null +++ b/tools/qvfb/PortableMedia.skin/defaultbuttons.conf @@ -0,0 +1,23 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Map=123 +Default=1 +1=Applications/mediaplayer.desktop +2=Applications/photoedit.desktop +3=Settings +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Select +Key2=Back +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png b/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png Binary files differnew file mode 100644 index 0000000..730e762 --- /dev/null +++ b/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png diff --git a/tools/qvfb/PortableMedia.skin/portablemedia.png b/tools/qvfb/PortableMedia.skin/portablemedia.png Binary files differnew file mode 100644 index 0000000..e44cbe1 --- /dev/null +++ b/tools/qvfb/PortableMedia.skin/portablemedia.png diff --git a/tools/qvfb/PortableMedia.skin/portablemedia.xcf b/tools/qvfb/PortableMedia.skin/portablemedia.xcf Binary files differnew file mode 100644 index 0000000..127e07c --- /dev/null +++ b/tools/qvfb/PortableMedia.skin/portablemedia.xcf diff --git a/tools/qvfb/README b/tools/qvfb/README new file mode 100644 index 0000000..bfab467 --- /dev/null +++ b/tools/qvfb/README @@ -0,0 +1,51 @@ +Qt for Embedded Linux Virtual Framebuffer +=============================== + +The virtual frame buffer allows a Qt for Embedded Linux program to be developed +on your desktop machine, without switching between consoles and X11. The virtual +framebuffer consists of a shared memory region (the virtual frame buffer) +and a utility to display the framebuffer in a window. The display is updated +periodically, so you will see discrete snapshots of the framebuffer rather +than each individual drawing operation. For this reason drawing problems +such as flickering may not be apparent until the program is run using a real +framebuffer. + +To use the virtual framebuffer: + +1. Ensure QT_NO_QWS_VFB is not set in qconfig.h (when you configure Qt, + add the -qvfb option). +2. Start qvfb (qvfb should be compiled as a normal Qt for X11 application, + NOT as a Qt for Embedded Linux application!). +3. Start a Qt for Embedded Linux server (i.e. construct QApplication with + QApplication::GuiServer flag, or run a client with the -qws option). + +qvfb supports the following command line options: + +[-width width] the width of the virtual framebuffer (default: 240). +[-height height] the height of the virtual framebuffer (default: 320). +[-depth depth] the depth of the virtual framebuffer (1,4,8 or 32, default: 8). +[-nocursor] do not display the X11 cursor in the framebuffer window. +[-qwsdisplay] the Qt for Embedded Linux display ID, e.g. -qwsdisplay :1 (default :0). +[-skin skinfile] tells qvfb to load a skin file, e.g. -skin pda.skin + +Please refer to the file "pda.skin" as an example of what a skin file looks like. +The format for skin files is: + Image filename of skin with buttons in their up positions + Image filename of skin with buttons in their down positions + X offset of top left corner of the virtual screen on the skin image + Y offset of top left corner of the virtual screen on the skin image + Width of the virtual screen on the skin image + Height of the virtual screen on the skin image + Number of defined button regions +Then for each button region the format is: + Button identifier + Qt scan codes to generate for the button + Top left X coordinate of the button region + Top left Y coordinate of the button region + Bottom right X coordinate of the button region + Bottom right Y coordinate of the button region + +The virtual framebuffer is a development tool only. No security issues have +been considered in the virtual framebuffer design. It should not be used +in a production environment and QT_NO_QWS_VFB should always be in force +in production libraries. diff --git a/tools/qvfb/S60-QVGA-Candybar.qrc b/tools/qvfb/S60-QVGA-Candybar.qrc new file mode 100644 index 0000000..8138484 --- /dev/null +++ b/tools/qvfb/S60-QVGA-Candybar.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>S60-QVGA-Candybar.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png b/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png Binary files differnew file mode 100644 index 0000000..89d40cb --- /dev/null +++ b/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar-down.png diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png b/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png Binary files differnew file mode 100644 index 0000000..0d0e598 --- /dev/null +++ b/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.png diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin b/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin new file mode 100644 index 0000000..4f8fe5d --- /dev/null +++ b/tools/qvfb/S60-QVGA-Candybar.skin/S60-QVGA-Candybar.skin @@ -0,0 +1,15 @@ +[SkinFile] +Up=S60-QVGA-Candybar.png +Down=S60-QVGA-Candybar-down.png +Screen=61 93 240 320 +Areas=7 +HasMouseHover=false + + +"Context1" 0x01100000 54 469 151 469 140 483 88 485 81 496 54 498 +"Back" 0x01000061 211 468 307 467 307 498 278 497 219 486 +"Select" 0x01010000 165 491 196 522 +"Left" 0x1000012 149 474 166 492 163 519 143 538 142 481 +"Down" 0x1000015 164 521 195 522 212 539 204 545 154 544 145 536 +"Right" 0x1000014 214 475 219 487 219 528 212 539 196 522 197 492 +"Up" 0x1000013 150 474 156 467 209 467 213 476 197 489 165 489 diff --git a/tools/qvfb/S60-QVGA-Candybar.skin/defaultbuttons.conf b/tools/qvfb/S60-QVGA-Candybar.skin/defaultbuttons.conf new file mode 100644 index 0000000..e349dbc --- /dev/null +++ b/tools/qvfb/S60-QVGA-Candybar.skin/defaultbuttons.conf @@ -0,0 +1,78 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Select +Key2=Back +Key3=Flip +Key4=Backspace +[TextButtons] +Buttons=0123456789*# +Hold0='0 +Hold1='1 +Hold2='2 +Hold3='3 +Hold4='4 +Hold5='5 +Hold6='6 +Hold7='7 +Hold8='8 +Hold9='9 +Hold*=symbol +Hold#=mode +Tap0=space +Tap1="\".,'?!-@:1" +Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32" +Tap3="\"de\xe8\xe9\xea\x66\x33" +Tap4="\"ghi\xec\xed\xee\x34" +Tap5="\"jkl5" +Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36" +Tap7="\"pqrs\xdf\x37" +Tap8="\"tu\xfc\xf9\xfav8" +Tap9="\"wxyz9" +Tap*=modify +Tap#=shift +[LocaleTextButtons] +Buttons=23456789 +Tap2[]='abc +Tap3[]='def +Tap4[]='ghi +Tap5[]='jkl +Tap6[]='mno +Tap7[]='pqrs +Tap8[]='tuv +Tap9[]='wxyz +[PhoneTextButtons] +Buttons=*# +Tap*='*+pw +Hold*=+ +Tap#=# +Hold#=mode +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/S60-nHD-Touchscreen.qrc b/tools/qvfb/S60-nHD-Touchscreen.qrc new file mode 100644 index 0000000..daf0cc3 --- /dev/null +++ b/tools/qvfb/S60-nHD-Touchscreen.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>S60-nHD-Touchscreen.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png b/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png Binary files differnew file mode 100644 index 0000000..7253e38 --- /dev/null +++ b/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen-down.png diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png b/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png Binary files differnew file mode 100644 index 0000000..675563e --- /dev/null +++ b/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.png diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin b/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin new file mode 100644 index 0000000..ed25d0e --- /dev/null +++ b/tools/qvfb/S60-nHD-Touchscreen.skin/S60-nHD-Touchscreen.skin @@ -0,0 +1,10 @@ +[SkinFile] +Up=S60-nHD-Touchscreen.png +Down=S60-nHD-Touchscreen-down.png +Screen=53 183 360 640 +Areas=3 +HasMouseHover=false + +"Call" 0x01100004 76 874 171 899 +"Hangup" 0x01100005 300 876 393 899 +"Home" 0x1000010 174 878 298 899 diff --git a/tools/qvfb/S60-nHD-Touchscreen.skin/defaultbuttons.conf b/tools/qvfb/S60-nHD-Touchscreen.skin/defaultbuttons.conf new file mode 100644 index 0000000..6665125 --- /dev/null +++ b/tools/qvfb/S60-nHD-Touchscreen.skin/defaultbuttons.conf @@ -0,0 +1,53 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/mediaplayer.desktop +3=Applications/simapp.desktop,Applications/calculator.desktop +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Applications/datebook.desktop +7=Games +8=Settings/beaming.desktop +9=Applications/todolist.desktop +*=Settings +0=Applications +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Back +Key2=Select +Key3=Call +Key4=Hangup +[Device] +PrimaryInput=Touchscreen +[Button] +Count=2 +[Button0] +Name[]=Home Button +Key=Home +PressedActionMappable=0 +PressedActionService=TaskManager +PressedActionMessage=multitask() +HeldActionMappable=0 +HeldActionService=TaskManager +HeldActionMessage=showRunningTasks() +[Button1] +Name=Power Button +Key=Hangup +HeldActionService=Launcher +HeldActionMessage=execute(QString) +HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n) diff --git a/tools/qvfb/SmartPhone.qrc b/tools/qvfb/SmartPhone.qrc new file mode 100644 index 0000000..8bb5325 --- /dev/null +++ b/tools/qvfb/SmartPhone.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>SmartPhone.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png b/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png Binary files differnew file mode 100644 index 0000000..d0db2ed --- /dev/null +++ b/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone.png b/tools/qvfb/SmartPhone.skin/SmartPhone.png Binary files differnew file mode 100644 index 0000000..e6ac5a0 --- /dev/null +++ b/tools/qvfb/SmartPhone.skin/SmartPhone.png diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone.skin b/tools/qvfb/SmartPhone.skin/SmartPhone.skin new file mode 100644 index 0000000..2f44c5a --- /dev/null +++ b/tools/qvfb/SmartPhone.skin/SmartPhone.skin @@ -0,0 +1,28 @@ +[SkinFile] +Up=SmartPhone.png +Down=SmartPhone-pressed.png +Screen=90 107 176 208 +Areas=21 +HasMouseHover=false + +"1" 0x0031 138 459 149 473 142 483 120 484 102 477 95 464 99 457 121 454 +"2" 0x0032 153 467 202 492 +"3" 0x0033 258 457 260 470 243 483 215 484 207 474 218 460 248 453 +"4" 0x0034 138 492 149 506 142 516 120 517 102 510 95 497 99 490 121 487 +"5" 0x0035 153 499 202 524 +"6" 0x0036 258 489 260 502 243 515 215 516 207 506 218 492 248 485 +"7" 0x0037 138 524 149 538 142 548 120 549 102 542 95 529 99 522 121 519 +"8" 0x0038 153 531 202 556 +"9" 0x0039 258 521 260 534 243 547 215 548 207 538 218 524 248 517 +"*" 0x002a 138 556 149 570 142 580 120 581 102 574 95 561 99 554 121 551 +"0" 0x0030 153 564 202 589 +"#" 0x0023 258 554 260 567 243 580 215 581 207 571 218 557 248 550 +"Call" 0x01100004 88 395 130 439 +"Hangup" 0x01100005 227 395 269 439 +"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318 +"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318 +"Select" 0x01010000 160 338 195 371 +"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369 +"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374 +"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375 +"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337 diff --git a/tools/qvfb/SmartPhone.skin/defaultbuttons.conf b/tools/qvfb/SmartPhone.skin/defaultbuttons.conf new file mode 100644 index 0000000..1103350 --- /dev/null +++ b/tools/qvfb/SmartPhone.skin/defaultbuttons.conf @@ -0,0 +1,78 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Select +Key2=Back +Key3=Call +Key4=Hangup +[TextButtons] +Buttons=0123456789*# +Hold0='0 +Hold1='1 +Hold2='2 +Hold3='3 +Hold4='4 +Hold5='5 +Hold6='6 +Hold7='7 +Hold8='8 +Hold9='9 +Hold*=symbol +Hold#=mode +Tap0=space +Tap1="\".,'?!-@:1" +Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32" +Tap3="\"de\xe8\xe9\xea\x66\x33" +Tap4="\"ghi\xec\xed\xee\x34" +Tap5="\"jkl5" +Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36" +Tap7="\"pqrs\xdf\x37" +Tap8="\"tu\xfc\xf9\xfav8" +Tap9="\"wxyz9" +Tap*=modify +Tap#=shift +[LocaleTextButtons] +Buttons=23456789 +Tap2[]='abc +Tap3[]='def +Tap4[]='ghi +Tap5[]='jkl +Tap6[]='mno +Tap7[]='pqrs +Tap8[]='tuv +Tap9[]='wxyz +[PhoneTextButtons] +Buttons=*# +Tap*='*+pw +Hold*=+ +Tap#='# +Hold#=mode +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/SmartPhone2.qrc b/tools/qvfb/SmartPhone2.qrc new file mode 100644 index 0000000..751e985 --- /dev/null +++ b/tools/qvfb/SmartPhone2.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>SmartPhone2.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png b/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png Binary files differnew file mode 100644 index 0000000..d4eb5b0 --- /dev/null +++ b/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2.png b/tools/qvfb/SmartPhone2.skin/SmartPhone2.png Binary files differnew file mode 100644 index 0000000..48ccc1c --- /dev/null +++ b/tools/qvfb/SmartPhone2.skin/SmartPhone2.png diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin b/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin new file mode 100644 index 0000000..16884bf --- /dev/null +++ b/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin @@ -0,0 +1,25 @@ +SmartPhone2.png SmartPhone2-pressed.png +90 107 +176 220 +21 +"Menu" 0x01100000 70 400 115 427 +"Backspace" 0x01000003 238 400 285 427 +"1" 0x0031 138 437 149 451 142 461 120 462 102 455 95 442 99 435 121 432 +"2" 0x0032 153 445 202 470 +"3" 0x0033 258 435 260 448 243 461 215 462 207 452 218 438 248 431 +"4" 0x0034 138 470 149 484 142 494 120 495 102 488 95 475 99 468 121 465 +"5" 0x0035 153 477 202 502 +"6" 0x0036 258 467 260 480 243 493 215 494 207 484 218 470 248 463 +"7" 0x0037 138 502 149 516 142 526 120 527 102 520 95 507 99 500 121 497 +"8" 0x0038 153 509 202 534 +"9" 0x0039 258 499 260 512 243 525 215 526 207 516 218 502 248 495 +"*" 0x002a 138 534 149 548 142 558 120 559 102 552 95 539 99 532 121 529 +"0" 0x0030 153 542 202 567 +"#" 0x0023 258 532 260 545 243 558 215 559 207 549 218 535 248 528 +"Yes" 0x01010001 91 343 141 393 +"No" 0x01010002 219 343 269 393 +"Select" 0x01010000 160 356 195 389 +"Left" 0x1000012 159 356 149 346 141 354 141 391 149 399 159 389 159 387 +"Down" 0x1000015 160 391 150 400 159 409 199 409 207 403 196 392 194 392 +"Right" 0x1000014 195 354 206 341 215 356 215 391 208 402 197 393 +"Up" 0x1000013 160 354 149 344 158 337 197 337 203 340 194 355 diff --git a/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf b/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf new file mode 100644 index 0000000..b083203 --- /dev/null +++ b/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf @@ -0,0 +1,52 @@ +[Button] +[IMethod] +key_count = 5 +key_hold_action_1 = insertText +key_hold_action_2 = insertText +key_hold_action_3 = insertSymbol +key_hold_action_4 = changeMode +key_hold_arg_1 = 1 +key_hold_arg_2 = 0 +key_id_1 = 1 +key_id_2 = 0 +key_id_3 = * +key_id_4 = # +key_id_5 = * +key_mode_1 = Abc +key_mode_2 = Abc +key_mode_3 = Abc +key_mode_4 = Abc +key_mode_5 = Phone +key_tap_action_1 = insertText +key_tap_action_2 = insertSpace +key_tap_action_3 = modifyText +key_tap_action_4 = changeShift +key_tap_action_5 = insertText +key_tap_arg_1 = .,'?!-@:〓 +key_tap_arg_5 = *+pw +[Menu] +1 = Applications/camera.desktop +2 = Applications/datebook.desktop +3 = Games +4 = Applications/qtmail.desktop +5 = Applications/addressbook.desktop +6 = Settings +7 = Settings/Beaming.desktop +8 = Applications +9 = Documents +Columns = 3 +Default = 5 +Map = 123456789 +Rows = 3 +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +[SystemButtons] +Count=5 +Key0=Yes +Key1=Select +Key2=No +Key3=Menu +Key4=Backspace +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/SmartPhoneWithButtons.qrc b/tools/qvfb/SmartPhoneWithButtons.qrc new file mode 100644 index 0000000..f3393ba --- /dev/null +++ b/tools/qvfb/SmartPhoneWithButtons.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>SmartPhoneWithButtons.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png Binary files differnew file mode 100644 index 0000000..456a068 --- /dev/null +++ b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png Binary files differnew file mode 100644 index 0000000..5ffbd6e --- /dev/null +++ b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin new file mode 100644 index 0000000..9afa67f --- /dev/null +++ b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin @@ -0,0 +1,31 @@ +[SkinFile] +Up=SmartPhoneWithButtons.png +Down=SmartPhoneWithButtons-pressed.png +Screen=90 107 176 208 +Areas=24 +HasMouseHover=false + +"1" 0x0031 138 459 149 473 142 483 120 484 102 477 95 464 99 457 121 454 +"2" 0x0032 153 467 202 492 +"3" 0x0033 258 457 260 470 243 483 215 484 207 474 218 460 248 453 +"4" 0x0034 138 492 149 506 142 516 120 517 102 510 95 497 99 490 121 487 +"5" 0x0035 153 499 202 524 +"6" 0x0036 258 489 260 502 243 515 215 516 207 506 218 492 248 485 +"7" 0x0037 138 524 149 538 142 548 120 549 102 542 95 529 99 522 121 519 +"8" 0x0038 153 531 202 556 +"9" 0x0039 258 521 260 534 243 547 215 548 207 538 218 524 248 517 +"*" 0x002a 138 556 149 570 142 580 120 581 102 574 95 561 99 554 121 551 +"0" 0x0030 153 564 202 589 +"#" 0x0023 258 554 260 567 243 580 215 581 207 571 218 557 248 550 +"Call" 0x01100004 88 395 130 439 +"Hangup" 0x01100005 227 395 269 439 +"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318 +"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318 +"Select" 0x01010000 160 338 195 371 +"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369 +"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374 +"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375 +"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337 +"Home" 0x1000010 164 402 195 434 +"F1" 0x1000030 138 422 163 448 +"F2" 0x1000031 196 422 220 448 diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf b/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf new file mode 100644 index 0000000..ebd6926 --- /dev/null +++ b/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf @@ -0,0 +1,103 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Button] +Count=3 +[Button0] +Name[]=Calendar Button +Key=F1 +PressedActionService=Calendar +PressedActionMessage=raiseToday() +HeldActionService=Calendar +HeldActionMessage=newEvent() +[Button1] +Name[]=Tasks Button +Key=F2 +PressedActionService=Tasks +PressedActionMessage=raise() +HeldActionService=Tasks +HeldActionMessage=newTask() +[Button2] +Name[]=Home Button +Key=Home +PressedActionMappable=0 +PressedActionService=TaskManager +PressedActionMessage=multitask() +HeldActionMappable=0 +HeldActionService=TaskManager +HeldActionMessage=showRunningTasks() +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Select +Key2=Back +Key3=Call +Key4=Hangup +[TextButtons] +Buttons=0123456789*# +Hold0='0 +Hold1='1 +Hold2='2 +Hold3='3 +Hold4='4 +Hold5='5 +Hold6='6 +Hold7='7 +Hold8='8 +Hold9='9 +Hold*=symbol +Hold#=mode +Tap0=space +Tap1="\".,'?!-@:1" +Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32" +Tap3="\"de\xe8\xe9\xea\x66\x33" +Tap4="\"ghi\xec\xed\xee\x34" +Tap5="\"jkl5" +Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36" +Tap7="\"pqrs\xdf\x37" +Tap8="\"tu\xfc\xf9\xfav8" +Tap9="\"wxyz9" +Tap*=modify +Tap#=shift +[LocaleTextButtons] +Buttons=23456789 +Tap2[]='abc +Tap3[]='def +Tap4[]='ghi +Tap5[]='jkl +Tap6[]='mno +Tap7[]='pqrs +Tap8[]='tuv +Tap9[]='wxyz +[PhoneTextButtons] +Buttons=*# +Tap*='*+pw +Hold*=+ +Tap#='# +Hold#=mode +[Device] +PrimaryInput=Keypad diff --git a/tools/qvfb/TouchscreenPhone.qrc b/tools/qvfb/TouchscreenPhone.qrc new file mode 100644 index 0000000..023144d --- /dev/null +++ b/tools/qvfb/TouchscreenPhone.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>TouchscreenPhone.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png Binary files differnew file mode 100644 index 0000000..01acb86 --- /dev/null +++ b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png Binary files differnew file mode 100644 index 0000000..e90de0d --- /dev/null +++ b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin new file mode 100644 index 0000000..24316a1 --- /dev/null +++ b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin @@ -0,0 +1,16 @@ +[SkinFile] +Up=TouchscreenPhone.png +Down=TouchscreenPhone-pressed.png +Screen=90 107 176 208 +Areas=9 +HasMouseHover=false + +"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318 +"Call" 0x01100004 88 395 130 439 +"Hangup" 0x01100005 227 395 269 439 +"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318 +"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369 +"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374 +"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375 +"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337 +"Select" 0x01010000 160 338 195 371 diff --git a/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf b/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf new file mode 100644 index 0000000..a13dfdc --- /dev/null +++ b/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf @@ -0,0 +1,45 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/datebook.desktop +3=Applications +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Games +7=Settings/Beaming.desktop +8=Applications/simapp.desktop,Applications/calculator.desktop +9=Settings +*=Applications/mediarecorder.desktop +0=Applications/todolist.desktop +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Back +Key2=Select +Key3=Call +Key4=Hangup +[Button] +Count=1 +[Button0] +Name=Power Button +Key=Hangup +HeldActionService=Launcher +HeldActionMessage=execute(QString) +HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n) +[Device] +PrimaryInput=Touchscreen + diff --git a/tools/qvfb/Trolltech-Keypad.qrc b/tools/qvfb/Trolltech-Keypad.qrc new file mode 100644 index 0000000..4775068 --- /dev/null +++ b/tools/qvfb/Trolltech-Keypad.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>Trolltech-Keypad.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png Binary files differnew file mode 100644 index 0000000..8dd5719 --- /dev/null +++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png Binary files differnew file mode 100644 index 0000000..5e1e6be --- /dev/null +++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png Binary files differnew file mode 100644 index 0000000..fb3d549 --- /dev/null +++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin new file mode 100644 index 0000000..4d90321 --- /dev/null +++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin @@ -0,0 +1,35 @@ +[SkinFile] +Up=Trolltech-Keypad.png +Down=Trolltech-Keypad-down.png +Closed=Trolltech-Keypad-closed.png +ClosedAreas=F1 F2 F3 Flip +ClosedScreen=95 456 128 96 +Screen=75 85 176 220 +Areas=25 +HasMouseHover=false +"1" 0x0031 65 542 68 536 76 532 114 536 114 573 64 568 +"2" 0x0032 133 537 188 574 +"3" 0x0033 206 536 246 532 252 536 256 542 258 569 205 572 +"4" 0x0034 64 578 114 618 +"5" 0x0035 133 581 188 618 +"6" 0x0036 206 580 256 577 258 613 206 616 +"7" 0x0037 66 622 116 625 114 662 66 658 +"8" 0x0038 133 626 188 662 +"9" 0x0039 206 625 256 622 256 658 206 661 +"*" 0x002a 68 667 116 670 114 705 86 699 76 693 69 686 +"0" 0x0030 133 671 188 708 +"#" 0x0023 206 670 254 665 254 684 245 692 232 699 206 704 +"Context1" 0x01100000 69 420 75 410 85 404 101 404 102 458 69 458 +"Back" 0x01000061 218 404 234 404 240 408 248 418 248 456 218 457 +"Home" 0x1000010 140 494 180 514 +"Hangup" 0x01100005 218 457 248 456 248 496 243 507 230 514 194 514 194 494 206 492 213 486 218 478 +"Call" 0x01100004 68 458 102 460 102 479 108 487 118 492 126 494 126 514 86 514 77 507 72 496 +"Select" 0x01010000 138 426 182 458 +"Up" 0x1000013 118 406 201 402 184 423 134 422 +"Right" 0x1000014 184 424 201 402 202 476 184 460 +"Down" 0x1000015 135 462 184 461 199 477 118 477 +"Left" 0x1000012 118 406 134 424 134 461 117 476 +"F1" 0x1000030 0 408 45 456 +"F2" 0x1000031 0 456 45 509 +"F3" 0x1000032 0 545 45 582 +"Flip" 0x1100006 32 353 293 386 diff --git a/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf b/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf new file mode 100644 index 0000000..6a78e67 --- /dev/null +++ b/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf @@ -0,0 +1,142 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Button] +Count=8 +[Button7] +Name[]=Home Down Button +Key=Down +Context=HomeScreen +PressedActionMappable=0 +HeldActionService=Messaging +HeldActionMessage=raise() +[Button6] +Name[]=Home Up Button +Key=Up +Context=HomeScreen +PressedActionMappable=0 +HeldActionService=Contacts +HeldActionMessage=raise() +[Button5] +Name[]=Home Right Button +Key=Right +Context=HomeScreen +PressedActionMappable=0 +HeldActionService=mediaplayer +HeldActionMessage=raise() +[Button4] +Name[]=Calender Button +Key=Left +Context=HomeScreen +PressedActionMappable=0 +HeldActionService=Calendar +HeldActionMessage=raiseToday() +[Button3] +Name[]=Left Soft Key +Key=Context1 +HeldActionService=TaskManager +HeldActionMessage=showRunningTasks() +HeldActionMappable=0 +PressActionMappable=0 +[Button2] +Name[]=VoiceNotes Button +Key=F1 +PressedActionService=mediarecorder +PressedActionMessage=raise() +HeldActionService=mediarecorder +HeldActionMessage=newEvent() +[Button1] +Name[]=Camera Button +Key=F2 +PressedActionService=Camera +PressedActionMessage=raise() +HeldActionService=Tasks +HeldActionMessage=newTask() +[Button0] +Name[]=Home Button +Key=Home +PressedActionMappable=0 +PressedActionService=TaskManager +PressedActionMessage=multitask() +HeldActionMappable=0 +HeldActionService=TaskManager +HeldActionMessage=showRunningTasks() +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/mediaplayer.desktop +3=Applications/simapp.desktop,Applications/calculator.desktop +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Applications/datebook.desktop +7=Games +8=Settings/Beaming.desktop +9=Applications/todolist.desktop +*=Settings +0=Applications +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=6 +Key0=Context1 +Key1=Select +Key2=Back +Key3=Call +Key4=Hangup +Key5=Flip +[TextButtons] +Buttons=0123456789*# +Hold0='0 +Hold1='1 +Hold2='2 +Hold3='3 +Hold4='4 +Hold5='5 +Hold6='6 +Hold7='7 +Hold8='8 +Hold9='9 +Hold*=symbol +Hold#=mode +Tap0=space +Tap0=space +Tap1="\".,'?!-@:1" +Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32" +Tap3="\"de\xe8\xe9\xea\x66\x33" +Tap4="\"ghi\xec\xed\xee\x34" +Tap5="\"jkl5" +Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36" +Tap7="\"pqrs\xdf\x37" +Tap8="\"tu\xfc\xf9\xfav8" +Tap9="\"wxyz9" +Tap*=modify +Tap#=shift +[LocaleTextButtons] +Buttons=23456789 +Tap2[]='abc +Tap3[]='def +Tap4[]='ghi +Tap5[]='jkl +Tap6[]='mno +Tap7[]='pqrs +Tap8[]='tuv +Tap9[]='wxyz +[PhoneTextButtons] +Buttons=*# +Tap*='*+pw +Hold*=+ +Tap#='# +Hold#=mode +[Device] +PrimaryInput=Keypad +[Environment] +QWS_DISPLAY=Multi: LinuxFb:mmHeight57:0 LinuxFb:offset=0,320:1 :0 diff --git a/tools/qvfb/Trolltech-Touchscreen.qrc b/tools/qvfb/Trolltech-Touchscreen.qrc new file mode 100644 index 0000000..40fafeb --- /dev/null +++ b/tools/qvfb/Trolltech-Touchscreen.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>Trolltech-Touchscreen.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png Binary files differnew file mode 100644 index 0000000..c1a422f --- /dev/null +++ b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png Binary files differnew file mode 100644 index 0000000..544a425 --- /dev/null +++ b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin new file mode 100644 index 0000000..5de882e --- /dev/null +++ b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin @@ -0,0 +1,17 @@ +[SkinFile] +Up=Trolltech-Touchscreen.png +Down=Trolltech-Touchscreen-down.png +Screen=40 109 176 220 +Areas=10 +HasMouseHover=false + +"Context1" 0x01100000 38 420 44 408 52 404 68 403 68 458 40 458 +"Back" 0x01000061 185 42 202 398 211 410 216 418 219 456 186 456 +"Call" 0x01100004 38 458 70 458 71 478 75 486 83 492 94 494 94 516 56 516 45 507 38 498 +"Hangup" 0x01100005 186 458 220 458 220 496 214 508 200 516 162 516 161 494 172 492 180 486 185 478 +"Left" 0x1000012 86 405 106 426 106 461 85 478 +"Down" 0x1000015 106 460 151 460 170 480 85 480 +"Right" 0x1000014 151 424 170 404 170 480 151 460 +"Up" 0x1000013 85 403 168 403 150 424 106 424 +"Select" 0x01010000 106 426 150 456 +"Home" 0x1000010 105 493 145 512 diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf b/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf new file mode 100644 index 0000000..6665125 --- /dev/null +++ b/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf @@ -0,0 +1,53 @@ +[Translation] +File=QtopiaDefaults +Context=Buttons +[Menu] +Rows=4 +Columns=3 +Map=123456789*0# +Default=5 +1=Applications/camera.desktop +2=Applications/mediaplayer.desktop +3=Applications/simapp.desktop,Applications/calculator.desktop +4=Applications/qtmail.desktop +5=Applications/addressbook.desktop +6=Applications/datebook.desktop +7=Games +8=Settings/beaming.desktop +9=Applications/todolist.desktop +*=Settings +0=Applications +#=Documents +Animator=Bounce +AnimatorBackground=Radial +[SoftKeys] +Count=3 +Key0=Context1 +Key1=Select +Key2=Back +[SystemButtons] +Count=5 +Key0=Context1 +Key1=Back +Key2=Select +Key3=Call +Key4=Hangup +[Device] +PrimaryInput=Touchscreen +[Button] +Count=2 +[Button0] +Name[]=Home Button +Key=Home +PressedActionMappable=0 +PressedActionService=TaskManager +PressedActionMessage=multitask() +HeldActionMappable=0 +HeldActionService=TaskManager +HeldActionMessage=showRunningTasks() +[Button1] +Name=Power Button +Key=Hangup +HeldActionService=Launcher +HeldActionMessage=execute(QString) +HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n) diff --git a/tools/qvfb/config.ui b/tools/qvfb/config.ui new file mode 100644 index 0000000..7a45bfe --- /dev/null +++ b/tools/qvfb/config.ui @@ -0,0 +1,2528 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>Config</class> + <widget class="QDialog" name="Config" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>650</height> + </rect> + </property> + <property name="windowTitle" > + <string>Configure</string> + </property> + <property name="sizeGripEnabled" > + <bool>true</bool> + </property> + <layout class="QVBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>8</number> + </property> + <property name="topMargin" > + <number>8</number> + </property> + <property name="rightMargin" > + <number>8</number> + </property> + <property name="bottomMargin" > + <number>8</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QGroupBox" name="ButtonGroup1" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title" > + <string>Size</string> + </property> + <layout class="QVBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>11</number> + </property> + <property name="topMargin" > + <number>11</number> + </property> + <property name="rightMargin" > + <number>11</number> + </property> + <property name="bottomMargin" > + <number>11</number> + </property> + <item> + <widget class="QRadioButton" name="size_176_220" > + <property name="text" > + <string>176x220 "SmartPhone"</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="size_240_320" > + <property name="text" > + <string>240x320 "PDA"</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="size_320_240" > + <property name="text" > + <string>320x240 "TV" / "QVGA"</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="size_640_480" > + <property name="text" > + <string>640x480 "VGA"</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="size_800_600" > + <property name="text" > + <string>800x600</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="size_1024_768" > + <property name="text" > + <string>1024x768</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QRadioButton" name="size_custom" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Custom</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="size_width" > + <property name="minimum" > + <number>1</number> + </property> + <property name="maximum" > + <number>1280</number> + </property> + <property name="singleStep" > + <number>16</number> + </property> + <property name="value" > + <number>400</number> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="size_height" > + <property name="minimum" > + <number>1</number> + </property> + <property name="maximum" > + <number>1024</number> + </property> + <property name="singleStep" > + <number>16</number> + </property> + <property name="value" > + <number>300</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="ButtonGroup2" > + <property name="title" > + <string>Depth</string> + </property> + <layout class="QVBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>11</number> + </property> + <property name="topMargin" > + <number>11</number> + </property> + <property name="rightMargin" > + <number>11</number> + </property> + <property name="bottomMargin" > + <number>11</number> + </property> + <item> + <widget class="QRadioButton" name="depth_1" > + <property name="text" > + <string>1 bit monochrome</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_4gray" > + <property name="text" > + <string>4 bit grayscale</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_8" > + <property name="text" > + <string>8 bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_12" > + <property name="text" > + <string>12 (16) bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_15" > + <property name="text" > + <string>15 bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_16" > + <property name="text" > + <string>16 bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_18" > + <property name="text" > + <string>18 bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_24" > + <property name="text" > + <string>24 bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_32" > + <property name="text" > + <string>32 bit</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="depth_32_argb" > + <property name="text" > + <string>32 bit ARGB</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="TextLabel1_3" > + <property name="text" > + <string>Skin</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="skin" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Expanding" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <item> + <property name="text" > + <string>None</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="touchScreen" > + <property name="text" > + <string>Emulate touch screen (no mouse move)</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="lcdScreen" > + <property name="text" > + <string>Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>10</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="TextLabel1" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string><p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.</string> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="GroupBox1" > + <property name="title" > + <string>Gamma</string> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>11</number> + </property> + <property name="topMargin" > + <number>11</number> + </property> + <property name="rightMargin" > + <number>11</number> + </property> + <property name="bottomMargin" > + <number>11</number> + </property> + <property name="horizontalSpacing" > + <number>6</number> + </property> + <property name="verticalSpacing" > + <number>6</number> + </property> + <item row="6" column="0" > + <widget class="QLabel" name="TextLabel3" > + <property name="text" > + <string>Blue</string> + </property> + </widget> + </item> + <item row="6" column="1" > + <widget class="QSlider" name="bslider" > + <property name="palette" > + <palette> + <active> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>127</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>38</red> + <green>38</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>127</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>38</red> + <green>38</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>127</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>38</red> + <green>38</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="maximum" > + <number>400</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="6" column="2" > + <widget class="QLabel" name="blabel" > + <property name="text" > + <string>1.0</string> + </property> + </widget> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="TextLabel2" > + <property name="text" > + <string>Green</string> + </property> + </widget> + </item> + <item row="4" column="1" > + <widget class="QSlider" name="gslider" > + <property name="palette" > + <palette> + <active> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>255</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>38</red> + <green>255</green> + <blue>38</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>127</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>170</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>255</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>38</red> + <green>255</green> + <blue>38</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>127</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>170</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>255</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>38</red> + <green>255</green> + <blue>38</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>127</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>170</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="maximum" > + <number>400</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="4" column="2" > + <widget class="QLabel" name="glabel" > + <property name="text" > + <string>1.0</string> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="TextLabel7" > + <property name="text" > + <string>All</string> + </property> + </widget> + </item> + <item row="0" column="2" > + <widget class="QLabel" name="TextLabel8" > + <property name="text" > + <string>1.0</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QSlider" name="gammaslider" > + <property name="palette" > + <palette> + <active> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>170</red> + <green>170</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>170</red> + <green>170</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>170</red> + <green>170</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="maximum" > + <number>400</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="TextLabel1_2" > + <property name="text" > + <string>Red</string> + </property> + </widget> + </item> + <item row="2" column="2" > + <widget class="QLabel" name="rlabel" > + <property name="text" > + <string>1.0</string> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QSlider" name="rslider" > + <property name="palette" > + <palette> + <active> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>38</green> + <blue>38</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>38</green> + <blue>38</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>38</green> + <blue>38</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>127</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>170</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>128</red> + <green>128</green> + <blue>128</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>220</red> + <green>220</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>10</red> + <green>95</green> + <blue>137</blue> + </color> + </brush> + </colorrole> + <colorrole role="HighlightedText" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Link" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="LinkVisited" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>232</red> + <green>232</green> + <blue>232</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="maximum" > + <number>400</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="8" column="0" colspan="3" > + <widget class="QPushButton" name="PushButton3" > + <property name="text" > + <string>Set all to 1.0</string> + </property> + </widget> + </item> + <item rowspan="9" row="0" column="3" > + <widget class="GammaView" native="1" name="MyCustomWidget1" /> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>6</number> + </property> + <property name="leftMargin" > + <number>0</number> + </property> + <property name="topMargin" > + <number>0</number> + </property> + <property name="rightMargin" > + <number>0</number> + </property> + <property name="bottomMargin" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="buttonOk" > + <property name="text" > + <string>&OK</string> + </property> + <property name="autoDefault" > + <bool>true</bool> + </property> + <property name="default" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="buttonCancel" > + <property name="text" > + <string>&Cancel</string> + </property> + <property name="autoDefault" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11" /> + <customwidgets> + <customwidget> + <class>GammaView</class> + <extends></extends> + <header>gammaview.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>size_width</sender> + <signal>valueChanged(int)</signal> + <receiver>size_custom</receiver> + <slot>click()</slot> + <hints> + <hint type="sourcelabel" > + <x>152</x> + <y>193</y> + </hint> + <hint type="destinationlabel" > + <x>94</x> + <y>199</y> + </hint> + </hints> + </connection> + <connection> + <sender>size_height</sender> + <signal>valueChanged(int)</signal> + <receiver>size_custom</receiver> + <slot>click()</slot> + <hints> + <hint type="sourcelabel" > + <x>259</x> + <y>196</y> + </hint> + <hint type="destinationlabel" > + <x>64</x> + <y>188</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/qvfb/gammaview.h b/tools/qvfb/gammaview.h new file mode 100644 index 0000000..53717a6 --- /dev/null +++ b/tools/qvfb/gammaview.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GAMMAVIEW_H +#define GAMMAVIEW_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE + +class GammaView: public QWidget +{ + Q_OBJECT +public: + GammaView( QWidget *parent = 0, Qt::WindowFlags f = 0 ) + : QWidget(parent,f) { } +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/images/logo-nt.png b/tools/qvfb/images/logo-nt.png Binary files differnew file mode 100644 index 0000000..92f77d8 --- /dev/null +++ b/tools/qvfb/images/logo-nt.png diff --git a/tools/qvfb/images/logo.png b/tools/qvfb/images/logo.png Binary files differnew file mode 100644 index 0000000..0093177 --- /dev/null +++ b/tools/qvfb/images/logo.png diff --git a/tools/qvfb/main.cpp b/tools/qvfb/main.cpp new file mode 100644 index 0000000..b0eb4e7 --- /dev/null +++ b/tools/qvfb/main.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfb.h" + +#include <QApplication> +#include <QRegExp> +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#ifdef Q_WS_X11 +#include <QX11Info> +#endif + +QT_BEGIN_NAMESPACE + +void fn_quit_qvfb(int) +{ + // pretend that we have quit normally + qApp->quit(); +} + + +void usage( const char *app ) +{ + printf( "Usage: %s [-width width] [-height height] [-depth depth] [-zoom zoom]" + "[-mmap] [-nocursor] [-qwsdisplay :id] [-x11display :id] [-skin skindirectory]\n" + "Supported depths: 1, 4, 8, 12, 15, 16, 18, 24, 32\n", app ); +} +int qvfb_protocol = 0; + +int runQVfb( int argc, char *argv[] ) +{ + Q_INIT_RESOURCE(qvfb); + + QApplication app( argc, argv ); + + int width = 0; + int height = 0; + int depth = -32; // default, but overridable by skin + bool depthSet = false; + int rotation = 0; + bool cursor = true; + QVFb::DisplayType displayType = QVFb::QWS; + double zoom = 1.0; + QString displaySpec( ":0" ); + QString skin; + + for ( int i = 1; i < argc; i++ ){ + QString arg = argv[i]; + if ( arg == "-width" ) { + width = atoi( argv[++i] ); + } else if ( arg == "-height" ) { + height = atoi( argv[++i] ); + } else if ( arg == "-skin" ) { + skin = argv[++i]; + } else if ( arg == "-depth" ) { + depth = atoi( argv[++i] ); + depthSet = true; + } else if ( arg == "-nocursor" ) { + cursor = false; + } else if ( arg == "-mmap" ) { + qvfb_protocol = 1; + } else if ( arg == "-zoom" ) { + zoom = atof( argv[++i] ); + } else if ( arg == "-qwsdisplay" ) { + displaySpec = argv[++i]; + displayType = QVFb::QWS; +#ifdef Q_WS_X11 + } else if ( arg == "-x11display" ) { + displaySpec = argv[++i]; + displayType = QVFb::X11; + + // Usually only the default X11 depth will work with Xnest, + // so override the default of 32 with the actual X11 depth. + if (!depthSet) + depth = -QX11Info::appDepth(); // default, but overridable by skin +#endif + } else { + printf( "Unknown parameter %s\n", arg.toLatin1().constData() ); + usage( argv[0] ); + exit(1); + } + } + + int displayId = 0; + QRegExp r( ":[0-9]+" ); + int m = r.indexIn( displaySpec, 0 ); + int len = r.matchedLength(); + if ( m >= 0 ) { + displayId = displaySpec.mid( m+1, len-1 ).toInt(); + } + QRegExp rotRegExp( "Rot[0-9]+" ); + m = rotRegExp.indexIn( displaySpec, 0 ); + len = rotRegExp.matchedLength(); + if ( m >= 0 ) { + rotation = displaySpec.mid( m+3, len-3 ).toInt(); + } + + signal(SIGINT, fn_quit_qvfb); + signal(SIGTERM, fn_quit_qvfb); + + QVFb mw( displayId, width, height, depth, rotation, skin, displayType ); + mw.setZoom(zoom); + //app.setMainWidget( &mw ); + mw.enableCursor(cursor); + mw.show(); + + return app.exec(); +} + +QT_END_NAMESPACE + +int main( int argc, char *argv[] ) +{ + return QT_PREPEND_NAMESPACE(runQVfb)(argc, argv); +} diff --git a/tools/qvfb/pda.qrc b/tools/qvfb/pda.qrc new file mode 100644 index 0000000..b14e7b3 --- /dev/null +++ b/tools/qvfb/pda.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/skins"> + <file>pda.skin</file> +</qresource> +</RCC> diff --git a/tools/qvfb/pda.skin b/tools/qvfb/pda.skin new file mode 100644 index 0000000..037f750 --- /dev/null +++ b/tools/qvfb/pda.skin @@ -0,0 +1,14 @@ +pda_up.png pda_down.png +57 81 +240 320 +11 +"Power" 0x0100000a 277 36 302 57 +"F1" 0x01000030 52 439 81 470 +"F2" 0x01000031 101 422 130 451 +"F3" 0x01000032 232 423 260 452 +"F4" 0x01000033 279 445 309 473 +"Left" 0x01000012 155 438 176 472 +"Down" 0x01000015 169 471 203 486 +"Right" 0x01000014 193 448 215 472 +"Up" 0x01000013 166 427 199 451 +"Enter" 0x01000005 177 448 193 468 diff --git a/tools/qvfb/pda_down.png b/tools/qvfb/pda_down.png Binary files differnew file mode 100644 index 0000000..0ea157d --- /dev/null +++ b/tools/qvfb/pda_down.png diff --git a/tools/qvfb/pda_up.png b/tools/qvfb/pda_up.png Binary files differnew file mode 100644 index 0000000..541e3c4 --- /dev/null +++ b/tools/qvfb/pda_up.png diff --git a/tools/qvfb/qanimationwriter.cpp b/tools/qvfb/qanimationwriter.cpp new file mode 100644 index 0000000..caa7e95 --- /dev/null +++ b/tools/qvfb/qanimationwriter.cpp @@ -0,0 +1,451 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qanimationwriter.h" +#include <QFile> +#include <QString> +#include <QPainter> +#include <png.h> +#include <limits.h> +#include <netinet/in.h> // for htonl + +#ifdef QT_LINUXBASE +# include <arpa/inet.h> // for htonl (LSB only) +#endif + +QT_BEGIN_NAMESPACE + +class QAnimationWriterData +{ +public: + QAnimationWriterData(QIODevice* d) : framerate(1000), dev(d) {} + void setFrameRate(int d) { framerate = d; } + virtual ~QAnimationWriterData() { } + virtual void setImage(const QImage& src)=0; + virtual bool canCompose() const { return false; } + virtual void composeImage(const QImage&, const QPoint& ) {} + +protected: + int framerate; + QIODevice* dev; +}; + + +class QAnimationWriterMNG : public QAnimationWriterData { + bool first; + png_structp png_ptr; + png_infop info_ptr; +public: + QAnimationWriterMNG(QIODevice* d) : QAnimationWriterData(d) + { + first = true; + begin_png(); + } + + ~QAnimationWriterMNG() + { + if (first) { + // Eh? Not images. + QImage dummy(1,1,QImage::Format_RGB32); + setImage(dummy); + } + writeMEND(); + end_png(); + } + + void begin_png() + { + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); + info_ptr = png_create_info_struct(png_ptr); + png_set_compression_level(png_ptr,9); + png_set_write_fn(png_ptr, (void*)this, write, 0); + } + + void end_png() + { + png_destroy_write_struct(&png_ptr, &info_ptr); + } + + static void write( png_structp png_ptr, png_bytep data, png_size_t length) + { + QAnimationWriterMNG* that = (QAnimationWriterMNG*)png_get_io_ptr(png_ptr); + /*uint nw =*/ that->dev->write((const char*)data,length); + } + + void writePNG(const QImage& image) + { +#ifndef QT_LINUXBASE + // LSB disallows accessing the info_ptr directly. LSB's png_set_IHDR sets + // the channels anyways, so just comment it out for LSB usage + info_ptr->channels = 4; +#endif + png_set_sig_bytes(png_ptr, 8); // Pretend we already wrote the sig + png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), + 8, image.hasAlphaChannel() + ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, + 0, 0, 0); + png_write_info(png_ptr, info_ptr); + if (!image.hasAlphaChannel()) + png_set_filler(png_ptr, 0, + QSysInfo::ByteOrder == QSysInfo::BigEndian ? + PNG_FILLER_BEFORE : PNG_FILLER_AFTER); + //if ( QImage::systemByteOrder() == QImage::BigEndian ) { + //png_set_swap_alpha(png_ptr); + //} + if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { + png_set_bgr(png_ptr); + } + + int height = image.height(); + png_bytep *row_pointers = new png_bytep[height]; + for (int i = 0; i < height; ++i) + row_pointers[i] = (png_bytep)image.scanLine(i); + png_write_image(png_ptr, row_pointers); + delete [] row_pointers; + png_write_end(png_ptr, info_ptr); + end_png(); + begin_png(); + } + + void writeMHDR(const QSize& size, int framerate) + { + dev->write("\212MNG\r\n\032\n", 8); + + struct { + int width; + int height; + int framerate; + int a,b,c; + int profile; + } chunk; + chunk.width = htonl(size.width()); + chunk.height = htonl(size.height()); + chunk.framerate = htonl(framerate); + chunk.a=0; + chunk.b=0; + chunk.c=0; + chunk.profile = htonl(0x00000003); + + png_write_chunk(png_ptr, (png_byte*)"MHDR", (png_byte*)&chunk, sizeof(chunk)); + } + + void writeMEND() + { + png_write_chunk(png_ptr, (png_byte*)"MEND", 0, 0); + } + + void writeDEFI(const QPoint& offset, const QSize& /*size*/) + { + struct { + ushort o; + uchar s; + uchar concrete; + int x,y; + int lc,rc,tc,bc; + } chunk; + chunk.o=0; + chunk.s=0; + chunk.concrete=1; + chunk.x=htonl(offset.x()); + chunk.y=htonl(offset.y()); + chunk.lc=0; + chunk.rc=0; + chunk.tc=htonl(INT_MAX); + chunk.bc=htonl(INT_MAX); + + png_write_chunk(png_ptr, (png_byte*)"DEFI", (png_byte*)&chunk, sizeof(chunk)); + } + + void writeFRAM(const QSize& size) + { + struct { + uchar mode; + uchar n; + uchar nu; + uchar d; + uchar t; + uchar clip; + uchar s; + uchar deltatype; + uint left; + uint right; + uint top; + uint bottom; + } chunk; + chunk.mode=1; + chunk.n='a'; + chunk.nu=0; + chunk.d=0; + chunk.clip=1; + chunk.t=0; + chunk.s=0; + chunk.deltatype=0; + chunk.left=0; + chunk.right=htonl(size.width()); + chunk.top=0; + chunk.bottom=htonl(size.height()); + + png_write_chunk(png_ptr, (png_byte*)"FRAM", (png_byte*)&chunk, sizeof(chunk)); + } + + void writeMOVE(const QPoint& offset) + { + struct { + uchar filler[3]; + uchar z[5]; + int x,y; + } chunk; + memset(chunk.z,0,5); + chunk.x=htonl(offset.x()); + chunk.y=htonl(offset.y()); + + png_write_chunk(png_ptr, (png_byte*)"MOVE", ((png_byte*)&chunk)+3, sizeof(chunk)-3); + } + + void setImage(const QImage& src) + { + if (first) { + first = false; + writeMHDR(src.size(),framerate); + } + composeImage(src,QPoint(0,0)); + } + + bool canCompose() const { return true; } + + void composeImage(const QImage& src, const QPoint& offset) + { + writeMOVE(offset); + //writeFRAM(src.size()); + writePNG(src); + } +}; + +QAnimationWriter::QAnimationWriter(const QString& filename, const char* format) +{ + if (qstrncmp(format, "MNG", 4)) { + qWarning("Format \"%s\" not supported, only MNG", format); + dev = 0; + d = 0; + } else { + QFile *f = new QFile(filename); + f->open(QIODevice::WriteOnly); + dev = f; + d = new QAnimationWriterMNG(dev); + } +} + +bool QAnimationWriter::okay() const +{ + if (!dev) + return false; + QFile *file = qobject_cast<QFile*>(dev); + Q_ASSERT(file); + return (file->error() == QFile::NoError); +} + +QAnimationWriter::~QAnimationWriter() +{ + delete d; + delete dev; +} + +void QAnimationWriter::setFrameRate(int r) +{ + if (d) + d->setFrameRate(r); +} + +void QAnimationWriter::appendFrame(const QImage& frm, const QPoint& offset) +{ + if (!dev) + return; + + const QImage frame = frm.convertToFormat(QImage::Format_RGB32); + const int alignx = 1; + if (prev.isNull() || !d->canCompose()) { + d->setImage(frame); + } else { + bool done; + int minx, maxx, miny, maxy; + int w = frame.width(); + int h = frame.height(); + + const quint32 *framePtr = reinterpret_cast<const quint32*>(frame.bits()); + const quint32 *prevPtr = reinterpret_cast<const quint32*>(prev.bits()); + const int frameStride = frame.bytesPerLine() / sizeof(quint32); + const int prevStride = prev.bytesPerLine() / sizeof(quint32); + + // Find left edge of change + done = false; + for (minx = 0; minx < w && !done; ++minx) { + const quint32 *p1 = framePtr + minx; + const quint32 *p2 = prevPtr + minx + offset.x(); + for (int y = 0; y < h; ++y) { + if (*p1 != *p2) { + done = true; + break; + } + p1 += frameStride; + p2 += prevStride; + } + } + --minx; + + // Find right edge of change + done = false; + for (maxx = w-1; maxx >= 0 && !done; --maxx) { + const quint32 *p1 = framePtr + maxx; + const quint32 *p2 = prevPtr + maxx + offset.x(); + for (int y = 0; y < h; ++y) { + if (*p1 != *p2) { + done = true; + break; + } + p1 += frameStride; + p2 += prevStride; + } + } + ++maxx; + + // Find top edge of change + done = false; + for (miny = 0; miny < h && !done; ++miny) { + const quint32 *p1 = framePtr + miny * frameStride; + const quint32 *p2 = prevPtr + miny * prevStride + offset.x(); + for (int x = 0; x < w; ++x) { + if (*p1 != *p2) { + done = true; + break; + } + ++p1; + ++p2; + } + } + --miny; + + // Find right edge of change + done = false; + for (maxy = h-1; maxy >= 0 && !done; --maxy) { + const quint32 *p1 = framePtr + maxy * frameStride; + const quint32 *p2 = prevPtr + maxy * prevStride + offset.x(); + for (int x = 0; x < w; ++x) { + if (*p1 != *p2) { + done = true; + break; + } + ++p1; + ++p2; + } + } + ++maxy; + + if (minx > maxx) + minx = maxx = 0; + if (miny > maxy) + miny = maxy = 0; + + if (alignx > 1) { + minx -= minx % alignx; + maxx = maxx - maxx % alignx + alignx - 1; + } + + int dw = maxx - minx + 1; + int dh = maxy - miny + 1; + + QImage diff(dw, dh, QImage::Format_ARGB32); + + int x, y; + for (y = 0; y < dh; ++y) { + QRgb* li = (QRgb*)frame.scanLine(y+miny)+minx; + QRgb* lp = (QRgb*)prev.scanLine(y+miny+offset.y())+minx+offset.x(); + QRgb* ld = (QRgb*)diff.scanLine(y); + if (alignx) { + for (x = 0; x < dw; x += alignx) { + int i; + for (i = 0; i < alignx; ++i) { + if (li[x+i] != lp[x+i]) + break; + } + if (i == alignx) { + // All the same + for (i = 0; i < alignx; ++i) + ld[x+i] = qRgba(0,0,0,0); + } else { + // Some different + for (i = 0; i < alignx; ++i) + ld[x+i] = 0xff000000 | li[x+i]; + } + } + } else { + for (x = 0; x < dw; ++x) { + if (li[x] != lp[x]) + ld[x] = 0xff000000 | li[x]; + else + ld[x] = qRgba(0,0,0,0); + } + } + } + + d->composeImage(diff, QPoint(minx, miny) + offset); + } + if (prev.isNull() || (prev.size() == frame.size() && offset == QPoint(0,0))) { + prev = frame; + } else { + QPainter p(&prev); + p.drawImage(offset.x(), offset.y(), frame, 0, 0, + frame.width(), frame.height()); + } +} + +void QAnimationWriter::appendFrame(const QImage& frm) +{ + appendFrame(frm, QPoint(0,0)); +} + +void QAnimationWriter::appendBlankFrame() +{ + QImage i(1,1,QImage::Format_ARGB32); + i.fill(0); + d->composeImage(i, QPoint(0,0)); +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qanimationwriter.h b/tools/qvfb/qanimationwriter.h new file mode 100644 index 0000000..8440a89 --- /dev/null +++ b/tools/qvfb/qanimationwriter.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANIMATIONWRITER_H +#define QANIMATIONWRITER_H + +#include <QImage> + +QT_BEGIN_NAMESPACE + +class QAnimationWriterData; + +class QAnimationWriter +{ +public: + QAnimationWriter(const QString& filename, const char* format = "MNG"); + ~QAnimationWriter(); + + bool okay() const; + void setFrameRate(int); + void appendBlankFrame(); + void appendFrame(const QImage&); + void appendFrame(const QImage&, const QPoint& offset); + +private: + QImage prev; + QIODevice* dev; + QAnimationWriterData* d; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qtopiakeysym.h b/tools/qvfb/qtopiakeysym.h new file mode 100644 index 0000000..2641e91 --- /dev/null +++ b/tools/qvfb/qtopiakeysym.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved. +** +** This file is part of the Phone Edition of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTKEYSYM_H +#define QTKEYSYM_H + +/* Special keys used by Qtopia, mapped into the X11 private keypad range */ +#define QTOPIAXK_Select 0x11000601 +#define QTOPIAXK_Yes 0x11000602 +#define QTOPIAXK_No 0x11000603 + +#define QTOPIAXK_Cancel 0x11000604 +#define QTOPIAXK_Printer 0x11000605 +#define QTOPIAXK_Execute 0x11000606 +#define QTOPIAXK_Sleep 0x11000607 +#define QTOPIAXK_Play 0x11000608 +#define QTOPIAXK_Zoom 0x11000609 + +#define QTOPIAXK_Context1 0x1100060A +#define QTOPIAXK_Context2 0x1100060B +#define QTOPIAXK_Context3 0x1100060C +#define QTOPIAXK_Context4 0x1100060D +#define QTOPIAXK_Call 0x1100060E +#define QTOPIAXK_Hangup 0x1100060F +#define QTOPIAXK_Flip 0x11000610 + +#define QTOPIAXK_Min QTOPIAXK_Select +#define QTOPIAXK_Max QTOPIAXK_Flip + +#endif diff --git a/tools/qvfb/qvfb.cpp b/tools/qvfb/qvfb.cpp new file mode 100644 index 0000000..b6a715c --- /dev/null +++ b/tools/qvfb/qvfb.cpp @@ -0,0 +1,1137 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfb.h" +#include "qvfbview.h" +#ifdef Q_WS_X11 +#include "qvfbx11view.h" +#endif +#include "qvfbratedlg.h" +#include "ui_config.h" +#include "qanimationwriter.h" + +#include <deviceskin.h> + +#include <QMenuBar> +#include <QMenu> +#include <QApplication> +#include <QMessageBox> +#include <QComboBox> +#include <QLabel> +#include <QFileDialog> +#include <QSlider> +#include <QSpinBox> +#include <QLayout> +#include <QRadioButton> +#include <QImage> +#include <QPixmap> +#include <QCheckBox> +#include <QCursor> +#include <QTime> +#include <QScrollArea> +#include <QProgressBar> +#include <QPushButton> +#include <QTextStream> +#include <QFile> +#include <QFileInfo> +#include <QDebug> + +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> + +QT_BEGIN_NAMESPACE + +// ===================================================================== + +static const char *red_on_led_xpm[] = { +"11 11 10 1", +" c None", +". c #FF0000", +"+ c #FF4C4C", +"@ c #FF7A7A", +"# c #D30000", +"$ c #FF9393", +"% c #BA0000", +"& c #FFFFFF", +"* c #7F0000", +"= c #000000", +" ", +" .++@@ ", +" .....+@ ", +" ##...$.+@ ", +" %#..$&$.+ ", +" *#...$..+ ", +" *%#...... ", +" =*%#..... ", +" =*%###. ", +" ===*. ", +" "}; + +static const char *red_off_led_xpm[] = { +"11 11 12 1", +" c None", +". c #CDB7B4", +"+ c #D2BFBD", +"@ c #DBCBCA", +"# c #E5D9D8", +"$ c #BC9E9B", +"% c #E2D6D5", +"& c #AD8986", +"* c #FFFFFF", +"= c #A8817D", +"- c #B2908D", +"; c #6F4D4A", +" ", +" .++@# ", +" .....@# ", +" $$...%.@# ", +" &$..%*%.@ ", +" =-...%..+ ", +" =&-...... ", +" ;==-..... ", +" ;=&-$$. ", +" ;==&$ ", +" "}; + +static bool copyButtonConfiguration(const QString &prefix, int displayId) +{ + const QString destDir = QString(QLatin1String("/tmp/qtembedded-%1/")).arg(displayId); + const QFileInfo src(prefix + QLatin1String("defaultbuttons.conf")); + const QFileInfo dst(destDir + QLatin1String("defaultbuttons.conf")); + unlink(dst.absoluteFilePath().toLatin1().constData()); + if (!src.exists()) + return false; + const bool rc = QFile::copy(src.absoluteFilePath(), dst.absoluteFilePath()); + if (!rc) + qWarning() << "Failed to copy the button configuration file " << src.absoluteFilePath() << " to " << dst.absoluteFilePath() << '.'; + return rc; +} + +// ===================================================================== + +class AnimationSaveWidget : public QWidget { + Q_OBJECT +public: + AnimationSaveWidget(QVFbAbstractView *v); + ~AnimationSaveWidget(); + bool detectPpmtoMpegCommand(); + void timerEvent(QTimerEvent *te); + void convertToMpeg(QString filename); + void removeTemporaryFiles(); +protected slots: + void toggleRecord(); + void reset(); + void save(); +private: + QVFbAbstractView *view; + QProgressBar *progressBar; + QLabel *statusText; + bool haveMpeg, savingAsMpeg, recording; + QCheckBox *mpegSave; + QAnimationWriter *animation; + QPushButton *recBt, *resetBt, *saveBt; + QLabel *timeDpy, *recLED; + int timerId, progressTimerId; + QPixmap recOn, recOff; + QTime tm; + int elapsed, imageNum; +}; + +// ===================================================================== + +Zoomer::Zoomer(QVFb* target) : + qvfb(target) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + QSlider *sl = new QSlider(Qt::Horizontal); + sl->setMinimum(10); + sl->setMaximum(64); + sl->setPageStep(1); + sl->setValue(32); + layout->addWidget(sl); + connect(sl,SIGNAL(valueChanged(int)),this,SLOT(zoom(int))); + label = new QLabel(); + layout->addWidget(label); +} + +void Zoomer::zoom(int z) +{ + double d = (double)z/32.0; + qvfb->setZoom(d); + label->setText(QString::number(d,'g',2)); +} + +// ===================================================================== + +QVFb::QVFb( int display_id, int w, int h, int d, int r, const QString &skin, DisplayType displayType, QWidget *parent, Qt::WindowFlags flags ) + : QMainWindow( parent, flags ) +{ + this->displayType = displayType; + view = 0; + secondaryView = 0; + scroller = 0; + this->skin = 0; + currentSkinIndex = -1; + findSkins(skin); + zoomer = 0; + QPixmap pix(":/res/images/logo.png"); + setWindowIcon( pix ); + rateDlg = 0; + refreshRate = 30; +#if QT_VERSION >= 0x030000 + // When compiling with Qt 3 we need to create the menu first to + // avoid scroll bars in the main window + createMenu( menuBar() ); + init( display_id, w, h, d, r, skin ); + enableCursor( true ); +#else + init( display_id, w, h, d, r, skin ); + createMenu( menuBar() ); +#endif +} + +QVFb::~QVFb() +{ +} + +void QVFb::popupMenu() +{ + QMenu *pm = new QMenu( this ); + createMenu( pm ); + pm->exec(QCursor::pos()); +} + +void QVFb::init( int display_id, int pw, int ph, int d, int r, const QString& skin_name ) +{ + delete view; + view = 0; + delete secondaryView; + secondaryView = 0; + delete scroller; + scroller = 0; + delete skin; + skin = 0; + + skinscaleH = skinscaleV = 1.0; + QVFbView::Rotation rot = ((r == 90) ? QVFbView::Rot90 : + ((r == 180) ? QVFbView::Rot180 : + ((r == 270) ? QVFbView::Rot270 : + QVFbView::Rot0 ))); + if ( !skin_name.isEmpty() ) { + const bool vis = isVisible(); + DeviceSkinParameters parameters; + QString readError; + if (parameters.read(skin_name,DeviceSkinParameters::ReadAll, &readError)) { + skin = new DeviceSkin(parameters, this); + connect(skin, SIGNAL(popupMenu()), this, SLOT(popupMenu())); + const int sw = parameters.screenSize().width(); + const int sh = parameters.screenSize().height(); + const int sd = parameters.screenDepth; + if (!pw) pw = sw; + if (!ph) ph = sh; + if (d < 0) { + if (sd) + d = sd; + else + d = -d; + } + if (vis) + hide(); + menuBar()->hide(); + scroller = 0; +#ifdef Q_WS_X11 + if (displayType == X11) + view = new QVFbX11View( display_id, pw, ph, d, rot, skin ); + else +#endif + view = new QVFbView( display_id, pw, ph, d, rot, skin ); + skin->setView( view ); + view->setContentsMargins( 0, 0, 0, 0 ); + view->setTouchscreenEmulation(!parameters.hasMouseHover); + connect(skin, SIGNAL(skinKeyPressEvent(int,QString,bool)), view, SLOT(skinKeyPressEvent(int,QString,bool))); + connect(skin, SIGNAL(skinKeyReleaseEvent(int,QString,bool)), view, SLOT(skinKeyReleaseEvent(int,QString,bool))); + + copyButtonConfiguration(skin->prefix(), view->displayId()); + + setCentralWidget( skin ); + adjustSize(); + skinscaleH = (double)sw/pw; + skinscaleV = (double)sh/ph; + if ( skinscaleH != 1.0 || skinscaleH != 1.0 ) + setZoom(skinscaleH); + view->show(); + + if (parameters.hasSecondaryScreen()) { + const QSize ssize = parameters.secondaryScreenSize(); + // assumes same depth and rotation +#ifdef Q_WS_X11 + if (displayType == X11) + secondaryView = new QVFbX11View( display_id+1, ssize.width(), ssize.height(), d, rot, skin ); + else +#endif + secondaryView = new QVFbView( display_id+1, ssize.width(), ssize.height(), d, rot, skin ); + skin->setSecondaryView(secondaryView); + secondaryView->show(); + } + + if ( vis ) show(); + } else { + qWarning("%s", qPrintable(readError)); + } + } + + // If we failed to get a skin or we were not supplied + // with one then fallback to a framebuffer without + // a skin + if (!skin){ + // Default values + if (!pw) + pw = 240; + if (!ph) + ph = 320; + if (!d) + d = 32; + else if (d < 0) + d = -d; + + if (currentSkinIndex != -1) { + clearMask(); + setParent( 0, 0 ); + move( pos() ); + show(); + //unset fixed size: + setMinimumSize(0,0); + setMaximumSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX); + } + menuBar()->show(); + scroller = new QScrollArea(this); + scroller->setFocusPolicy(Qt::NoFocus); // don't steal key events from the embedded app +#ifdef Q_WS_X11 + if (displayType == X11) + view = new QVFbX11View( display_id, pw, ph, d, rot, scroller ); + else +#endif + view = new QVFbView( display_id, pw, ph, d, rot, scroller ); + scroller->setWidget(view); + view->setContentsMargins( 0, 0, 0, 0 ); + setCentralWidget(scroller); +#if QT_VERSION >= 0x030000 + ph += 2; // avoid scrollbar +#endif + scroller->show(); + // delete defaultbuttons.conf if it was left behind... + unlink(QFileInfo(QString("/tmp/qtembedded-%1/defaultbuttons.conf").arg(view->displayId())).absoluteFilePath().toLatin1().constData()); + if (secondaryView) + unlink(QFileInfo(QString("/tmp/qtembedded-%1/defaultbuttons.conf").arg(view->displayId()+1)).absoluteFilePath().toLatin1().constData()); + } + view->setRate(refreshRate); + if (secondaryView) { + secondaryView->setRate(refreshRate); + } + // Resize QVFb to the new size + QSize newSize = view->sizeHint(); + + // ... fudge factor + newSize += QSize(20, 35); + + resize(newSize); + + setWindowTitle(QString("Virtual framebuffer %1x%2 %3bpp Display :%4 Rotate %5") + .arg(view->displayWidth()).arg(view->displayHeight()) + .arg(d).arg(display_id).arg(r)); +} + +void QVFb::enableCursor( bool e ) +{ + if ( skin && skin->hasCursor() ) { + view->setCursor( Qt::BlankCursor ); + if (secondaryView) + secondaryView->setCursor( Qt::BlankCursor ); + } else { + view->setCursor( e ? Qt::ArrowCursor : Qt::BlankCursor ); + if (secondaryView) + secondaryView->setCursor( e ? Qt::ArrowCursor : Qt::BlankCursor ); + } + cursorAction->setChecked( e ); +} + +template <typename T> +void QVFb::createMenu(T *menu) +{ + menu->addMenu( createFileMenu() ); + menu->addMenu( createViewMenu() ); + menu->addSeparator(); + menu->addMenu( createHelpMenu() ); +} + +QMenu* QVFb::createFileMenu() +{ + QMenu *file = new QMenu( "File", this ); + file->addAction( "Configure...", this, SLOT(configure()), 0 ); + file->addSeparator(); + file->addAction( "&Save image...", this, SLOT(saveImage()), 0 ); + file->addAction( "&Animation...", this, SLOT(toggleAnimation()), 0 ); + file->addSeparator(); + file->addAction( "&Quit", qApp, SLOT(quit()) ); + return file; +} + +QMenu* QVFb::createViewMenu() +{ + viewMenu = new QMenu( "View", this ); + cursorAction = viewMenu->addAction( "Show &Cursor", this, + SLOT(toggleCursor()) ); + cursorAction->setCheckable(true); + if ( view ) + enableCursor(true); + viewMenu->addAction( "&Refresh Rate...", this, SLOT(changeRate()) ); + viewMenu->addSeparator(); + viewMenu->addAction( "No rotation", this, SLOT(setRot0()) ); + viewMenu->addAction( "90\260 rotation", this, SLOT(setRot90()) ); + viewMenu->addAction( "180\260 rotation", this, SLOT(setRot180()) ); + viewMenu->addAction( "270\260 rotation", this, SLOT(setRot270()) ); + viewMenu->addSeparator(); + viewMenu->addAction( "Zoom scale &0.5", this, SLOT(setZoomHalf()) ); + viewMenu->addAction( "Zoom scale 0.75", this, SLOT(setZoom075()) ); + viewMenu->addAction( "Zoom scale &1", this, SLOT(setZoom1()) ); + viewMenu->addAction( "Zoom scale &2", this, SLOT(setZoom2()) ); + viewMenu->addAction( "Zoom scale &3", this, SLOT(setZoom3()) ); + viewMenu->addAction( "Zoom scale &4", this, SLOT(setZoom4()) ); + viewMenu->addSeparator(); + viewMenu->addAction( "Zoom scale...", this, SLOT(setZoom()) ); + return viewMenu; +} + + +QMenu* QVFb::createHelpMenu() +{ + QMenu *help = new QMenu( "Help", this ); + help->addAction("About...", this, SLOT(about())); + return help; +} + +void QVFb::setZoom(double z) +{ + view->setZoom(z,z*skinscaleV/skinscaleH); + if (secondaryView) + secondaryView->setZoom(z,z*skinscaleV/skinscaleH); + + if (skin) { + skin->setTransform(QMatrix().scale(z/skinscaleH,z/skinscaleV).rotate(90*view->displayRotation())); + if (secondaryView) + secondaryView->setFixedSize( + int(secondaryView->displayWidth()*z), + int(secondaryView->displayHeight()*z*skinscaleV/skinscaleH)); + } +} + +void QVFb::setRotation(QVFbView::Rotation r) +{ + view->setRotation(r); + if (secondaryView) + secondaryView->setRotation(r); + setZoom(view->zoomH()); +} + +void QVFb::setRot0() +{ + setRotation(QVFbView::Rot0); +} + +void QVFb::setRot90() +{ + setRotation(QVFbView::Rot90); +} + +void QVFb::setRot180() +{ + setRotation(QVFbView::Rot180); +} + +void QVFb::setRot270() +{ + setRotation(QVFbView::Rot270); +} + +void QVFb::setZoomHalf() +{ + setZoom(0.5); +} + +void QVFb::setZoom075() +{ + setZoom(0.75); +} + +void QVFb::setZoom1() +{ + setZoom(1); +} + +void QVFb::setZoom() +{ + if ( !zoomer ) + zoomer = new Zoomer(this); + zoomer->show(); +} + +void QVFb::setZoom2() +{ + setZoom(2); +} + +void QVFb::setZoom3() +{ + setZoom(3); +} + +void QVFb::setZoom4() +{ + setZoom(4); +} + +void QVFb::saveImage() +{ + QImage img = view->image(); + QString filename = QFileDialog::getSaveFileName(this, "Save Main Screen image", "snapshot.png", "Portable Network Graphics (*.png)"); + if (!filename.isEmpty()){ + if(!img.save(filename,"PNG")) + QMessageBox::critical(this, "Save Main Screen Image", "Save failed. Check that you have permission to write to the target directory."); + } + if (secondaryView) { + QImage img = view->image(); + QString filename = QFileDialog::getSaveFileName(this, "Save Second Screen image", "snapshot.png", "Portable Network Graphics (*.png)"); + if (!filename.isEmpty()) { + if(!img.save(filename,"PNG")) + QMessageBox::critical(this, "Save Second Screen Image", "Save failed. Check that you have permission to write to the target directory."); + } + } +} + +void QVFb::toggleAnimation() +{ + static AnimationSaveWidget *animWidget = 0; + if ( !animWidget ) + animWidget = new AnimationSaveWidget(view); + if ( animWidget->isVisible() ) + animWidget->hide(); + else + animWidget->show(); +} + +void QVFb::toggleCursor() +{ + enableCursor(cursorAction->isChecked()); +} + +void QVFb::changeRate() +{ + if ( !rateDlg ) { + rateDlg = new QVFbRateDialog( refreshRate, this ); + connect( rateDlg, SIGNAL(updateRate(int)), this, SLOT(setRate(int)) ); + } + + rateDlg->show(); +} + +void QVFb::setRate(int i) +{ + refreshRate = i; + view->setRate(i); + if (secondaryView) + secondaryView->setRate(i); +} + + +void QVFb::about() +{ + QMessageBox::about(this, "About QVFB", + "<h2>The Qt for Embedded Linux Virtual X11 Framebuffer</h2>" + "<p>This application runs under Qt for X11, emulating a simple framebuffer, " + "which the Qt for Embedded Linux server and clients can attach to just as if " + "it was a hardware Linux framebuffer. " + "<p>With the aid of this development tool, you can develop Qt for Embedded " + "Linux applications under X11 without having to switch to a virtual console. " + "This means you can comfortably use your other development tools such " + "as GUI profilers and debuggers." + ); +} + +void QVFb::findSkins(const QString ¤tSkin) +{ + skinnames.clear(); + skinfiles.clear(); + QDir dir(":/skins/","*.skin"); + const QFileInfoList l = dir.entryInfoList(); + int i = 1; // "None" is already in list at index 0 + for (QFileInfoList::const_iterator it = l.begin(); it != l.end(); ++it) { + skinnames.append((*it).baseName()); // should perhaps be in file + skinfiles.append((*it).filePath()); + if (((*it).baseName() + ".skin") == currentSkin) + currentSkinIndex = i; + i++; + } +} + +class Config : public QDialog, public Ui::Config +{ +public: + Config(QWidget *parent) + : QDialog(parent) + { + setupUi(this); + setModal(true); + + connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept())); + connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); + } +}; + +void QVFb::configure() +{ + config = new Config(this); + + int w = view->displayWidth(); + int h = view->displayHeight(); + + // Need to block signals, because we connect to animateClick(), + // since QCheckBox doesn't have setChecked(bool) in 2.x. + chooseSize(QSize(w,h)); + config->skin->insertItems(config->skin->count(), skinnames); + if (currentSkinIndex > 0) + config->skin->setCurrentIndex(currentSkinIndex); + config->skin->addItem(tr("Browse...")); + config->touchScreen->setChecked(view->touchScreenEmulation()); + config->lcdScreen->setChecked(view->lcdScreenEmulation()); + chooseDepth(view->displayDepth(), view->displayFormat()); + connect(config->skin, SIGNAL(activated(int)), this, SLOT(skinConfigChosen(int))); + if ( view->gammaRed() == view->gammaGreen() && view->gammaGreen() == view->gammaBlue() ) { + config->gammaslider->setValue(int(view->gammaRed()*400)); + config->rslider->setValue(100); + config->gslider->setValue(100); + config->bslider->setValue(100); + } else { + config->gammaslider->setValue(100); + config->rslider->setValue(int(view->gammaRed()*400)); + config->gslider->setValue(int(view->gammaGreen()*400)); + config->bslider->setValue(int(view->gammaBlue()*400)); + } + connect(config->gammaslider, SIGNAL(valueChanged(int)), this, SLOT(setGamma400(int))); + connect(config->rslider, SIGNAL(valueChanged(int)), this, SLOT(setR400(int))); + connect(config->gslider, SIGNAL(valueChanged(int)), this, SLOT(setG400(int))); + connect(config->bslider, SIGNAL(valueChanged(int)), this, SLOT(setB400(int))); + updateGammaLabels(); + + double ogr=view->gammaRed(), ogg=view->gammaGreen(), ogb=view->gammaBlue(); + qApp->setQuitOnLastWindowClosed(false); + + hide(); + if ( config->exec() ) { + int id = view->displayId(); // not settable yet + if ( config->size_176_220->isChecked() ) { + w=176; h=220; + } else if ( config->size_240_320->isChecked() ) { + w=240; h=320; + } else if ( config->size_320_240->isChecked() ) { + w=320; h=240; + } else if ( config->size_640_480->isChecked() ) { + w=640; h=480; + } else if ( config->size_800_600->isChecked() ) { + w=800; h=600; + } else if ( config->size_1024_768->isChecked() ) { + w=1024; h=768; + } else { + w=config->size_width->value(); + h=config->size_height->value(); + } + int d; + if ( config->depth_1->isChecked() ) + d=1; + else if ( config->depth_4gray->isChecked() ) + d=4; + else if ( config->depth_8->isChecked() ) + d=8; + else if ( config->depth_12->isChecked() ) + d=12; + else if ( config->depth_15->isChecked() ) + d = 15; + else if ( config->depth_16->isChecked() ) + d=16; + else if ( config->depth_18->isChecked() ) + d=18; + else if ( config->depth_24->isChecked() ) + d=24; + else + d=32; + QVFbView::PixelFormat displayFormat = config->depth_32_argb->isChecked() + ? QVFbView::ARGBFormat : QVFbView::DefaultFormat; + int skinIndex = config->skin->currentIndex(); + if ( w != view->displayWidth() || h != view->displayHeight() + || d != view->displayDepth() || skinIndex != currentSkinIndex ) { + QVFbView::Rotation rot = view->displayRotation(); + int r = ((rot == QVFbView::Rot90) ? 90 : + ((rot == QVFbView::Rot180) ? 180 : + ((rot == QVFbView::Rot270) ? 270 : 0 ))); + currentSkinIndex = skinIndex; + init( id, w, h, d, r, skinIndex > 0 ? skinfiles[skinIndex-1] : QString::null ); + } + view->setViewFormat(displayFormat); + view->setTouchscreenEmulation( config->touchScreen->isChecked() ); + bool lcdEmulation = config->lcdScreen->isChecked(); + view->setLcdScreenEmulation( lcdEmulation ); + if ( lcdEmulation ) + setZoom3(); + } else { + view->setGamma(ogr, ogg, ogb); + } + show(); + qApp->setQuitOnLastWindowClosed(true); + delete config; + config=0; +} + +void QVFb::chooseSize(const QSize& sz) +{ + config->size_width->blockSignals(true); + config->size_height->blockSignals(true); + config->size_width->setValue(sz.width()); + config->size_height->setValue(sz.height()); + config->size_width->blockSignals(false); + config->size_height->blockSignals(false); + config->size_custom->setChecked(true); // unless changed by settings below + config->size_176_220->setChecked(sz == QSize(176,220)); + config->size_240_320->setChecked(sz == QSize(240,320)); + config->size_320_240->setChecked(sz == QSize(320,240)); + config->size_640_480->setChecked(sz == QSize(640,480)); + config->size_800_600->setChecked(sz == QSize(800,600)); + config->size_1024_768->setChecked(sz == QSize(1024,768)); +} + +void QVFb::chooseDepth(int depth, QVFbView::PixelFormat displayFormat) +{ + config->depth_1->setChecked(depth==1); + config->depth_4gray->setChecked(depth==4); + config->depth_8->setChecked(depth==8); + config->depth_12->setChecked(depth==12); + config->depth_15->setChecked(depth==15); + config->depth_16->setChecked(depth==16); + config->depth_18->setChecked(depth==18); + config->depth_24->setChecked(depth==24); + config->depth_32->setChecked(depth==32 && displayFormat != QVFbView::ARGBFormat); + config->depth_32_argb->setChecked(depth==32 && displayFormat == QVFbView::ARGBFormat); +} + +void QVFb::skinConfigChosen(int i) +{ + if (i == config->skin->count() - 1) { // Browse... ? + QFileDialog dlg(this); + dlg.setFileMode(QFileDialog::DirectoryOnly); + dlg.setWindowTitle(tr("Load Custom Skin...")); + dlg.setFilter(tr("All QVFB Skins (*.skin)")); + dlg.setDirectory(QDir::current()); + if (dlg.exec() && dlg.selectedFiles().count() == 1) { + skinfiles.append(dlg.selectedFiles().first()); + i = skinfiles.count(); + config->skin->insertItem(i, QFileInfo(skinfiles.last()).baseName()); + config->skin->setCurrentIndex(i); + } else { + i = 0; + } + } + if ( i ) { + DeviceSkinParameters parameters; + QString readError; + if (parameters.read(skinfiles[i-1], DeviceSkinParameters::ReadSizeOnly, &readError)) { + chooseSize(parameters.screenSize()); + if (parameters.screenDepth) + chooseDepth(parameters.screenDepth,QVFbView::ARGBFormat); + config->touchScreen->setChecked(!parameters.hasMouseHover); + } else { + qWarning("%s", qPrintable(readError)); + } + } +} + +void QVFb::setGamma400(int n) +{ + double g = n/100.0; + view->setGamma(config->rslider->value()/100.0*g, + config->gslider->value()/100.0*g, + config->bslider->value()/100.0*g); + updateGammaLabels(); +} + +void QVFb::setR400(int n) +{ + double g = n/100.0; + view->setGamma(config->rslider->value()/100.0*g, + view->gammaGreen(), + view->gammaBlue()); + updateGammaLabels(); +} + +void QVFb::setG400(int n) +{ + double g = n/100.0; + view->setGamma(view->gammaRed(), + config->gslider->value()/100.0*g, + view->gammaBlue()); + updateGammaLabels(); +} + +void QVFb::setB400(int n) +{ + double g = n/100.0; + view->setGamma(view->gammaRed(), + view->gammaGreen(), + config->bslider->value()/100.0*g); + updateGammaLabels(); +} + +void QVFb::updateGammaLabels() +{ + config->rlabel->setText(QString::number(view->gammaRed(),'g',2)); + config->glabel->setText(QString::number(view->gammaGreen(),'g',2)); + config->blabel->setText(QString::number(view->gammaBlue(),'g',2)); +} + +QSize QVFb::sizeHint() const +{ + return QSize(int(view->displayWidth()*view->zoomH()), + int(menuBar()->height()+view->displayHeight()*view->zoomV())); +} + +// ===================================================================== + +AnimationSaveWidget::AnimationSaveWidget(QVFbAbstractView *v) : + QWidget((QWidget*)0,0), + view(v), recording(false), animation(0), + timerId(-1), progressTimerId(-1), + recOn(red_on_led_xpm), recOff(red_off_led_xpm), + imageNum(0) +{ + // Create the animation record UI dialog + QVBoxLayout *vlayout = new QVBoxLayout( this ); + + QWidget *hbox = new QWidget( this ); + vlayout->addWidget(hbox); + QHBoxLayout *hlayout = new QHBoxLayout(hbox); + recBt = new QPushButton( tr("Record"), hbox ); + hlayout->addWidget(recBt); + resetBt = new QPushButton( tr("Reset"), hbox ); + hlayout->addWidget(resetBt); + saveBt = new QPushButton( tr("Save"), hbox ); + hlayout->addWidget(saveBt); + recBt->setFixedWidth( 100 ); + resetBt->setFixedWidth( 100 ); + saveBt->setFixedWidth( 100 ); + timeDpy = new QLabel( "00:00", hbox ); + hlayout->addWidget(timeDpy); + recLED = new QLabel( hbox ); + hlayout->addWidget(recLED); + recLED->setPixmap( recOff ); + timeDpy->setMargin( 5 ); + connect( recBt, SIGNAL(clicked()), this, SLOT(toggleRecord()) ); + connect( resetBt, SIGNAL(clicked()), this, SLOT(reset()) ); + connect( saveBt, SIGNAL(clicked()), this, SLOT(save()) ); + elapsed = 0; + vlayout->setMargin( 5 ); + vlayout->setSpacing( 5 ); + haveMpeg = detectPpmtoMpegCommand(); + mpegSave = new QCheckBox( tr("Save in MPEG format (requires netpbm package installed)"), this ); + vlayout->addWidget(mpegSave); + mpegSave->setChecked( haveMpeg ); + mpegSave->setEnabled( haveMpeg ); + savingAsMpeg = haveMpeg; + QWidget *hbox2 = new QWidget( this ); + vlayout->addWidget(hbox2); + QHBoxLayout *hlayout2 = new QHBoxLayout( hbox2 ); + statusText = new QLabel( tr("Click record to begin recording."), hbox2 ); + hlayout2->addWidget(statusText); + progressBar = new QProgressBar( hbox2 ); + progressBar->setValue( 0 ); + hlayout2->addWidget(progressBar); + progressBar->hide(); +} + +AnimationSaveWidget::~AnimationSaveWidget() +{ + // clean up + removeTemporaryFiles(); + delete animation; +} + +// returns true if we have ppmtompeg command, else returns false +bool AnimationSaveWidget::detectPpmtoMpegCommand() +{ + // search the PATH for the ppmtompeg command to test we can record to mpeg + QStringList paths = QString(::getenv("PATH")).split(":"); + for ( int i = 0; i < paths.count(); i++ ) + if ( QFile::exists( paths[i] + "/" + "ppmtompeg" ) ) + return true; + return false; +} + +void AnimationSaveWidget::timerEvent( QTimerEvent *te ) +{ + QString str; + + // Recording timer + if ( te->timerId() == timerId ) { + + // Add a frame to the animation + if ( savingAsMpeg && view ) + view->image().save( str.sprintf("/tmp/qvfb_tmp_image_%04d.ppm", imageNum), "PPM"); + else if ( animation && view ) + animation->appendFrame(view->image());//QPoint(0,0)); + imageNum++; + + // Update the display of number of seconds that have been recorded. + int tmMsec = tm.elapsed(); + timeDpy->setText( str.sprintf("%02d:%02d", tmMsec/60000, (tmMsec%60000)/1000) ); + QObject::timerEvent( te ); + + // Make the recording LED blink + static int tick = 0; + static bool on = false; + if ( tick > 10 ) { + tick = 0; + if ( on ) + recLED->setPixmap( recOff ); + else + recLED->setPixmap( recOn ); + on = !on; + } + tick++; + } + + // Saving progress timer + if ( te->timerId() == progressTimerId ) { + // Parse output log file to work out the encoding progress. + QFile f("/tmp/qvfb_tmp_output.log"); + f.open(QIODevice::ReadOnly); + int largestNum = 0; + bool done = false; + char buffer[1024]; + while ( !f.atEnd() ) { + // example of the output log entries + // During each frame: + // "FRAME 764 (B): I BLOCKS: 0...... + // When complete: + // "======FRAMES READ: 766" + f.readLine(buffer, 1024); + str = QString(buffer); + if ( str.left(6) == "FRAME " ) { + int num = str.mid(6, str.indexOf(QChar(' '), 6) - 6).toInt(); + if ( num > largestNum ) + largestNum = num; + } else if ( str.left(18) == "======FRAMES READ:" ) { + done = true; + } + } + f.close(); + + // Update the progress bar with the frame we are up to + progressBar->setValue( largestNum ); + + // Finished saving + if ( done ) { + progressBar->hide(); + statusText->setText( tr("Finished saving.")); + removeTemporaryFiles(); + killTimer( progressTimerId ); + progressTimerId = -1; + reset(); + } + } +} + +// Takes the saved ppm files and converts them to a mpeg file named filename +void AnimationSaveWidget::convertToMpeg(QString filename) +{ + recLED->setPixmap( recOff ); + killTimer( timerId ); + + progressBar->show(); + progressBar->setRange( 0, imageNum ); + progressBar->setValue( 0 ); + + // Build parameter file required by ppmtompeg + QFile file("/tmp/qvfb_tmp_ppmtompeg.params"); + if ( file.open( QIODevice::WriteOnly ) ) { + QTextStream t( &file ); + t << "PATTERN IBBPBBPBBPBBPBB\n"; + t << "OUTPUT " << filename << "\n"; + t << "INPUT_DIR /tmp\n"; + t << "INPUT\n"; + QString str; + str = str.sprintf("%04d", imageNum - 1); + t << "qvfb_tmp_image_*.ppm [0000-" << str << "]\n"; + t << "END_INPUT\n"; + t << "BASE_FILE_FORMAT PPM\n"; + t << "INPUT_CONVERT *\n"; + t << "GOP_SIZE 15\n"; + t << "SLICES_PER_FRAME 1\n"; + t << "PIXEL HALF\n"; + t << "RANGE 5\n"; + t << "PSEARCH_ALG LOGARITHMIC\n"; + t << "BSEARCH_ALG SIMPLE\n"; + t << "IQSCALE 1\n"; + t << "PQSCALE 1\n"; + t << "BQSCALE 1\n"; + t << "REFERENCE_FRAME DECODED\n"; + t << "ASPECT_RATIO 1\n"; + t << "FRAME_RATE 24\n"; + t << "BIT_RATE 64000\n"; // Quality + t << "BUFFER_SIZE 2048\n"; + } + file.close(); + + // ### can't use QProcess, not in Qt 2.3 + // ### but it's certainly in Qt 4! use it? + // Execute the ppmtompeg command as a seperate process to do the encoding + pid_t pid = ::fork(); + if ( !pid ) { + // Child process + // redirect stdout to log file + freopen("/tmp/qvfb_tmp_output.log", "w", stdout); + // ppmtompeg tool is from the netpbm package + ::execlp("ppmtompeg", "ppmtompeg", "/tmp/qvfb_tmp_ppmtompeg.params", (void *)0); + exit(0); + } + + // Update the saving progress bar every 200ms + progressTimerId = startTimer( 200 ); +} + +// Cleanup temporary files created during creating a mpeg file +void AnimationSaveWidget::removeTemporaryFiles() +{ + QString str; + for ( int i = 0; i < imageNum; i++ ) + QFile::remove( str.sprintf("/tmp/qvfb_tmp_image_%04d.ppm", i) ); + QFile::remove("/tmp/qvfb_tmp_ppmtompeg.params"); + QFile::remove("/tmp/qvfb_tmp_output.log"); + imageNum = 0; +} + +// toggles between recording and paused (usually when record button clicked) +void AnimationSaveWidget::toggleRecord() +{ + if ( recording ) { + recLED->setPixmap( recOff ); + recBt->setText( tr("Record") ); + statusText->setText( tr("Paused. Click record to resume, or save if done.")); + killTimer( timerId ); + timerId = -1; + elapsed = tm.elapsed(); + } else { + recLED->setPixmap( recOn ); + recBt->setText( tr("Pause") ); + statusText->setText( tr("Recording...")); + tm.start(); + if ( elapsed == 0 ) { + savingAsMpeg = mpegSave->isChecked(); + if ( !savingAsMpeg ) { + delete animation; + animation = new QAnimationWriter("/tmp/qvfb_tmp_animation.mng","MNG"); + animation->setFrameRate(24); + if ( view ) + animation->appendFrame(view->image()); + } + } + tm = tm.addMSecs(-elapsed); + elapsed = 0; + timerId = startTimer(1000 / 24); + } + recording = !recording; +} + +// Reset everything to initial state of not recording +void AnimationSaveWidget::reset() +{ + if ( recording ) { + toggleRecord(); + statusText->setText( tr("Click record to begin recording.")); + removeTemporaryFiles(); + } + progressBar->setValue( 0 ); + timeDpy->setText( "00:00" ); + elapsed = 0; + imageNum = 0; + delete animation; + animation = 0; +} + +// Prompt for filename to save to and put animation in that file +void AnimationSaveWidget::save() +{ + if ( recording ) + toggleRecord(); // pauses + statusText->setText( tr("Saving... ")); + + QString filename; + if ( savingAsMpeg ) { + filename = QFileDialog::getSaveFileName(this, tr("Save animation..."), "", "*.mpg"); + if ( !filename.isNull() ) + convertToMpeg(filename); + } else { + filename = QFileDialog::getSaveFileName(this, tr("Save animation..."), "", "*.mng"); + if (filename.isNull()) { + statusText->setText(tr("Save canceled.")); + } else { + QFile::remove(filename); + bool success = QFile::rename(QLatin1String("/tmp/qvfb_tmp_animation.mng"), + filename); + if (success) { + statusText->setText(tr("Finished saving.")); + reset(); + } else { + statusText->setText(tr("Save failed!")); + } + } + } +} + +QT_END_NAMESPACE + +#include "qvfb.moc" diff --git a/tools/qvfb/qvfb.h b/tools/qvfb/qvfb.h new file mode 100644 index 0000000..90f2a33 --- /dev/null +++ b/tools/qvfb/qvfb.h @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVFB_H +#define QVFB_H + +#include <QMainWindow> +#include <QStringList> +#include "qvfbview.h" + +QT_BEGIN_NAMESPACE + +class QVFbAbstractView; +class QVFbRateDialog; +class QPopupMenu; +class QMenuData; +class QAction; +class Config; +class DeviceSkin; +class QVFb; +class QLabel; +class QMenu; +class QScrollArea; + +class Zoomer : public QWidget { + Q_OBJECT +public: + Zoomer(QVFb* target); + +private slots: + void zoom(int); + +private: + QVFb *qvfb; + QLabel *label; +}; + +class QVFb: public QMainWindow +{ + Q_OBJECT +public: + enum DisplayType { QWS, X11 }; + + QVFb( int display_id, int w, int h, int d, int r, const QString &skin, DisplayType displayType, QWidget *parent = 0, Qt::WindowFlags wflags = 0 ); + ~QVFb(); + + void enableCursor( bool e ); + + QSize sizeHint() const; + +public slots: + void popupMenu(); + +protected slots: + void saveImage(); + void toggleAnimation(); + void toggleCursor(); + void changeRate(); + void setRate(int); + void about(); + + void configure(); + void skinConfigChosen(int i); + void chooseSize(const QSize& sz); + void chooseDepth(int depth, QVFbView::PixelFormat displayFormat); + + void setZoom1(); + void setZoom2(); + void setZoom3(); + void setZoom4(); + void setZoomHalf(); + void setZoom075(); + + void setZoom(); + + void setRot0(); + void setRot90(); + void setRot180(); + void setRot270(); + +public slots: + void setZoom(double); + void setRotation(QVFbView::Rotation); + +protected: + template <typename T> + void createMenu(T *menu); + QMenu* createFileMenu(); + QMenu* createViewMenu(); + QMenu* createHelpMenu(); + +private: + void findSkins(const QString ¤tSkin); + void init( int display_id, int w, int h, int d, int r, const QString& skin ); + DeviceSkin *skin; + double skinscaleH,skinscaleV; + QVFbAbstractView *view; + QVFbAbstractView *secondaryView; + QVFbRateDialog *rateDlg; + QMenu *viewMenu; + QAction *cursorAction; + Config* config; + QStringList skinnames; + QStringList skinfiles; + int currentSkinIndex; + Zoomer *zoomer; + QScrollArea* scroller; + DisplayType displayType; + + int refreshRate; +private slots: + void setGamma400(int n); + void setR400(int n); + void setG400(int n); + void setB400(int n); + void updateGammaLabels(); +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qvfb.pro b/tools/qvfb/qvfb.pro new file mode 100644 index 0000000..85c4d96 --- /dev/null +++ b/tools/qvfb/qvfb.pro @@ -0,0 +1,74 @@ +TEMPLATE = app +CONFIG += qt warn_on uic +TARGET = qvfb +DESTDIR = ../../bin + +!win32:!embedded:!mac:CONFIG += x11 + +target.path=$$[QT_INSTALL_BINS] +INSTALLS += target + +DEPENDPATH = ../../include + +FORMS = config.ui +HEADERS = qvfb.h \ + qvfbview.h \ + qvfbratedlg.h \ + qanimationwriter.h \ + gammaview.h \ + qvfbprotocol.h \ + qvfbshmem.h \ + qvfbmmap.h \ + qvfbhdr.h \ + qlock_p.h \ + qwssignalhandler_p.h + +SOURCES = qvfb.cpp \ + qvfbview.cpp \ + qvfbratedlg.cpp \ + main.cpp \ + qanimationwriter.cpp \ + qvfbprotocol.cpp \ + qvfbshmem.cpp \ + qvfbmmap.cpp \ + qlock.cpp \ + qwssignalhandler.cpp + +include($$QT_SOURCE_TREE/tools/shared/deviceskin/deviceskin.pri) + +contains(QT_CONFIG, opengl) { + QT += opengl +} + +contains(QT_CONFIG, system-png) { + LIBS += -lpng +} else { + INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/libpng +} +contains(QT_CONFIG, system-zlib) { + LIBS += -lz +} else { + INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib +} + +unix:x11 { + HEADERS += qvfbx11view.h \ + x11keyfaker.h \ + qtopiakeysym.h + SOURCES += qvfbx11view.cpp \ + x11keyfaker.cpp + LIBS += -lXtst +} + +RESOURCES += qvfb.qrc \ + ClamshellPhone.qrc \ + PDAPhone.qrc \ + SmartPhone2.qrc \ + SmartPhone.qrc \ + SmartPhoneWithButtons.qrc \ + TouchscreenPhone.qrc \ + Trolltech-Keypad.qrc \ + Trolltech-Touchscreen.qrc \ + PortableMedia.qrc \ + S60-QVGA-Candybar.qrc \ + S60-nHD-Touchscreen.qrc diff --git a/tools/qvfb/qvfb.qrc b/tools/qvfb/qvfb.qrc new file mode 100644 index 0000000..27c39df --- /dev/null +++ b/tools/qvfb/qvfb.qrc @@ -0,0 +1,7 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/res"> + <file>images/logo.png</file> + <file>images/logo-nt.png</file> +</qresource> +</RCC> + diff --git a/tools/qvfb/qvfbmmap.cpp b/tools/qvfb/qvfbmmap.cpp new file mode 100644 index 0000000..d8230f7 --- /dev/null +++ b/tools/qvfb/qvfbmmap.cpp @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfbmmap.h" +#include "qvfbhdr.h" + +#include <QTimer> + +#include <stdlib.h> +#include <unistd.h> +#include <sys/ipc.h> +#include <sys/types.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/sem.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> + +QT_BEGIN_NAMESPACE + +QMMapViewProtocol::QMMapViewProtocol(int displayid, const QSize &s, + int d, QObject *parent) + : QVFbViewProtocol(displayid, parent), hdr(0), dataCache(0), windowId(0) +{ + switch (d) { + case 1: + case 4: + case 8: + case 12: + case 15: + case 16: + case 18: + case 24: + case 32: + break; + default: + qFatal("Unsupported bit depth %d\n", d); + } + + fileName = QString("/tmp/.qtvfb_map-%1").arg(displayid); + + int w = s.width(); + int h = s.height(); + + + kh = new QVFbKeyPipeProtocol(displayid); + mh = new QVFbMouseLinuxTP(displayid); + + int bpl; + if (d < 8) + bpl = (w * d + 7) / 8; + else + bpl = w * ((d + 7) / 8); + + displaySize = bpl * h; + + unsigned char *data; + uint data_offset_value = sizeof(QVFbHeader); + const int page_size = getpagesize(); + if (data_offset_value % page_size) + data_offset_value += page_size - (data_offset_value % page_size); + + dataSize = bpl * h + data_offset_value; + + unlink(fileName.toLocal8Bit().data()); + fd = ::open( fileName.toLocal8Bit().data(), O_CREAT|O_RDWR, 0666 ); + ::lseek(fd, dataSize, SEEK_SET); + ::write(fd, "\0", 1); + if (fd < 0) { + data = (unsigned char *)-1; + } else { + // might need to do something about size? + data = (unsigned char *)mmap(NULL, dataSize, PROT_WRITE | PROT_READ, + MAP_SHARED, fd, 0); + if (data == MAP_FAILED) + data = (unsigned char *)-1; + } + + if ( (long)data == -1 ){ + delete kh; + delete mh; + qFatal( "Cannot attach to mapped file %s", fileName.toLocal8Bit().data()); + } + dataCache = (unsigned char *)malloc(displaySize); + memset(dataCache, 0, displaySize); + memset(data+sizeof(QVFbHeader), 0, displaySize); + + hdr = (QVFbHeader *)data; + hdr->width = w; + hdr->height = h; + hdr->depth = d; + hdr->linestep = bpl; + hdr->numcols = 0; + hdr->dataoffset = data_offset_value; + hdr->update = QRect(); + hdr->brightness = 255; + hdr->windowId = 0; + + mRefreshTimer = new QTimer(this); + connect(mRefreshTimer, SIGNAL(timeout()), this, SLOT(flushChanges())); +} + +QMMapViewProtocol::~QMMapViewProtocol() +{ + munmap((char *)hdr, dataSize); + ::close(fd); + unlink(fileName.toLocal8Bit().constData()); + free(dataCache); + delete kh; + delete mh; +} + +int QMMapViewProtocol::brightness() const +{ + return hdr->brightness; +} + +int QMMapViewProtocol::width() const +{ + return hdr->width; +} + +int QMMapViewProtocol::height() const +{ + return hdr->height; +} + +int QMMapViewProtocol::depth() const +{ + return hdr->depth; +} + +int QMMapViewProtocol::linestep() const +{ + return hdr->linestep; +} + +int QMMapViewProtocol::numcols() const +{ + return hdr->numcols; +} + +QVector<QRgb> QMMapViewProtocol::clut() const +{ + QVector<QRgb> vector(hdr->numcols); + for (int i=0; i < hdr->numcols; ++i) + vector[i] = hdr->clut[i]; + + return vector; +} + +unsigned char *QMMapViewProtocol::data() const +{ + return dataCache; + //return ((unsigned char *)hdr)+hdr->dataoffset; +} + +void QMMapViewProtocol::flushChanges() +{ + // based of dirty rect, copy changes from hdr to hdrcopy + memcpy(dataCache, ((char *)hdr) + hdr->dataoffset, displaySize); + emit displayDataChanged(QRect(0, 0, width(), height())); +} + +void QMMapViewProtocol::setRate(int interval) +{ + if (interval > 0) + return mRefreshTimer->start(1000/interval); + else + mRefreshTimer->stop(); +} + +int QMMapViewProtocol::rate() const +{ + int i = mRefreshTimer->interval(); + if (i > 0) + return 1000/i; + else + return 0; +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qvfbmmap.h b/tools/qvfb/qvfbmmap.h new file mode 100644 index 0000000..5b580ac --- /dev/null +++ b/tools/qvfb/qvfbmmap.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QVFB_MMAP_PROTOCOL_H +#define QVFB_MMAP_PROTOCOL_H + +#include "qvfbprotocol.h" + +QT_BEGIN_NAMESPACE + +class QVFbHeader; +class QTimer; +class QMMapViewProtocol : public QVFbViewProtocol +{ + Q_OBJECT +public: + QMMapViewProtocol(int display_id, const QSize &size, int depth, QObject *parent = 0); + ~QMMapViewProtocol(); + + int width() const; + int height() const; + int depth() const; + int linestep() const; + int numcols() const; + QVector<QRgb> clut() const; + unsigned char *data() const; + int brightness() const; + + void setRate(int); + int rate() const; + +protected slots: + void flushChanges(); + +protected: + QVFbKeyProtocol *keyHandler() const { return kh; } + QVFbMouseProtocol *mouseHandler() const { return mh; } + +private: + QVFbKeyPipeProtocol *kh; + QVFbMouseLinuxTP *mh; + QVFbHeader *hdr; + QString fileName; + int fd; + size_t dataSize; + size_t displaySize; + unsigned char *dataCache; + QTimer *mRefreshTimer; + WId windowId; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qvfbprotocol.cpp b/tools/qvfb/qvfbprotocol.cpp new file mode 100644 index 0000000..08d2973 --- /dev/null +++ b/tools/qvfb/qvfbprotocol.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfbprotocol.h" +#include "qvfbhdr.h" + +#include <QDebug> +#include <QTimer> + +#include <sys/types.h> +#include <sys/stat.h> +#include <math.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef Q_OS_UNIX +#include <unistd.h> +#endif + +QT_BEGIN_NAMESPACE + +QVFbViewProtocol::QVFbViewProtocol(int display_id, QObject *parent) : + QObject(parent), mDisplayId(display_id) { } + +QVFbViewProtocol::~QVFbViewProtocol() {} + +void QVFbViewProtocol::flushChanges() {} + +void QVFbViewProtocol::sendKeyboardData(QString unicode, int keycode, + int modifiers, bool press, bool repeat) +{ + if (keyHandler()) + keyHandler()->sendKeyboardData(unicode, keycode, modifiers, press, repeat); +} + +void QVFbViewProtocol::sendMouseData(const QPoint &pos, int buttons, int wheel) +{ + if (mouseHandler()) + mouseHandler()->sendMouseData(pos, buttons, wheel); +} + +static int openPipe(const char *fileName) +{ + unlink(fileName); + + mkfifo(fileName, 0666); + int fd = ::open(fileName, O_RDWR | O_NDELAY); + return fd; +} + +QVFbKeyPipeProtocol::QVFbKeyPipeProtocol(int display_id) + : QVFbKeyProtocol(display_id) +{ + fileName = QString(QT_VFB_KEYBOARD_PIPE).arg(display_id); + fd = openPipe(fileName.toLocal8Bit().constData()); + + if (fd == -1) + qFatal("Cannot open keyboard pipe %s", fileName.toLocal8Bit().data()); +} + +QVFbKeyPipeProtocol::~QVFbKeyPipeProtocol() +{ + sendKeyboardData(0, 0, 0, true, false); // magic die key + ::close(fd); + unlink(fileName.toLocal8Bit().constData()); +} + +void QVFbKeyPipeProtocol::sendKeyboardData(QString unicode, int keycode, + int modifiers, bool press, bool repeat) +{ + QVFbKeyData kd; + kd.unicode = unicode[0].unicode(); + kd.keycode = keycode; + kd.modifiers = static_cast<Qt::KeyboardModifier>(modifiers); + kd.press = press; + kd.repeat = repeat; + write(fd, &kd, sizeof(QVFbKeyData)); +} + +QVFbMousePipe::QVFbMousePipe(int display_id) + : QVFbMouseProtocol(display_id) +{ + fileName = QString(QT_VFB_MOUSE_PIPE).arg(display_id); + fd = openPipe(fileName.toLocal8Bit().constData()); + + if (fd == -1) + qFatal("Cannot open mouse pipe %s", fileName.toLocal8Bit().data()); +} + +QVFbMousePipe::~QVFbMousePipe() +{ + ::close(fd); + unlink(fileName.toLocal8Bit().constData()); +} + + +void QVFbMousePipe::sendMouseData(const QPoint &pos, int buttons, int wheel) +{ + write(fd, &pos, sizeof(QPoint)); + write(fd, &buttons, sizeof(int)); + write(fd, &wheel, sizeof(int)); +} + +QVFbMouseLinuxTP::QVFbMouseLinuxTP(int display_id) + : QObject(), QVFbMousePipe(display_id), lastPos(-1,-1) +{ + /* the timer is needed because a real touch screen send data as long as + there is pressure. And the linux tp driver will filter, requiring + a minimum of 5 samples before it even registers a press. + */ + repeater = new QTimer(this); + connect(repeater, SIGNAL(timeout()), this, SLOT(repeatLastPress())); +} + +QVFbMouseLinuxTP::~QVFbMouseLinuxTP() +{ +} + + +void QVFbMouseLinuxTP::sendMouseData(const QPoint &pos, int buttons, int) +{ + if (buttons & Qt::LeftButton) { + // press + repeater->start(5); + writeToPipe(pos, 1); + lastPos = pos; + } else { + // release + if (lastPos == QPoint(-1,-1)) + return; /* only send one release */ + repeater->stop(); + writeToPipe(pos, 0); + lastPos = QPoint(-1,-1); + } +} + +void QVFbMouseLinuxTP::writeToPipe(const QPoint &pos, ushort pressure) +{ + ushort v; + write(fd, &pressure, sizeof(ushort)); + v = pos.x(); + write(fd, &v, sizeof(ushort)); + v = pos.y(); + write(fd, &v, sizeof(ushort)); + v = 1; // pad + write(fd, &v, sizeof(ushort)); +} + +void QVFbMouseLinuxTP::repeatLastPress() +{ + writeToPipe(lastPos, 1); +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qvfbprotocol.h b/tools/qvfb/qvfbprotocol.h new file mode 100644 index 0000000..e7b6f63 --- /dev/null +++ b/tools/qvfb/qvfbprotocol.h @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QVFBPROTOCOL_H +#define QVFBPROTOCOL_H + +#include <QImage> +#include <QVector> +#include <QColor> + +QT_BEGIN_NAMESPACE + +class QVFbKeyProtocol; +class QVFbMouseProtocol; +class QVFbViewProtocol : public QObject +{ + Q_OBJECT +public: + QVFbViewProtocol(int display_id, QObject *parent = 0); + + virtual ~QVFbViewProtocol(); + + int id() const { return mDisplayId; } + + void sendKeyboardData(QString unicode, int keycode, + int modifiers, bool press, bool repeat); + void sendMouseData(const QPoint &pos, int buttons, int wheel); + + virtual int width() const = 0; + virtual int height() const = 0; + virtual int depth() const = 0; + virtual int linestep() const = 0; + virtual int numcols() const = 0; + virtual QVector<QRgb> clut() const = 0; + virtual unsigned char *data() const = 0; + virtual int brightness() const = 0; + + virtual void setRate(int) {} +public slots: + virtual void flushChanges(); + +signals: + void displayDataChanged(const QRect &); + void displayEmbedRequested(WId windowId); + +protected: + virtual QVFbKeyProtocol *keyHandler() const = 0; + virtual QVFbMouseProtocol *mouseHandler() const = 0; + +private: + int mDisplayId; +}; + +class QVFbKeyProtocol +{ +public: + QVFbKeyProtocol(int display_id) : mDisplayId(display_id) {} + virtual ~QVFbKeyProtocol() {} + + int id() const { return mDisplayId; } + + virtual void sendKeyboardData(QString unicode, int keycode, + int modifiers, bool press, bool repeat) = 0; + +private: + int mDisplayId; +}; + +class QVFbMouseProtocol +{ +public: + QVFbMouseProtocol(int display_id) : mDisplayId(display_id) {} + virtual ~QVFbMouseProtocol() {} + + int id() const { return mDisplayId; } + + virtual void sendMouseData(const QPoint &pos, int buttons, int wheel) = 0; + +private: + int mDisplayId; +}; + +/* since there is very little variation in input protocols defaults are + provided */ + +class QVFbKeyPipeProtocol : public QVFbKeyProtocol +{ +public: + QVFbKeyPipeProtocol(int display_id); + ~QVFbKeyPipeProtocol(); + + void sendKeyboardData(QString unicode, int keycode, + int modifiers, bool press, bool repeat); + + QString pipeName() const { return fileName; } +private: + int fd; + QString fileName; +}; + +class QVFbMousePipe: public QVFbMouseProtocol +{ +public: + QVFbMousePipe(int display_id); + ~QVFbMousePipe(); + + void sendMouseData(const QPoint &pos, int buttons, int wheel); + + QString pipeName() const { return fileName; } +protected: + int fd; + QString fileName; +}; + +class QTimer; +class QVFbMouseLinuxTP : public QObject, public QVFbMousePipe +{ + Q_OBJECT +public: + QVFbMouseLinuxTP(int display_id); + ~QVFbMouseLinuxTP(); + + void sendMouseData(const QPoint &pos, int buttons, int wheel); + +protected slots: + void repeatLastPress(); + +protected: + void writeToPipe(const QPoint &pos, ushort pressure); + QPoint lastPos; + QTimer *repeater; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qvfbratedlg.cpp b/tools/qvfb/qvfbratedlg.cpp new file mode 100644 index 0000000..594e3f1 --- /dev/null +++ b/tools/qvfb/qvfbratedlg.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfbratedlg.h" +#include <QLayout> +#include <QLabel> +#include <qslider.h> +#include <QPushButton> + +QT_BEGIN_NAMESPACE + +QVFbRateDialog::QVFbRateDialog(int rate, QWidget *parent) + : QDialog(parent) +{ + oldRate = rate; + + QVBoxLayout *tl = new QVBoxLayout(this); + tl->setMargin(5); + + QLabel *label = new QLabel("Target frame rate:", this); + tl->addWidget(label); + + QHBoxLayout *hl = new QHBoxLayout(); + tl->addItem(hl); + rateSlider = new QSlider(Qt::Horizontal); + rateSlider->setMinimum(1); + rateSlider->setMaximum(100); + rateSlider->setPageStep(10); + rateSlider->setValue(rate); + hl->addWidget(rateSlider); + connect(rateSlider, SIGNAL(valueChanged(int)), this, SLOT(rateChanged(int))); + rateLabel = new QLabel(QString("%1fps").arg(rate), this); + hl->addWidget(rateLabel); + + hl = new QHBoxLayout(); + tl->addItem(hl); + QPushButton *pb = new QPushButton("OK", this); + connect(pb, SIGNAL(clicked()), this, SLOT(ok())); + hl->addWidget(pb); + pb = new QPushButton("Cancel", this); + connect(pb, SIGNAL(clicked()), this, SLOT(cancel())); + hl->addWidget(pb); +} + +void QVFbRateDialog::rateChanged(int r) +{ + if (rateSlider->value() != r) + rateSlider->setValue(r); + rateLabel->setText(QString("%1fps").arg(r)); + emit updateRate(r); +} + +void QVFbRateDialog::cancel() +{ + rateChanged(oldRate); + reject(); +} + +void QVFbRateDialog::ok() +{ + oldRate = rateSlider->value(); + accept(); +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qvfbratedlg.h b/tools/qvfb/qvfbratedlg.h new file mode 100644 index 0000000..1611c76 --- /dev/null +++ b/tools/qvfb/qvfbratedlg.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVFBRATEDLG_H +#define QVFBRATEDLG_H + +#include <QDialog> + +QT_BEGIN_NAMESPACE + +class QLabel; +class QSlider; + +class QVFbRateDialog : public QDialog +{ + Q_OBJECT +public: + QVFbRateDialog(int value, QWidget *parent = 0); + +signals: + void updateRate(int r); + +protected slots: + void rateChanged(int r); + void cancel(); + void ok(); + +private: + QLabel *rateLabel; + QSlider *rateSlider; + int oldRate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qvfbshmem.cpp b/tools/qvfb/qvfbshmem.cpp new file mode 100644 index 0000000..d07cd0f --- /dev/null +++ b/tools/qvfb/qvfbshmem.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlock_p.h" + +#include "qvfbshmem.h" +#include "qvfbhdr.h" + +#define QTE_PIPE "QtEmbedded-%1" + +#include <QFile> +#include <QTimer> + +#include <stdlib.h> +#include <unistd.h> +#include <sys/ipc.h> +#include <sys/types.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/sem.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> + +QT_BEGIN_NAMESPACE + +#ifdef Q_WS_QWS +#error qvfb must be compiled with the Qt for X11 package +#endif + +// Get the name of the directory where Qt for Embedded Linux temporary data should +// live. +static QString qws_dataDir(int qws_display_id) +{ + QByteArray dataDir = QString("/tmp/qtembedded-%1").arg(qws_display_id).toLocal8Bit(); + if (mkdir(dataDir, 0700)) { + if (errno != EEXIST) { + qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); + } + } + + struct stat buf; + if (lstat(dataDir, &buf)) + qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData()); + + if (!S_ISDIR(buf.st_mode)) + qFatal("%s is not a directory", dataDir.constData()); + if (buf.st_uid != getuid()) + qFatal("Qt for Embedded Linux data directory is not owned by user %uh", getuid()); + + if ((buf.st_mode & 0677) != 0600) + qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData()); + dataDir += "/"; + + return QString(dataDir); +} + + +static QString displayPipe; +static QString displayPiped; +class DisplayLock +{ +public: + DisplayLock() : qlock(0) { + if (QFile::exists(displayPiped)) { + qlock = new QLock(displayPipe, 'd', false); + qlock->lock(QLock::Read); + } + } + ~DisplayLock() { + if (qlock) { + qlock->unlock(); + delete qlock; + qlock = 0; + } + } +private: + QLock *qlock; +}; + +QShMemViewProtocol::QShMemViewProtocol(int displayid, const QSize &s, + int d, QObject *parent) + : QVFbViewProtocol(displayid, parent), hdr(0), dataCache(0), lockId(-1), + windowId(0) +{ + int w = s.width(); + int h = s.height(); + + QString username = "unknown"; + const char *logname = getenv("LOGNAME"); + if ( logname ) + username = logname; + + QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString(QTE_PIPE).arg(displayid); + int oldPipeSemkey = ftok(oldPipe.toLatin1().constData(), 'd'); + if (oldPipeSemkey != -1) { + int oldPipeLockId = semget(oldPipeSemkey, 0, 0); + if (oldPipeLockId >= 0){ + sembuf sops; + sops.sem_num = 0; + sops.sem_op = 1; + sops.sem_flg = SEM_UNDO; + int rv; + do { + rv = semop(lockId,&sops,1); + } while (rv == -1 && errno == EINTR); + + perror("QShMemViewProtocol::QShMemViewProtocol"); + qFatal("Cannot create lock file as an old version of QVFb has " + "opened %s. Close other QVFb and try again", + oldPipe.toLatin1().constData()); + } + } + + kh = new QVFbKeyPipeProtocol(displayid); + /* should really depend on receiving qt version, but how can + one tell? */ + mh = new QVFbMousePipe(displayid); + + QString mousePipe = mh->pipeName(); + + key_t key = ftok(mousePipe.toLatin1().constData(), 'b'); + + int bpl; + if (d < 8) + bpl = (w * d + 7) / 8; + else + bpl = w * ((d + 7) / 8); + + displaySize = bpl * h; + + unsigned char *data; + uint data_offset_value = sizeof(QVFbHeader); + + int dataSize = bpl * h + data_offset_value; + shmId = shmget(key, dataSize, IPC_CREAT | 0666); + if (shmId != -1) + data = (unsigned char *)shmat(shmId, 0, 0); + else { + struct shmid_ds shm; + shmctl(shmId, IPC_RMID, &shm); + shmId = shmget(key, dataSize, IPC_CREAT | 0666); + if (shmId == -1) { + perror("QShMemViewProtocol::QShMemViewProtocol"); + qFatal("Cannot get shared memory 0x%08x", key); + } + data = (unsigned char *)shmat(shmId, 0, 0); + } + + if ((long)data == -1) { + delete kh; + delete mh; + perror("QShMemViewProtocol::QShMemViewProtocol"); + qFatal("Cannot attach to shared memory %d",shmId); + } + dataCache = (unsigned char *)malloc(displaySize); + memset(dataCache, 0, displaySize); + memset(data+sizeof(QVFbHeader), 0, displaySize); + + hdr = (QVFbHeader *)data; + hdr->width = w; + hdr->height = h; + hdr->depth = d; + hdr->linestep = bpl; + hdr->dataoffset = data_offset_value; + hdr->update = QRect(); + hdr->dirty = 0; + hdr->numcols = 0; + hdr->viewerVersion = QT_VERSION; + hdr->brightness = 255; + hdr->windowId = 0; + + displayPipe = qws_dataDir(displayid) + QString(QTE_PIPE).arg(displayid); + + displayPiped = displayPipe + 'd'; + + + mRefreshTimer = new QTimer(this); + connect(mRefreshTimer, SIGNAL(timeout()), this, SLOT(flushChanges())); +} + +QShMemViewProtocol::~QShMemViewProtocol() +{ + struct shmid_ds shm; + shmdt( (char*)hdr ); + shmctl( shmId, IPC_RMID, &shm ); + free(dataCache); + delete kh; + delete mh; +} + +int QShMemViewProtocol::width() const +{ + return hdr->width; +} + +int QShMemViewProtocol::height() const +{ + return hdr->height; +} + +int QShMemViewProtocol::depth() const +{ + return hdr->depth; +} + +int QShMemViewProtocol::linestep() const +{ + return hdr->linestep; +} + +int QShMemViewProtocol::numcols() const +{ + return hdr->numcols; +} + +QVector<QRgb> QShMemViewProtocol::clut() const +{ + QVector<QRgb> vector(hdr->numcols); + for (int i=0; i < hdr->numcols; ++i) + vector[i]=hdr->clut[i]; + + return vector; +} + +unsigned char *QShMemViewProtocol::data() const +{ + return dataCache; + //return ((unsigned char *)hdr)+hdr->dataoffset; +} + +int QShMemViewProtocol::brightness() const +{ + return hdr->brightness; +} + +void QShMemViewProtocol::flushChanges() +{ + QRect r; + if (hdr->dirty) { + DisplayLock(); + + hdr->dirty = false; + r = hdr->update; + hdr->update = QRect(); + + if (hdr->windowId != windowId) { + windowId = hdr->windowId; + emit displayEmbedRequested(hdr->windowId); + } else if (!hdr->windowId) { + // copy the memory area, for now, be inefficient. + memcpy(dataCache, ((char *)hdr) + hdr->dataoffset, displaySize); + } + } + emit displayDataChanged(r); +} + +void QShMemViewProtocol::setRate(int interval) +{ + if (interval > 0) + return mRefreshTimer->start(1000/interval); + else + mRefreshTimer->stop(); +} + +int QShMemViewProtocol::rate() const +{ + int i = mRefreshTimer->interval(); + if (i > 0) + return 1000/i; + else + return 0; +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qvfbshmem.h b/tools/qvfb/qvfbshmem.h new file mode 100644 index 0000000..166ff07 --- /dev/null +++ b/tools/qvfb/qvfbshmem.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QVFB_SHM_PROTOCOL_H +#define QVFB_SHM_PROTOCOL_H + +#include "qvfbprotocol.h" + +QT_BEGIN_NAMESPACE + +class QVFbHeader; +class QTimer; +class QShMemViewProtocol : public QVFbViewProtocol +{ + Q_OBJECT +public: + QShMemViewProtocol(int display_id, const QSize &size, int depth, QObject *parent = 0); + ~QShMemViewProtocol(); + + int width() const; + int height() const; + int depth() const; + int linestep() const; + int numcols() const; + QVector<QRgb> clut() const; + unsigned char *data() const; + int brightness() const; + + void setRate(int); + int rate() const; + +protected slots: + void flushChanges(); + +protected: + QVFbKeyProtocol *keyHandler() const { return kh; } + QVFbMouseProtocol *mouseHandler() const { return mh; } + +private: + QVFbKeyPipeProtocol *kh; + QVFbMousePipe *mh; + QVFbHeader *hdr; + size_t displaySize; + unsigned char *dataCache; + int lockId; + int shmId; + QTimer *mRefreshTimer; + WId windowId; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qvfbview.cpp b/tools/qvfb/qvfbview.cpp new file mode 100644 index 0000000..53a5360 --- /dev/null +++ b/tools/qvfb/qvfbview.cpp @@ -0,0 +1,824 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfbview.h" +#include "qvfbshmem.h" +#include "qvfbmmap.h" + +#include "qanimationwriter.h" +#include <QApplication> +#include <QPainter> +#include <QImage> +#include <QBitmap> +#include <QMatrix> +#include <QPaintEvent> +#include <QScrollArea> +#include <QFile> +#include <QDebug> + +#ifdef Q_WS_X11 +#include <QX11EmbedContainer> +#include <QHBoxLayout> +#endif + +#include <stdlib.h> +#include <unistd.h> +#include <sys/ipc.h> +#include <sys/types.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/sem.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> + +QT_BEGIN_NAMESPACE + +extern int qvfb_protocol; + +QVFbAbstractView::QVFbAbstractView( QWidget *parent ) +#ifdef QVFB_USE_GLWIDGET + : QGLWidget( parent ) +#else + : QWidget( parent ) +#endif +{ +} + +QVFbAbstractView::~QVFbAbstractView() +{ +} + +QVFbView::QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent) + : QVFbAbstractView(parent), + viewdepth(d), viewFormat(DefaultFormat), rsh(0), gsh(0), bsh(0), rmax(15), gmax(15), bmax(15), + contentsWidth(w), contentsHeight(h), gred(1.0), ggreen(1.0), gblue(1.0), + gammatable(0), refreshRate(30), animation(0), + hzm(0.0), vzm(0.0), mView(0), + emulateTouchscreen(false), emulateLcdScreen(false), rotation(r) +#ifdef Q_WS_X11 + , embedContainer(0) +#endif +{ + switch(qvfb_protocol) { + default: + case 0: + mView = new QShMemViewProtocol(id, QSize(w, h), d, this); + break; + case 1: + mView = new QMMapViewProtocol(id, QSize(w, h), d, this); + break; + } + + connect(mView, SIGNAL(displayDataChanged(const QRect &)), + SLOT(refreshDisplay(const QRect &))); +#ifdef Q_WS_X11 + connect(mView, SIGNAL(displayEmbedRequested(WId)), + this, SLOT(embedDisplay(WId))); +#endif + + setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat); + setMouseTracking(true); + setFocusPolicy(Qt::StrongFocus); + setAttribute(Qt::WA_NoSystemBackground); + + setZoom(1.0,1.0); + + setGamma(1.0,1.0,1.0); + mView->setRate(30); +} + +QVFbView::~QVFbView() +{ + stopAnimation(); + sendKeyboardData(0, 0, 0, true, false); // magic die key +#ifdef Q_WS_X11 + delete embedContainer; +#endif +} + +QSize QVFbView::sizeHint() const +{ + return QSize(contentsWidth, contentsHeight); +} + +void QVFbView::setRate(int i) +{ + mView->setRate(i); +} + +void QVFbView::setGamma(double gr, double gg, double gb) +{ + gred = gr; ggreen = gg; gblue = gb; + + switch (viewdepth) { + case 12: + rsh = 12; + gsh = 7; + bsh = 1; + rmax = 15; + gmax = 15; + bmax = 15; + break; + case 15: + rsh = 10; + gsh = 5; + bsh = 0; + rmax = 31; + gmax = 31; + bmax = 31; + break; + case 16: + rsh = 11; + gsh = 5; + bsh = 0; + rmax = 31; + gmax = 63; + bmax = 31; + break; + case 18: + rsh = 12; + gsh = 6; + bsh = 0; + rmax = 63; + gmax = 63; + bmax = 63; + break; + case 24: + case 32: + rsh = 16; + gsh = 8; + bsh = 0; + rmax = 255; + gmax = 255; + bmax = 255; + } + int mm = qMax(rmax,qMax(gmax,bmax))+1; + if (gammatable) + delete [] gammatable; + gammatable = new QRgb[mm]; + for (int i=0; i<mm; i++) { + int r = int(pow(i,gr)*255/rmax); + int g = int(pow(i,gg)*255/gmax); + int b = int(pow(i,gb)*255/bmax); + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + gammatable[i] = qRgb(r,g,b); +//qDebug("%d: %d,%d,%d",i,r,g,b); + } + + mView->flushChanges(); +} + +void QVFbView::getGamma(int i, QRgb& rgb) +{ + if (i > 255) i = 255; + if (i < 0) i = 0; + rgb = qRgb(qRed(gammatable[i*rmax/255]), + qGreen(gammatable[i*rmax/255]), + qBlue(gammatable[i*rmax/255])); +} + +int QVFbView::displayId() const +{ + return mView->id(); +} + +int QVFbView::displayWidth() const +{ + return mView->width(); +} + +int QVFbView::displayHeight() const +{ + return mView->height(); +} + +int QVFbView::displayDepth() const +{ + return viewdepth; +} + +QVFbView::PixelFormat QVFbView::displayFormat() const +{ + return viewFormat; +} + +QVFbView::Rotation QVFbView::displayRotation() const +{ + return rotation; +} + +void QVFbView::setZoom(double hz, double vz) +{ + if (hzm != hz || vzm != vz) { + hzm = hz; + vzm = vz; + mView->flushChanges(); + + contentsWidth = int(displayWidth()*hz); + contentsHeight = int(displayHeight()*vz); + if (rotation & 1) + qSwap(contentsWidth,contentsHeight); + resize(contentsWidth, contentsHeight); + + if (isVisible()) { + updateGeometry(); + qApp->sendPostedEvents(); + topLevelWidget()->adjustSize(); + update(); + } + } +} + +void QVFbView::setRotation(QVFbView::Rotation r) +{ + rotation = r; + // Force update... + double ohzm = hzm; + hzm=0.0; + setZoom(ohzm,vzm); +} + +static QRect mapToDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation) +{ + int x1 = r.x(); + int y1 = r.y(); + int x2 = r.right(); + int y2 = r.bottom(); + int w = s.width(); + int h = s.height(); + switch (rotation) { + case QVFbView::Rot90: + return QRect( + QPoint(y1, w - x1), + QPoint(y2, w - x2)).normalized(); + case QVFbView::Rot180: + return QRect( + QPoint(w - x1, h - y1), + QPoint(w - x2, h - y2)).normalized(); + case QVFbView::Rot270: + return QRect( + QPoint(h - y1, x1), + QPoint(h - y2, x2)).normalized(); + default: + break; + } + return r; +} + +static QRect mapFromDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation) +{ + return mapToDevice(r,s,QVFbView::Rotation(4-(int)rotation)); +} + +void QVFbView::sendMouseData(const QPoint &pos, int buttons, int wheel) +{ + QPoint p = mapToDevice(QRect(pos,QSize(1,1)), QSize(int(width()/hzm), int(height()/vzm)), rotation).topLeft(); + mView->sendMouseData(p, buttons, wheel); +} + +void QVFbView::sendKeyboardData(QString unicode, int keycode, int modifiers, + bool press, bool repeat) +{ + mView->sendKeyboardData(unicode, keycode, modifiers, press, repeat); +} + +void QVFbView::refreshDisplay(const QRect &r) +{ + if (animation) { + if (r.isEmpty()) { + animation->appendBlankFrame(); + } else { + int l; + QImage img = getBuffer(r, l); + animation->appendFrame(img,QPoint(r.x(),r.y())); + } + } + if (!r.isNull()) { + if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1 + update(mapFromDevice(r, QSize(displayWidth(), displayHeight()), rotation)); + else + update(); + } +} + +static void dim(QRgb* rgb, int n, int brightness) +{ + uchar* b = (uchar*)rgb; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + b++; +#endif + while (n--) { + b[0] = (uint)b[0] * brightness / 255; + b[1] = (uint)b[1] * brightness / 255; + b[2] = (uint)b[2] * brightness / 255; + b += 4; + } +} + +QImage QVFbView::getBuffer(const QRect &r, int &leading) const +{ + const int brightness = mView->brightness(); + if ( brightness == 0 ) { + QImage img(r.size(),QImage::Format_RGB32); + img.fill(0); + leading = 0; + return img; + } + + static QByteArray buffer; + + const int requiredSize = r.width() * r.height() * 4; + + QImage img; + leading = 0; + + switch (viewdepth) { + case 1: { + if (requiredSize > buffer.size()) + buffer.resize(requiredSize); + + // XXX: hw: replace by drawhelper functionality + + const int pixelsPerByte = 8; + quint8 *src = reinterpret_cast<quint8*>(mView->data()) + + r.y() * mView->linestep() + r.x() / pixelsPerByte; + const int align = qMin(r.width(), (8 - (r.x() & 7)) & 7); + const int doAlign = (align > 0 ? 1 : 0); + const int tail = qMin(r.width(), (r.width() - align) & 7); + const int doTail = (tail > 0 ? 1 : 0); + const int width8 = (r.width() - align) / pixelsPerByte; + const int stride = mView->linestep() - (width8 + doAlign); + + uchar *b = reinterpret_cast<uchar*>(buffer.data()); + img = QImage(b, r.width(), r.height(), QImage::Format_RGB32); + for (int y = 0; y < r.height(); ++y) { + quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y)); + quint8 c; + + if (doAlign) { + switch (align) { + case 7: c = ((*src & 0x40) >> 6) * 0xff; + *dest++ = qRgb(c, c, c); + case 6: c = ((*src & 0x20) >> 5) * 0xff; + *dest++ = qRgb(c, c, c); + case 5: c = ((*src & 0x10) >> 4) * 0xff; + *dest++ = qRgb(c, c, c); + case 4: c = ((*src & 0x08) >> 3) * 0xff; + *dest++ = qRgb(c, c, c); + case 3: c = ((*src & 0x04) >> 2) * 0xff; + *dest++ = qRgb(c, c, c); + case 2: c = ((*src & 0x02) >> 1) * 0xff; + *dest++ = qRgb(c, c, c); + case 1: c = ((*src & 0x01)) * 0xff; + *dest++ = qRgb(c, c, c); + } + ++src; + } + for (int i = 0; i < width8; ++i) { + c = ((*src & 0x80) >> 7) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x40) >> 6) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x20) >> 5) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x10) >> 4) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x08) >> 3) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x04) >> 2) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x02) >> 1) * 0xff; + *dest++ = qRgb(c, c, c); + c = ((*src & 0x01)) * 0xff; + *dest++ = qRgb(c, c, c); + + ++src; + } + if (doTail) { + switch (tail) { + case 7: c = ((*src & 0x02) >> 1) * 0xff; + dest[6] = qRgb(c, c, c); + case 6: c = ((*src & 0x04) >> 2) * 0xff; + dest[5] = qRgb(c, c, c); + case 5: c = ((*src & 0x08) >> 3) * 0xff; + dest[4] = qRgb(c, c, c); + case 4: c = ((*src & 0x10) >> 4) * 0xff; + dest[3] = qRgb(c, c, c); + case 3: c = ((*src & 0x20) >> 5) * 0xff; + dest[2] = qRgb(c, c, c); + case 2: c = ((*src & 0x40) >> 6) * 0xff; + dest[1] = qRgb(c, c, c); + case 1: c = ((*src & 0x80) >> 7) * 0xff; + dest[0] = qRgb(c, c, c); + } + } + src += stride; + } + break; + } + case 4: { + if (requiredSize > buffer.size()) + buffer.resize(requiredSize); + + // XXX: hw: replace by drawhelper functionality + + const int pixelsPerByte = 2; + const int doAlign = r.x() & 1; + const int doTail = (r.width() - doAlign) & 1; + const int width8 = (r.width() - doAlign) / pixelsPerByte; + + uchar *b = reinterpret_cast<uchar*>(buffer.data()); + img = QImage(b, r.width(), r.height(), QImage::Format_RGB32); + for (int y = 0; y < r.height(); ++y) { + const quint8 *sptr = mView->data() + + (r.y() + y) * mView->linestep() + + r.x() / pixelsPerByte; + quint32 *dptr = reinterpret_cast<quint32*>(img.scanLine(y)); + + if (doAlign) { + quint8 c = (*sptr++ & 0x0f); + c |= (c << 4); + *dptr++ = qRgb(c, c, c); + } + + for (int i = 0; i < width8; ++i) { + quint8 c1 = (*sptr >> 4); + quint8 c2 = (*sptr & 0x0f); + c1 |= (c1 << 4); + c2 |= (c2 << 4); + *dptr++ = qRgb(c1, c1, c1); + *dptr++ = qRgb(c2, c2, c2); + ++sptr; + } + + if (doTail) { + quint8 c = *sptr >> 4; + c |= (c << 4); + *dptr = qRgb(c, c, c); + } + } + break; + } + case 12: + img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2), + r.width(), r.height(), mView->linestep(), + QImage::Format_RGB444); + break; + case 15: + img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2), + r.width(), r.height(), mView->linestep(), + QImage::Format_RGB555); + break; + case 16: + img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2), + r.width(), r.height(), mView->linestep(), + QImage::Format_RGB16); + break; + case 18: + img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3), + r.width(), r.height(), mView->linestep(), + QImage::Format_RGB666); + break; + case 24: + img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3), + r.width(), r.height(), mView->linestep(), + QImage::Format_RGB888); + break; + case 32: + img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 4), + r.width(), r.height(), mView->linestep(), + viewFormat == ARGBFormat ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); + break; + case 8: + img = QImage(mView->data() + r.y() * mView->linestep() + r.x(), + r.width(), r.height(), mView->linestep(), + QImage::Format_Indexed8); + img.setColorTable(mView->clut()); + if (img.numColors() <= 0) + img = QImage(); + break; + } + + if ( brightness != 255 ) { + if (img.format() == QImage::Format_Indexed8) { + QVector<QRgb> c = img.colorTable(); + dim(c.data(),c.count(),brightness); + img.setColorTable(c); + } else { + if ( img.format() != QImage::Format_ARGB32_Premultiplied ) + img = img.convertToFormat(QImage::Format_RGB32); + + // NOTE: calling bits() may change numBytes(), so do not + // pass them as parameters (which are evaluated right-to-left). + QRgb *b = (QRgb*)img.bits(); + int n = img.numBytes()/4; + dim(b,n,brightness); + } + } + + return img; +} + +static int findMultiple(int start, double m, int limit, int step) +{ + int r = start; + while (r != limit) { + if (int(int(r * m)/m) == r) + break; + r += step; + } + return r; +} + +void QVFbView::drawScreen(const QRect &rect) +{ + QRect r = QRect(0, 0, mView->width(), mView->height()); + + if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1 + r &= rect; + + if (int(hzm) != hzm || int(vzm) != vzm) { + r.setLeft(findMultiple(r.left(),hzm,0,-1)); + r.setTop(findMultiple(r.top(),vzm,0,-1)); + int w = findMultiple(r.width(),hzm,mView->width(),1); + int h = findMultiple(r.height(),vzm,mView->height(),1); + r.setRight(r.left()+w-1); + r.setBottom(r.top()+h-1); + } + + int leading; + const QImage img = getBuffer(r, leading); + + QPixmap pm; + if (hzm == 1.0 && vzm == 1.0) { + pm = QPixmap::fromImage(img); + } else if (emulateLcdScreen && hzm == 3.0 && vzm == 3.0) { + QImage img2(img.width()*3, img.height(), QImage::Format_RGB32); + for (int row = 0; row < img2.height(); row++) { + QRgb *dptr = (QRgb*)img2.scanLine(row); + QRgb *sptr = (QRgb*)img.scanLine(row); + for (int col = 0; col < img.width(); col++) { + QRgb s = *sptr++; + *dptr++ = qRgb(qRed(s),0,0); + *dptr++ = qRgb(0,qGreen(s),0); + *dptr++ = qRgb(0,0,qBlue(s)); + } + } + QMatrix m; + m.scale(1.0, 3.0); + pm = QPixmap::fromImage(img2); + pm = pm.transformed(m); + } else if (int(hzm) == hzm && int(vzm) == vzm) { + QMatrix m; + m.scale(hzm,vzm); + pm = QPixmap::fromImage(img); + pm = pm.transformed(m); + } else { + pm = QPixmap::fromImage(img.scaled(int(img.width()*hzm),int(img.height()*vzm), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + } + + int x1 = r.x(); + int y1 = r.y(); + int leadingX = leading; + int leadingY = 0; + + // Do the rotation thing + int rotX1 = mView->width() - x1 - img.width(); + int rotY1 = mView->height() - y1 - img.height(); + int rotLeadingX = (leading) ? mView->width() - leadingX - img.width() : 0; + int rotLeadingY = 0; + switch (rotation) { + case Rot0: + break; + case Rot90: + leadingY = leadingX; + leadingX = rotLeadingY; + y1 = x1; + x1 = rotY1; + break; + case Rot180: + leadingX = rotLeadingX; + leadingY = leadingY; + x1 = rotX1; + y1 = rotY1; + break; + case Rot270: + leadingX = leadingY; + leadingY = rotLeadingX; + x1 = y1; + y1 = rotX1; + break; + default: + break; + } + x1 = int(x1*hzm); + y1 = int(y1*vzm); + leadingX = int(leadingX*hzm); + leadingY = int(leadingY*vzm); + if (rotation != 0) { + QMatrix m; + m.rotate(rotation * 90.0); + pm = pm.transformed(m); + } + + QPainter p(this); + if (viewFormat == ARGBFormat) { + QPixmap bg(":/res/images/logo-nt.png"); + p.fillRect(x1,y1,pm.width(), pm.height(), QBrush(bg)); + } + p.drawPixmap(x1, y1, pm, leadingX, leadingY, pm.width(), pm.height()); +} + +//bool QVFbView::eventFilter(QObject *obj, QEvent *e) +//{ +// if (obj == this && +// (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut)) +// return true; +// +// return QWidgetView::eventFilter(obj, e); +//} + +void QVFbView::paintEvent(QPaintEvent *e) +{ + drawScreen(mapToDevice(e->rect(),QSize(int(width()/hzm), int(height()/vzm)),rotation)); +} + +void QVFbView::mousePressEvent(QMouseEvent *e) +{ + sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); +} + +void QVFbView::contextMenuEvent(QContextMenuEvent*) +{ + +} + +void QVFbView::mouseDoubleClickEvent(QMouseEvent *e) +{ + sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); +} + +void QVFbView::mouseReleaseEvent(QMouseEvent *e) +{ + sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); +} + +void QVFbView::skinMouseEvent(QMouseEvent *e) +{ + sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); +} + +void QVFbView::mouseMoveEvent(QMouseEvent *e) +{ + if (!emulateTouchscreen || (e->buttons() & Qt::MouseButtonMask)) + sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0); +} + +void QVFbView::wheelEvent(QWheelEvent *e) +{ + if (!e) + return; + sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), e->delta()); +} + +void QVFbView::setTouchscreenEmulation(bool b) +{ + emulateTouchscreen = b; +} + +void QVFbView::setLcdScreenEmulation(bool b) +{ + emulateLcdScreen = b; +} + +void QVFbView::setViewFormat(PixelFormat f) +{ + if (viewFormat == f) + return; + viewFormat = f; + setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat); +} + +#ifdef Q_WS_X11 +void QVFbView::embedDisplay(WId windowId) +{ + if (windowId == 0) { + delete embedContainer; + embedContainer = 0; + return; + } + + if (!embedContainer) { + embedContainer = new QX11EmbedContainer(this); + embedContainer->setGeometry(rect()); + embedContainer->show(); + } + embedContainer->embedClient(windowId); +} +#endif + +bool QVFbView::event(QEvent *e) +{ + if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { + QKeyEvent *ke = static_cast<QKeyEvent*>(e); + sendKeyboardData(ke->text(), ke->key(), + ke->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier), + ke->type() == QEvent::KeyPress, ke->isAutoRepeat()); + ke->accept(); + return true; + } + return QVFbAbstractView::event(e); +} + +void QVFbView::keyPressEvent(QKeyEvent *e) +{ + sendKeyboardData(e->text(), e->key(), + e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier), + true, e->isAutoRepeat()); +} + +void QVFbView::keyReleaseEvent(QKeyEvent *e) +{ + sendKeyboardData(e->text(), e->key(), + e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier), + false, e->isAutoRepeat()); +} + + +QImage QVFbView::image() const +{ + int l; + QImage r = getBuffer(QRect(0, 0, mView->width(), mView->height()), l).copy(); + return r; +} + +void QVFbView::startAnimation(const QString& filename) +{ + delete animation; + animation = new QAnimationWriter(filename,"MNG"); + animation->setFrameRate(refreshRate); + animation->appendFrame(QImage(mView->data(), + mView->width(), mView->height(), QImage::Format_RGB32)); +} + +void QVFbView::stopAnimation() +{ + delete animation; + animation = 0; +} + + +void QVFbView::skinKeyPressEvent(int code, const QString& text, bool autorep) +{ + QKeyEvent e(QEvent::KeyPress,code,0,text,autorep); + keyPressEvent(&e); +} + +void QVFbView::skinKeyReleaseEvent(int code, const QString& text, bool autorep) +{ + QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep); + keyReleaseEvent(&e); +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qvfbview.h b/tools/qvfb/qvfbview.h new file mode 100644 index 0000000..d533613 --- /dev/null +++ b/tools/qvfb/qvfbview.h @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVFBVIEW_H +#define QVFBVIEW_H + +//#ifdef QT_NO_OPENGL +#include <QWidget> +//#else +//#define QVFB_USE_GLWIDGET +//#include <QGLWidget> +//#endif + +QT_BEGIN_NAMESPACE + +class QImage; +class QTimer; +class QAnimationWriter; +struct QVFbHeader; +class QVFbViewProtocol; +class QX11EmbedContainer; + +class QVFbAbstractView : +#ifdef QVFB_USE_GLWIDGET + public QGLWidget +#else + public QWidget +#endif +{ + Q_OBJECT +public: + enum Rotation { Rot0, Rot90, Rot180, Rot270 }; + enum PixelFormat { DefaultFormat, GrayscaleFormat, RGBFormat, ARGBFormat }; + QVFbAbstractView( QWidget *parent = 0); + virtual ~QVFbAbstractView(); + + virtual int displayId() const = 0; + virtual int displayWidth() const = 0; + virtual int displayHeight() const = 0; + virtual int displayDepth() const = 0; + virtual PixelFormat displayFormat() const { return DefaultFormat; } + virtual Rotation displayRotation() const = 0; + + virtual void setGamma(double gr, double gg, double gb) = 0; + virtual double gammaRed() const = 0; + virtual double gammaGreen() const = 0; + virtual double gammaBlue() const = 0; + virtual void getGamma(int i, QRgb& rgb) = 0; + + virtual bool touchScreenEmulation() const = 0; + virtual bool lcdScreenEmulation() const = 0; + virtual int rate() = 0; + virtual bool animating() const = 0; + virtual QImage image() const = 0; + virtual void setRate(int) = 0; + + virtual double zoomH() const = 0; + virtual double zoomV() const = 0; + +public slots: + virtual void setTouchscreenEmulation( bool ) = 0; + virtual void setLcdScreenEmulation( bool ) = 0; + virtual void setZoom( double, double ) = 0; + virtual void setRotation(Rotation) = 0; + virtual void startAnimation( const QString& ) = 0; + virtual void stopAnimation() = 0; + virtual void skinKeyPressEvent( int code, const QString& text, bool autorep=FALSE ) = 0; + virtual void skinKeyReleaseEvent( int code, const QString& text, bool autorep=FALSE ) = 0; + virtual void setViewFormat(PixelFormat) {} + virtual void embedDisplay(WId) {} +}; + +class QVFbView : public QVFbAbstractView +{ + Q_OBJECT +public: + QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent = 0); + virtual ~QVFbView(); + + int displayId() const; + int displayWidth() const; + int displayHeight() const; + int displayDepth() const; + PixelFormat displayFormat() const; + Rotation displayRotation() const; + + bool touchScreenEmulation() const { return emulateTouchscreen; } + bool lcdScreenEmulation() const { return emulateLcdScreen; } + int rate() { return refreshRate; } + bool animating() const { return !!animation; } + QImage image() const; + + void setGamma(double gr, double gg, double gb); + double gammaRed() const { return gred; } + double gammaGreen() const { return ggreen; } + double gammaBlue() const { return gblue; } + void getGamma(int i, QRgb& rgb); + void skinMouseEvent(QMouseEvent *e); + + double zoomH() const { return hzm; } + double zoomV() const { return vzm; } + + QSize sizeHint() const; + void setRate(int); + +public slots: + void setTouchscreenEmulation(bool); + void setLcdScreenEmulation(bool); + void setZoom(double, double); + void setRotation(Rotation); + void startAnimation(const QString&); + void stopAnimation(); + void skinKeyPressEvent(int code, const QString& text, bool autorep=FALSE); + void skinKeyReleaseEvent(int code, const QString& text, bool autorep=FALSE); + void setViewFormat(PixelFormat); +#ifdef Q_WS_X11 + void embedDisplay(WId id); +#endif + +protected slots: + void refreshDisplay(const QRect &); + +protected: + QImage getBuffer(const QRect &r, int &leading) const; + void drawScreen(const QRect &r); + void sendMouseData(const QPoint &pos, int buttons, int wheel); + void sendKeyboardData(QString unicode, int keycode, int modifiers, + bool press, bool repeat); + //virtual bool eventFilter(QObject *obj, QEvent *e); + virtual void paintEvent(QPaintEvent *pe); + virtual void contextMenuEvent(QContextMenuEvent *e); + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseDoubleClickEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e); + virtual void mouseMoveEvent(QMouseEvent *e); + virtual void wheelEvent(QWheelEvent *e); + virtual void keyPressEvent(QKeyEvent *e); + virtual void keyReleaseEvent(QKeyEvent *e); + virtual bool event(QEvent *event); + +private: + void setDirty(const QRect&); + int viewdepth; // "faked" depth + PixelFormat viewFormat; + int rsh; + int gsh; + int bsh; + int rmax; + int gmax; + int bmax; + int contentsWidth; + int contentsHeight; + double gred, ggreen, gblue; + QRgb* gammatable; + + int refreshRate; + QAnimationWriter *animation; + double hzm,vzm; + QVFbViewProtocol *mView; + bool emulateTouchscreen; + bool emulateLcdScreen; + Rotation rotation; + +#ifdef Q_WS_X11 + QX11EmbedContainer *embedContainer; +#endif +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/qvfbx11view.cpp b/tools/qvfb/qvfbx11view.cpp new file mode 100644 index 0000000..cad0b2c --- /dev/null +++ b/tools/qvfb/qvfbx11view.cpp @@ -0,0 +1,388 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved. +** +** This file is part of the Phone Edition of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvfbx11view.h" +#include "x11keyfaker.h" +#include <qevent.h> +#include <QX11Info> +#include <QTimer> +#include <QProcess> +#include <QDebug> +#include <QUuid> +#include <QDataStream> +#include <QTemporaryFile> +#include <X11/Xlib.h> + +QT_BEGIN_NAMESPACE + +QVFbX11View::QVFbX11View + (int id, int w, int h, int d, Rotation r, QWidget *parent) + : QVFbAbstractView(parent) +{ + this->id = id; + this->w = w; + this->h = h; + this->d = d; + this->rotation = r; + this->gr = 1.0; + this->gg = 1.0; + this->gb = 1.0; + this->touchscreen = false; + this->lcd = false; + this->keyFaker = 0; + this->xnest = 0; + this->serverAuthFile = 0; + this->shutdown = false; + + // Try to find Xephyr, as it is better than Xnest in many ways. + if (QFile::exists("/usr/bin/Xephyr")) + xserver = "/usr/bin/Xephyr"; + else if (QFile::exists("/usr/local/bin/Xephyr")) + xserver = "/usr/local/bin/Xephyr"; + else if (QFile::exists("/usr/X11R6/bin/Xephyr")) + xserver = "/usr/X11R6/bin/Xephyr"; + else + xserver = "Xnest"; +} + +QVFbX11View::~QVFbX11View() +{ + shutdown = true; + if (xnest) { + xnest->terminate(); + xnestStopped(); + } +} + +int QVFbX11View::displayId() const +{ + return id; +} + +int QVFbX11View::displayWidth() const +{ + return ( (int)rotation & 0x01 ) ? h : w; +} + +int QVFbX11View::displayHeight() const +{ + return ( (int)rotation & 0x01 ) ? w : h; +} + +int QVFbX11View::displayDepth() const +{ + return d; +} + +QVFbX11View::Rotation QVFbX11View::displayRotation() const +{ + return rotation; +} + +void QVFbX11View::skinKeyPressEvent(int code, const QString&, bool) +{ + if (keyFaker) + keyFaker->sendKeyEvent(code, true); +} + +void QVFbX11View::skinKeyReleaseEvent(int code, const QString&, bool) +{ + if (keyFaker) + keyFaker->sendKeyEvent(code, false); +} + +void QVFbX11View::setGamma(double gr, double gg, double gb) +{ + // We remember the values, but don't do anything with them. + this->gr = gr; + this->gg = gg; + this->gb = gb; +} + +double QVFbX11View::gammaRed() const +{ + return gr; +} + +double QVFbX11View::gammaGreen() const +{ + return gg; +} + +double QVFbX11View::gammaBlue() const +{ + return gb; +} + +void QVFbX11View::getGamma(int, QRgb& rgb) +{ + rgb = qRgb(255, 255, 255); +} + +bool QVFbX11View::touchScreenEmulation() const +{ + return touchscreen; +} + +bool QVFbX11View::lcdScreenEmulation() const +{ + return lcd; +} + +int QVFbX11View::rate() +{ + // We don't support refresh rates, so return a default value. + return 30; +} + +bool QVFbX11View::animating() const +{ + // We don't support animation. + return false; +} + +QImage QVFbX11View::image() const +{ + // We don't support image capture. + return QImage(); +} + +void QVFbX11View::setRate(int) +{ + // We don't support rate adjustments. +} + + +double QVFbX11View::zoomH() const +{ + // Zoom is not possible with Xnest. + return 1.0; +} + +double QVFbX11View::zoomV() const +{ + // Zoom is not possible with Xnest. + return 1.0; +} + +QSize QVFbX11View::sizeHint() const +{ + return QSize(w, h); +} + +void QVFbX11View::setTouchscreenEmulation( bool flag ) +{ + touchscreen = flag; +} + +void QVFbX11View::setLcdScreenEmulation( bool flag ) +{ + lcd = flag; +} + +void QVFbX11View::setZoom( double, double ) +{ + // Zoom is not possible with Xnest. +} + +void QVFbX11View::setRotation( Rotation ) +{ + // Rotation is not possible with Xnest. +} + +void QVFbX11View::startAnimation( const QString& ) +{ + // Animation is not supported. +} + +void QVFbX11View::stopAnimation() +{ + // Animation is not supported. +} + +// Generate a 16-byte magic cookie string. +static QString generateMagicCookie() +{ + static const char hexchars[] = "0123456789abcdef"; + QUuid uuid = QUuid::createUuid(); + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + stream << uuid; + QString value; + foreach ( char ch, ba ) { + value += QChar( hexchars[(ch >> 4) & 0x0F] ); + value += QChar( hexchars[ch & 0x0F] ); + } + return value; +} + +void QVFbX11View::showEvent(QShowEvent *e) +{ + if (!xnest) + startXnest(); + QWidget::showEvent(e); +} + +void QVFbX11View::keyPressEvent(QKeyEvent *e) +{ + if (keyFaker) + keyFaker->sendKeyEvent(e->key(), true); + QWidget::keyPressEvent(e); +} + +void QVFbX11View::keyReleaseEvent(QKeyEvent *e) +{ + if (keyFaker) + keyFaker->sendKeyEvent(e->key(), false); + QWidget::keyReleaseEvent(e); +} + +void QVFbX11View::startXnest() +{ + // Add authentication credentials to the XAUTHORITY file. + QString cookie = generateMagicCookie(); + QStringList xauthargs; + xauthargs += "add"; + xauthargs += ":" + QString::number(displayId()); + xauthargs += "MIT-MAGIC-COOKIE-1"; + xauthargs += cookie; + if (QProcess::execute("xauth", xauthargs) != 0) + qWarning() << "xauth: failed to add Xnest client authentication credentials"; + + // Write the credentials to another authentication file for the server. + serverAuthFile = new QTemporaryFile(this); + QString authFilename; + if (serverAuthFile->open()) { + authFilename = serverAuthFile->fileName(); + serverAuthFile->close(); + xauthargs.clear(); + xauthargs += "-f"; + xauthargs += authFilename; + xauthargs += "add"; + xauthargs += ":" + QString::number(displayId()); + xauthargs += "MIT-MAGIC-COOKIE-1"; + xauthargs += cookie; + if (QProcess::execute("xauth", xauthargs) != 0) + qWarning() << "xauth: failed to add Xnest server authentication credentials"; + } + + // Create a raw X11 window to act as the Xnest's root window. + // We cannot use winId() directly because qvfb is already + // selecting for events that Xnest wants to select for. + WId root = XCreateSimpleWindow + (QX11Info::display(), winId(), 0, 0, w, h, 0, + BlackPixel(QX11Info::display(), QX11Info::appScreen()), + BlackPixel(QX11Info::display(), QX11Info::appScreen())); + XMapWindow(QX11Info::display(), root); + + // Warn the user if the visual number looks wrong. Xnest expects + // its root window to be on the default visual. + if (QX11Info::appVisual() != DefaultVisual(QX11Info::display(), QX11Info::appScreen())) { + qWarning() << "*** Qt is not using the default visual. Xnest may fail " + "with a BadMatch error."; + qWarning() << "*** If it fails, then restart qvfb with \" -visual" + << DefaultVisual(QX11Info::display(), QX11Info::appScreen()) + ->visualid << "\""; + } + + // Make sure the root window is in the X server before Xnest starts. + XSync(QX11Info::display(), False); + + // Start the Xnest process. + xnest = new QProcess(this); + connect(xnest, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(xnestStopped())); + connect(xnest, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(xnestStopped())); + QStringList args; + args += "-auth"; + args += authFilename; + if (!xserver.contains("Xephyr")) { + args += "-geometry"; + args += QString::number(w) + "x" + QString::number(h) + "+0+0"; + args += "-depth"; + args += QString::number(d); + } + args += "-br"; // Start Xnest with a black background. + args += "-parent"; + args += "0x" + QString::number(root, 16); + args += ":" + QString::number(displayId()); + xnest->setProcessChannelMode(QProcess::ForwardedChannels); + xnest->start(xserver, args); + //qDebug() << args; + + QTimer::singleShot(200, this, SLOT(startKeyFaker())); +} + +void QVFbX11View::xnestStopped() +{ + if (!shutdown) { + if (xnest && xnest->error() == QProcess::FailedToStart) + qWarning() << xserver << "could not be started"; + else + qWarning() << xserver << "stopped unexpectedly"; + } + if (keyFaker) { + delete keyFaker; + keyFaker = 0; + } + if (xnest) { + xnest->deleteLater(); + xnest = 0; + + QStringList xauthargs; + xauthargs += "remove"; + xauthargs += ":" + QString::number(displayId()); + if (QProcess::execute("xauth", xauthargs) != 0) + qWarning() << "xauth: failed to remove Xnest authentication credentials"; + } + if (serverAuthFile) { + delete serverAuthFile; + serverAuthFile = 0; + } +} + +void QVFbX11View::startKeyFaker() +{ + if (!keyFaker && xnest) + keyFaker = new X11KeyFaker(":" + QString::number(displayId()), this); +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/qvfbx11view.h b/tools/qvfb/qvfbx11view.h new file mode 100644 index 0000000..a96fa6d --- /dev/null +++ b/tools/qvfb/qvfbx11view.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved. +** +** This file is part of the Phone Edition of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVFBX11VIEW_H +#define QVFBX11VIEW_H + +#include "qvfbview.h" + +QT_BEGIN_NAMESPACE + +class X11KeyFaker; +class QProcess; +class QTemporaryFile; + +class QVFbX11View : public QVFbAbstractView +{ + Q_OBJECT +public: + QVFbX11View( int id, int w, int h, int d, Rotation r, QWidget *parent = 0); + virtual ~QVFbX11View(); + + QString xServerPath() const { return xserver; } + void setXServerPath(const QString& path) { xserver = path; } + + int displayId() const; + int displayWidth() const; + int displayHeight() const; + int displayDepth() const; + Rotation displayRotation() const; + + void skinKeyPressEvent( int code, const QString& text, bool autorep=FALSE ); + void skinKeyReleaseEvent( int code, const QString& text, bool autorep=FALSE ); + + void setGamma(double gr, double gg, double gb); + double gammaRed() const; + double gammaGreen() const; + double gammaBlue() const; + void getGamma(int i, QRgb& rgb); + + bool touchScreenEmulation() const; + bool lcdScreenEmulation() const; + int rate(); + bool animating() const; + QImage image() const; + void setRate(int); + + double zoomH() const; + double zoomV() const; + + QSize sizeHint() const; + +public slots: + void setTouchscreenEmulation( bool ); + void setLcdScreenEmulation( bool ); + void setZoom( double, double ); + void setRotation(Rotation); + void startAnimation( const QString& ); + void stopAnimation(); + +protected: + void showEvent(QShowEvent *); + void keyPressEvent(QKeyEvent *); + void keyReleaseEvent(QKeyEvent *); + +private slots: + void startXnest(); + void xnestStopped(); + void startKeyFaker(); + +private: + int id, w, h, d; + Rotation rotation; + double gr, gg, gb; + bool touchscreen, lcd; + X11KeyFaker *keyFaker; + QProcess *xnest; + QTemporaryFile *serverAuthFile; + bool shutdown; + QString xserver; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qvfb/translations/translations.pro b/tools/qvfb/translations/translations.pro new file mode 100644 index 0000000..736a72c --- /dev/null +++ b/tools/qvfb/translations/translations.pro @@ -0,0 +1,32 @@ +# Include those manually as they do not contain any directory specification + +FORMS = ../config.ui +HEADERS = ../qvfb.h \ + ../qvfbview.h \ + ../qvfbratedlg.h \ + ../qanimationwriter.h \ + ../gammaview.h \ + ../qvfbprotocol.h \ + ../qvfbshmem.h \ + ../qvfbmmap.h \ + ../qvfbhdr.h \ + ../qlock_p.h \ + ../qwssignalhandler_p.h \ + ../../shared/deviceskin/deviceskin.cpp + +SOURCES = ../qvfb.cpp \ + ../qvfbview.cpp \ + ../qvfbratedlg.cpp \ + ../main.cpp \ + ../qanimationwriter.cpp \ + ../qvfbprotocol.cpp \ + ../qvfbshmem.cpp \ + ../qvfbmmap.cpp \ + ../qlock.cpp \ + ../qwssignalhandler.cpp \ + ../../shared/deviceskin/deviceskin.cpp + +TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/qvfb_pl.ts \ + $$[QT_INSTALL_TRANSLATIONS]/qvfb_untranslated.ts \ + $$[QT_INSTALL_TRANSLATIONS]/qvfb_zh_CN.ts \ + $$[QT_INSTALL_TRANSLATIONS]/qvfb_zh_TW.ts diff --git a/tools/qvfb/x11keyfaker.cpp b/tools/qvfb/x11keyfaker.cpp new file mode 100644 index 0000000..76d6e6a --- /dev/null +++ b/tools/qvfb/x11keyfaker.cpp @@ -0,0 +1,626 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved. +** +** This file is part of the Phone Edition of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "x11keyfaker.h" +#include <QTimer> +#include <QSocketNotifier> +#include <QDebug> +#include <X11/Xlib.h> +#include <X11/cursorfont.h> +#include <X11/extensions/XTest.h> +#include <X11/keysym.h> +#include <X11/XF86keysym.h> +#include "qtopiakeysym.h" +#include <unistd.h> +#include <fcntl.h> + +QT_BEGIN_NAMESPACE + +X11KeyFaker::X11KeyFaker(const QString& displayName, QObject *parent) + : QObject(parent) +{ + this->displayName = displayName; + this->dpy = 0; + this->retryCount = 0; + this->shiftKeycode = 0; + this->modeSwitchKeycode = 0; + this->modifiers = 0; + connect(); +} + +X11KeyFaker::~X11KeyFaker() +{ + if (dpy) + XCloseDisplay(dpy); +} + +void X11KeyFaker::sendKeyEvent(int qtCode, bool isPress) +{ + if (!dpy) + return; + + // Convert the Qt key code into an X keysym. + KeySym keysym = NoSymbol; + switch (qtCode) { + case Qt::Key_Escape: keysym = XK_Escape; break; + case Qt::Key_Tab: keysym = XK_Tab; break; + case Qt::Key_Backtab: keysym = XK_ISO_Left_Tab; break; + case Qt::Key_Backspace: keysym = XK_BackSpace; break; + case Qt::Key_Return: keysym = XK_Return; break; + case Qt::Key_Enter: keysym = XK_KP_Enter; break; + case Qt::Key_Insert: keysym = XK_KP_Insert; break; + case Qt::Key_Delete: keysym = XK_KP_Delete; break; + case Qt::Key_Pause: keysym = XK_Pause; break; + case Qt::Key_Print: keysym = XK_Print; break; + case Qt::Key_SysReq: keysym = 0x1005FF60; break; + case Qt::Key_Clear: keysym = XK_KP_Begin; break; + case Qt::Key_Home: keysym = XK_Home; break; + case Qt::Key_End: keysym = XK_End; break; + case Qt::Key_Left: keysym = XK_Left; break; + case Qt::Key_Up: keysym = XK_Up; break; + case Qt::Key_Right: keysym = XK_Right; break; + case Qt::Key_Down: keysym = XK_Down; break; + case Qt::Key_PageUp: keysym = XK_Prior; break; + case Qt::Key_PageDown: keysym = XK_Next; break; + case Qt::Key_Shift: keysym = XK_Shift_L; break; + case Qt::Key_Control: keysym = XK_Control_L; break; + case Qt::Key_Meta: keysym = XK_Meta_L; break; + case Qt::Key_Alt: keysym = XK_Alt_L; break; + case Qt::Key_CapsLock: keysym = XK_Caps_Lock; break; + case Qt::Key_NumLock: keysym = XK_Num_Lock; break; + case Qt::Key_ScrollLock: keysym = XK_Scroll_Lock; break; + case Qt::Key_F1: keysym = XK_F1; break; + case Qt::Key_F2: keysym = XK_F2; break; + case Qt::Key_F3: keysym = XK_F3; break; + case Qt::Key_F4: keysym = XK_F4; break; + case Qt::Key_F5: keysym = XK_F5; break; + case Qt::Key_F6: keysym = XK_F6; break; + case Qt::Key_F7: keysym = XK_F7; break; + case Qt::Key_F8: keysym = XK_F8; break; + case Qt::Key_F9: keysym = XK_F9; break; + case Qt::Key_F10: keysym = XK_F10; break; + case Qt::Key_F11: keysym = XK_F11; break; + case Qt::Key_F12: keysym = XK_F12; break; + case Qt::Key_F13: keysym = XK_F13; break; + case Qt::Key_F14: keysym = XK_F14; break; + case Qt::Key_F15: keysym = XK_F15; break; + case Qt::Key_F16: keysym = XK_F16; break; + case Qt::Key_F17: keysym = XK_F17; break; + case Qt::Key_F18: keysym = XK_F18; break; + case Qt::Key_F19: keysym = XK_F19; break; + case Qt::Key_F20: keysym = XK_F20; break; + case Qt::Key_F21: keysym = XK_F21; break; + case Qt::Key_F22: keysym = XK_F22; break; + case Qt::Key_F23: keysym = XK_F23; break; + case Qt::Key_F24: keysym = XK_F24; break; + case Qt::Key_F25: keysym = XK_F25; break; + case Qt::Key_F26: keysym = XK_F26; break; + case Qt::Key_F27: keysym = XK_F27; break; + case Qt::Key_F28: keysym = XK_F28; break; + case Qt::Key_F29: keysym = XK_F29; break; + case Qt::Key_F30: keysym = XK_F30; break; + case Qt::Key_F31: keysym = XK_F31; break; + case Qt::Key_F32: keysym = XK_F32; break; + case Qt::Key_F33: keysym = XK_F33; break; + case Qt::Key_F34: keysym = XK_F34; break; + case Qt::Key_F35: keysym = XK_F35; break; + case Qt::Key_Super_L: keysym = XK_Super_L; break; + case Qt::Key_Super_R: keysym = XK_Super_R; break; + case Qt::Key_Menu: keysym = XK_Menu; break; + case Qt::Key_Hyper_L: keysym = XK_Hyper_L; break; + case Qt::Key_Hyper_R: keysym = XK_Hyper_R; break; + case Qt::Key_Help: keysym = XK_Help; break; + case Qt::Key_Direction_L: keysym = NoSymbol; break; // ??? + case Qt::Key_Direction_R: keysym = NoSymbol; break; // ??? + case Qt::Key_Space: keysym = XK_space; break; + case Qt::Key_Exclam: keysym = XK_exclam; break; + case Qt::Key_QuoteDbl: keysym = XK_quotedbl; break; + case Qt::Key_NumberSign: keysym = XK_numbersign; break; + case Qt::Key_Dollar: keysym = XK_dollar; break; + case Qt::Key_Percent: keysym = XK_percent; break; + case Qt::Key_Ampersand: keysym = XK_ampersand; break; + case Qt::Key_Apostrophe: keysym = XK_apostrophe; break; + case Qt::Key_ParenLeft: keysym = XK_parenleft; break; + case Qt::Key_ParenRight: keysym = XK_parenright; break; + case Qt::Key_Asterisk: keysym = XK_asterisk; break; + case Qt::Key_Plus: keysym = XK_plus; break; + case Qt::Key_Comma: keysym = XK_comma; break; + case Qt::Key_Minus: keysym = XK_minus; break; + case Qt::Key_Period: keysym = XK_period; break; + case Qt::Key_Slash: keysym = XK_slash; break; + case Qt::Key_0: keysym = XK_0; break; + case Qt::Key_1: keysym = XK_1; break; + case Qt::Key_2: keysym = XK_2; break; + case Qt::Key_3: keysym = XK_3; break; + case Qt::Key_4: keysym = XK_4; break; + case Qt::Key_5: keysym = XK_5; break; + case Qt::Key_6: keysym = XK_6; break; + case Qt::Key_7: keysym = XK_7; break; + case Qt::Key_8: keysym = XK_8; break; + case Qt::Key_9: keysym = XK_9; break; + case Qt::Key_Colon: keysym = XK_colon; break; + case Qt::Key_Semicolon: keysym = XK_semicolon; break; + case Qt::Key_Less: keysym = XK_less; break; + case Qt::Key_Equal: keysym = XK_equal; break; + case Qt::Key_Greater: keysym = XK_greater; break; + case Qt::Key_Question: keysym = XK_question; break; + case Qt::Key_At: keysym = XK_at; break; + case Qt::Key_A: keysym = XK_a; break; // Must be lower case keysyms + case Qt::Key_B: keysym = XK_b; break; // for correct shift handling. + case Qt::Key_C: keysym = XK_c; break; + case Qt::Key_D: keysym = XK_d; break; + case Qt::Key_E: keysym = XK_e; break; + case Qt::Key_F: keysym = XK_f; break; + case Qt::Key_G: keysym = XK_g; break; + case Qt::Key_H: keysym = XK_h; break; + case Qt::Key_I: keysym = XK_i; break; + case Qt::Key_J: keysym = XK_j; break; + case Qt::Key_K: keysym = XK_k; break; + case Qt::Key_L: keysym = XK_l; break; + case Qt::Key_M: keysym = XK_m; break; + case Qt::Key_N: keysym = XK_n; break; + case Qt::Key_O: keysym = XK_o; break; + case Qt::Key_P: keysym = XK_p; break; + case Qt::Key_Q: keysym = XK_q; break; + case Qt::Key_R: keysym = XK_r; break; + case Qt::Key_S: keysym = XK_s; break; + case Qt::Key_T: keysym = XK_t; break; + case Qt::Key_U: keysym = XK_u; break; + case Qt::Key_V: keysym = XK_v; break; + case Qt::Key_W: keysym = XK_w; break; + case Qt::Key_X: keysym = XK_x; break; + case Qt::Key_Y: keysym = XK_y; break; + case Qt::Key_Z: keysym = XK_z; break; + case Qt::Key_BracketLeft: keysym = XK_bracketleft; break; + case Qt::Key_Backslash: keysym = XK_backslash; break; + case Qt::Key_BracketRight: keysym = XK_bracketright; break; + case Qt::Key_AsciiCircum: keysym = XK_asciicircum; break; + case Qt::Key_Underscore: keysym = XK_underscore; break; + case Qt::Key_QuoteLeft: keysym = XK_quoteleft; break; + case Qt::Key_BraceLeft: keysym = XK_braceleft; break; + case Qt::Key_Bar: keysym = XK_bar; break; + case Qt::Key_BraceRight: keysym = XK_braceright; break; + case Qt::Key_AsciiTilde: keysym = XK_asciitilde; break; + + case Qt::Key_nobreakspace: keysym = XK_nobreakspace; break; + case Qt::Key_exclamdown: keysym = XK_exclamdown; break; + case Qt::Key_cent: keysym = XK_cent; break; + case Qt::Key_sterling: keysym = XK_sterling; break; + case Qt::Key_currency: keysym = XK_currency; break; + case Qt::Key_yen: keysym = XK_yen; break; + case Qt::Key_brokenbar: keysym = XK_brokenbar; break; + case Qt::Key_section: keysym = XK_section; break; + case Qt::Key_diaeresis: keysym = XK_diaeresis; break; + case Qt::Key_copyright: keysym = XK_copyright; break; + case Qt::Key_ordfeminine: keysym = XK_ordfeminine; break; + case Qt::Key_guillemotleft: keysym = XK_guillemotleft; break; + case Qt::Key_notsign: keysym = XK_notsign; break; + case Qt::Key_hyphen: keysym = XK_hyphen; break; + case Qt::Key_registered: keysym = XK_registered; break; + case Qt::Key_macron: keysym = XK_macron; break; + case Qt::Key_degree: keysym = XK_degree; break; + case Qt::Key_plusminus: keysym = XK_plusminus; break; + case Qt::Key_twosuperior: keysym = XK_twosuperior; break; + case Qt::Key_threesuperior: keysym = XK_threesuperior; break; + case Qt::Key_acute: keysym = XK_acute; break; + case Qt::Key_mu: keysym = XK_mu; break; + case Qt::Key_paragraph: keysym = XK_paragraph; break; + case Qt::Key_periodcentered: keysym = XK_periodcentered; break; + case Qt::Key_cedilla: keysym = XK_cedilla; break; + case Qt::Key_onesuperior: keysym = XK_onesuperior; break; + case Qt::Key_masculine: keysym = XK_masculine; break; + case Qt::Key_guillemotright: keysym = XK_guillemotright; break; + case Qt::Key_onequarter: keysym = XK_onequarter; break; + case Qt::Key_onehalf: keysym = XK_onehalf; break; + case Qt::Key_threequarters: keysym = XK_threequarters; break; + case Qt::Key_questiondown: keysym = XK_questiondown; break; + case Qt::Key_Agrave: keysym = XK_agrave; break; // Lower case keysyms + case Qt::Key_Aacute: keysym = XK_aacute; break; // for shift handling. + case Qt::Key_Acircumflex: keysym = XK_acircumflex; break; + case Qt::Key_Atilde: keysym = XK_atilde; break; + case Qt::Key_Adiaeresis: keysym = XK_adiaeresis; break; + case Qt::Key_Aring: keysym = XK_aring; break; + case Qt::Key_AE: keysym = XK_ae; break; + case Qt::Key_Ccedilla: keysym = XK_ccedilla; break; + case Qt::Key_Egrave: keysym = XK_egrave; break; + case Qt::Key_Eacute: keysym = XK_eacute; break; + case Qt::Key_Ecircumflex: keysym = XK_ecircumflex; break; + case Qt::Key_Ediaeresis: keysym = XK_ediaeresis; break; + case Qt::Key_Igrave: keysym = XK_igrave; break; + case Qt::Key_Iacute: keysym = XK_iacute; break; + case Qt::Key_Icircumflex: keysym = XK_icircumflex; break; + case Qt::Key_Idiaeresis: keysym = XK_idiaeresis; break; + case Qt::Key_ETH: keysym = XK_eth; break; + case Qt::Key_Ntilde: keysym = XK_ntilde; break; + case Qt::Key_Ograve: keysym = XK_ograve; break; + case Qt::Key_Oacute: keysym = XK_oacute; break; + case Qt::Key_Ocircumflex: keysym = XK_ocircumflex; break; + case Qt::Key_Otilde: keysym = XK_otilde; break; + case Qt::Key_Odiaeresis: keysym = XK_odiaeresis; break; + case Qt::Key_multiply: keysym = XK_multiply; break; + case Qt::Key_Ooblique: keysym = XK_ooblique; break; + case Qt::Key_Ugrave: keysym = XK_ugrave; break; + case Qt::Key_Uacute: keysym = XK_uacute; break; + case Qt::Key_Ucircumflex: keysym = XK_ucircumflex; break; + case Qt::Key_Udiaeresis: keysym = XK_udiaeresis; break; + case Qt::Key_Yacute: keysym = XK_yacute; break; + case Qt::Key_THORN: keysym = XK_thorn; break; + case Qt::Key_ssharp: keysym = XK_ssharp; break; + case Qt::Key_division: keysym = XK_division; break; + case Qt::Key_ydiaeresis: keysym = XK_ydiaeresis; break; + + case Qt::Key_AltGr: keysym = XK_ISO_Level3_Shift; break; + case Qt::Key_Multi_key: keysym = XK_Multi_key; break; + case Qt::Key_Codeinput: keysym = XK_Codeinput; break; + case Qt::Key_SingleCandidate: keysym = XK_SingleCandidate; break; + case Qt::Key_MultipleCandidate: keysym = XK_MultipleCandidate; break; + case Qt::Key_PreviousCandidate: keysym = XK_PreviousCandidate; break; + + case Qt::Key_Mode_switch: keysym = XK_Mode_switch; break; + + case Qt::Key_Kanji: keysym = XK_Kanji; break; + case Qt::Key_Muhenkan: keysym = XK_Muhenkan; break; + case Qt::Key_Henkan: keysym = XK_Henkan; break; + case Qt::Key_Romaji: keysym = XK_Romaji; break; + case Qt::Key_Hiragana: keysym = XK_Hiragana; break; + case Qt::Key_Katakana: keysym = XK_Katakana; break; + case Qt::Key_Hiragana_Katakana: keysym = XK_Hiragana_Katakana; break; + case Qt::Key_Zenkaku: keysym = XK_Zenkaku; break; + case Qt::Key_Hankaku: keysym = XK_Hankaku; break; + case Qt::Key_Zenkaku_Hankaku: keysym = XK_Zenkaku_Hankaku; break; + case Qt::Key_Touroku: keysym = XK_Touroku; break; + case Qt::Key_Massyo: keysym = XK_Massyo; break; + case Qt::Key_Kana_Lock: keysym = XK_Kana_Lock; break; + case Qt::Key_Kana_Shift: keysym = XK_Kana_Shift; break; + case Qt::Key_Eisu_Shift: keysym = XK_Eisu_Shift; break; + case Qt::Key_Eisu_toggle: keysym = XK_Eisu_toggle; break; + + case Qt::Key_Hangul: keysym = XK_Hangul; break; + case Qt::Key_Hangul_Start: keysym = XK_Hangul_Start; break; + case Qt::Key_Hangul_End: keysym = XK_Hangul_End; break; + case Qt::Key_Hangul_Hanja: keysym = XK_Hangul_Hanja; break; + case Qt::Key_Hangul_Jamo: keysym = XK_Hangul_Jamo; break; + case Qt::Key_Hangul_Romaja: keysym = XK_Hangul_Romaja; break; + case Qt::Key_Hangul_Jeonja: keysym = XK_Hangul_Jeonja; break; + case Qt::Key_Hangul_Banja: keysym = XK_Hangul_Banja; break; + case Qt::Key_Hangul_PreHanja: keysym = XK_Hangul_PreHanja; break; + case Qt::Key_Hangul_PostHanja: keysym = XK_Hangul_PostHanja; break; + case Qt::Key_Hangul_Special: keysym = XK_Hangul_Special; break; + + case Qt::Key_Dead_Grave: keysym = XK_dead_grave; break; + case Qt::Key_Dead_Acute: keysym = XK_dead_acute; break; + case Qt::Key_Dead_Circumflex: keysym = XK_dead_circumflex; break; + case Qt::Key_Dead_Tilde: keysym = XK_dead_tilde; break; + case Qt::Key_Dead_Macron: keysym = XK_dead_macron; break; + case Qt::Key_Dead_Breve: keysym = XK_dead_breve; break; + case Qt::Key_Dead_Abovedot: keysym = XK_dead_abovedot; break; + case Qt::Key_Dead_Diaeresis: keysym = XK_dead_diaeresis; break; + case Qt::Key_Dead_Abovering: keysym = XK_dead_abovering; break; + case Qt::Key_Dead_Doubleacute: keysym = XK_dead_doubleacute; break; + case Qt::Key_Dead_Caron: keysym = XK_dead_caron; break; + case Qt::Key_Dead_Cedilla: keysym = XK_dead_cedilla; break; + case Qt::Key_Dead_Ogonek: keysym = XK_dead_ogonek; break; + case Qt::Key_Dead_Iota: keysym = XK_dead_iota; break; + case Qt::Key_Dead_Voiced_Sound: keysym = XK_dead_voiced_sound; break; + case Qt::Key_Dead_Semivoiced_Sound: keysym = XK_dead_semivoiced_sound; break; + case Qt::Key_Dead_Belowdot: keysym = XK_dead_belowdot; break; + case Qt::Key_Dead_Hook: keysym = XK_dead_hook; break; + case Qt::Key_Dead_Horn: keysym = XK_dead_horn; break; + + case Qt::Key_Back: keysym = XF86XK_Back; break; + case Qt::Key_Forward: keysym = XF86XK_Forward; break; + case Qt::Key_Stop: keysym = XF86XK_Stop; break; + case Qt::Key_Refresh: keysym = XF86XK_Refresh; break; + + case Qt::Key_VolumeDown: keysym = XF86XK_AudioLowerVolume; break; + case Qt::Key_VolumeMute: keysym = XF86XK_AudioMute; break; + case Qt::Key_VolumeUp: keysym = XF86XK_AudioRaiseVolume; break; + case Qt::Key_BassBoost: keysym = NoSymbol; break; // ??? + case Qt::Key_BassUp: keysym = NoSymbol; break; // ??? + case Qt::Key_BassDown: keysym = NoSymbol; break; // ??? + case Qt::Key_TrebleUp: keysym = NoSymbol; break; // ??? + case Qt::Key_TrebleDown: keysym = NoSymbol; break; // ??? + + case Qt::Key_MediaPlay: keysym = XF86XK_AudioPlay; break; + case Qt::Key_MediaStop: keysym = XF86XK_AudioStop; break; + case Qt::Key_MediaPrevious: keysym = XF86XK_AudioPrev; break; + case Qt::Key_MediaNext: keysym = XF86XK_AudioNext; break; + case Qt::Key_MediaRecord: keysym = XF86XK_AudioRecord; break; + + case Qt::Key_HomePage: keysym = XF86XK_HomePage; break; + case Qt::Key_Favorites: keysym = XF86XK_Favorites; break; + case Qt::Key_Search: keysym = XF86XK_Search; break; + case Qt::Key_Standby: keysym = XF86XK_Standby; break; + case Qt::Key_OpenUrl: keysym = XF86XK_OpenURL; break; + + case Qt::Key_LaunchMail: keysym = XF86XK_Mail; break; + case Qt::Key_LaunchMedia: keysym = XF86XK_AudioMedia; break; + case Qt::Key_Launch0: keysym = XF86XK_Launch0; break; + case Qt::Key_Launch1: keysym = XF86XK_Launch1; break; + case Qt::Key_Launch2: keysym = XF86XK_Launch2; break; + case Qt::Key_Launch3: keysym = XF86XK_Launch3; break; + case Qt::Key_Launch4: keysym = XF86XK_Launch4; break; + case Qt::Key_Launch5: keysym = XF86XK_Launch5; break; + case Qt::Key_Launch6: keysym = XF86XK_Launch6; break; + case Qt::Key_Launch7: keysym = XF86XK_Launch7; break; + case Qt::Key_Launch8: keysym = XF86XK_Launch8; break; + case Qt::Key_Launch9: keysym = XF86XK_Launch9; break; + case Qt::Key_LaunchA: keysym = XF86XK_LaunchA; break; + case Qt::Key_LaunchB: keysym = XF86XK_LaunchB; break; + case Qt::Key_LaunchC: keysym = XF86XK_LaunchC; break; + case Qt::Key_LaunchD: keysym = XF86XK_LaunchD; break; + case Qt::Key_LaunchE: keysym = XF86XK_LaunchE; break; + case Qt::Key_LaunchF: keysym = XF86XK_LaunchF; break; + + case Qt::Key_MediaLast: keysym = NoSymbol; break; // ??? + + case Qt::Key_Select: keysym = QTOPIAXK_Select; break; + case Qt::Key_Yes: keysym = QTOPIAXK_Yes; break; + case Qt::Key_No: keysym = QTOPIAXK_No; break; + + case Qt::Key_Cancel: keysym = QTOPIAXK_Cancel; break; + case Qt::Key_Printer: keysym = QTOPIAXK_Printer; break; + case Qt::Key_Execute: keysym = QTOPIAXK_Execute; break; + case Qt::Key_Sleep: keysym = QTOPIAXK_Sleep; break; + case Qt::Key_Play: keysym = QTOPIAXK_Play; break; + case Qt::Key_Zoom: keysym = QTOPIAXK_Zoom; break; + + case Qt::Key_Context1: keysym = QTOPIAXK_Context1; break; + case Qt::Key_Context2: keysym = QTOPIAXK_Context2; break; + case Qt::Key_Context3: keysym = QTOPIAXK_Context3; break; + case Qt::Key_Context4: keysym = QTOPIAXK_Context4; break; + case Qt::Key_Call: keysym = QTOPIAXK_Call; break; + case Qt::Key_Hangup: keysym = QTOPIAXK_Hangup; break; + case Qt::Key_Flip: keysym = QTOPIAXK_Flip; break; + + case Qt::Key_unknown: keysym = NoSymbol; break; + } + if (keysym == NoSymbol) + return; + + // Convert the X keysym into an X keycode. + KeyCode keycode = XKeysymToKeycode(dpy, keysym); + if (keycode == NoSymbol) + return; + + // Determine if we need to fake shift keys as well. + int index = 0; + while (index < 4 && XKeycodeToKeysym(dpy, keycode, index) != keysym) + ++index; + int extraModifiers = 0; + if ((index & 1) != 0) + extraModifiers |= ShiftMask; + if ((index & 2) != 0) + extraModifiers |= Mod2Mask; + if ((modifiers & LockMask) != 0) { + // If Caps Lock is set, then flip the shift state for alphabetic keys. + if (qtCode >= Qt::Key_A && qtCode <= Qt::Key_Z) + extraModifiers ^= ShiftMask; + if (qtCode >= Qt::Key_Agrave && qtCode <= Qt::Key_THORN && + qtCode != Qt::Key_multiply) + extraModifiers ^= ShiftMask; + } + + // Adjust modifier keys for the shift states. This is needed for + // things like the * and # phone keys, which need Shift to be pressed + // when entering from a keyboard, but don't need Shift from a skin. + unsigned long delay = 0; + if (extraModifiers != 0) { + if ((extraModifiers & ShiftMask) != 0) { + if ((modifiers & ShiftMask) == 0) + XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++); + } else { + if ((modifiers & ShiftMask) != 0) + XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++); + } + if ((extraModifiers & Mod2Mask) != 0) { + if ((modifiers & Mod2Mask) == 0) + XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++); + } else { + if ((modifiers & Mod2Mask) != 0) + XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++); + } + } + + // Fake the actual key. + XTestFakeKeyEvent(dpy, keycode, (Bool)isPress, delay++); + + // Adjust the modifiers back. + if (extraModifiers != 0) { + if ((extraModifiers & ShiftMask) != 0) { + if ((modifiers & ShiftMask) == 0) + XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++); + } else { + if ((modifiers & ShiftMask) != 0) + XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++); + } + if ((extraModifiers & Mod2Mask) != 0) { + if ((modifiers & Mod2Mask) == 0) + XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++); + } else { + if ((modifiers & Mod2Mask) != 0) + XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++); + } + } + + // Flush the key events. + XFlush(dpy); + + // Update the modifiers if this was a shift key. + if (isPress) { + if (qtCode == Qt::Key_Shift) + modifiers |= ShiftMask; + if (qtCode == Qt::Key_CapsLock) + modifiers |= LockMask; + if (qtCode == Qt::Key_Mode_switch) + modifiers |= Mod2Mask; + } else { + if (qtCode == Qt::Key_Shift) + modifiers &= ~ShiftMask; + if (qtCode == Qt::Key_CapsLock) + modifiers &= ~LockMask; + if (qtCode == Qt::Key_Mode_switch) + modifiers &= ~Mod2Mask; + } +} + +// Determine if an X11 keycode is currently mapped to one or more keysyms. +static bool keycodeInUse(Display *dpy, int keycode) +{ + for (int index = 0; index < 8; ++index) { + if (XKeycodeToKeysym(dpy, keycode, index) != NoSymbol) + return true; + } + return false; +} + +// Allocate a keycode for a special keysym. +static bool allocateSpecialKeysym + (Display *dpy, int& min_keycode, int& max_keycode, KeySym key) +{ + if (XKeysymToKeycode(dpy, key) != NoSymbol) + return true; // There is already a mapping for this key. Good! + while (max_keycode >= min_keycode) { + if (!keycodeInUse(dpy, max_keycode)) + break; + --max_keycode; + } + if (max_keycode < min_keycode) + return false; + XChangeKeyboardMapping(dpy, max_keycode, 1, &key, 1); + --max_keycode; + return true; +} + +void X11KeyFaker::connect() +{ + // Open the display. + dpy = XOpenDisplay(displayName.toLatin1().data()); + if (!dpy) { + // Try again in a few milliseconds. Xnest may not be alive yet. + // Give up after 10 seconds. + if (++retryCount < 50) + QTimer::singleShot(200, this, SLOT(connect())); + else + QTimer::singleShot(0, this, SIGNAL(couldNotConnect())); + return; + } + + // Query the XTest extension, which we need to fake the key events. + int event_base, error_base, major, minor; + if (!XTestQueryExtension + (dpy, &event_base, &error_base, &major, &minor)) { + XCloseDisplay(dpy); + dpy = 0; + QTimer::singleShot(0, this, SIGNAL(couldNotConnect())); + return; + } + + // Modify the Xnest's keyboard mappings to add Qtopia's special keysyms. + int min_keycode = 1, max_keycode = 255; + XDisplayKeycodes(dpy, &min_keycode, &max_keycode); + bool ok = true; + for (KeySym key = QTOPIAXK_Max; key >= QTOPIAXK_Min; --key) { + // This is an extension keysym, not part of the standard X11 set. + if (!allocateSpecialKeysym(dpy, min_keycode, max_keycode, key)) { + ok = false; + break; + } + } + static const KeySym specials[] = { + XF86XK_Back, // Qt::Key_Back + XF86XK_AudioLowerVolume, // Qt::Key_VolumeUp + XF86XK_AudioRaiseVolume, // Qt::Key_VolumeDown + XK_F28, // Qt::Key_F28 + NoSymbol + }; + int index = 0; + while (ok && specials[index] != NoSymbol) { + // This is a standard X11/XFree86 keysym that Qtopia uses, + // but it may not be on the user's physical keyboard. + if (!allocateSpecialKeysym + (dpy, min_keycode, max_keycode, specials[index])) + ok = false; + ++index; + } + if (!ok) + qWarning() << "There are insufficient spare X11 keycodes to allocate the special Qtopia keys"; + + // Change the root cursor to something more reasonable than "X". + Cursor cursor = XCreateFontCursor(dpy, XC_left_ptr); + XDefineCursor(dpy, RootWindow(dpy, DefaultScreen(dpy)), cursor); + + // Look up the shift keys. + shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_L); + if (shiftKeycode == NoSymbol) + shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_R); + modeSwitchKeycode = XKeysymToKeycode(dpy, XK_Mode_switch); + + // Make sure all of the above changes are flushed. + XFlush(dpy); + + // Set up event handling for the display. + QSocketNotifier *notifier = new QSocketNotifier + (ConnectionNumber(dpy), QSocketNotifier::Read, this); + QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readyRead())); + + // Make sure the file descriptor is not inherited across exec's. + fcntl(ConnectionNumber(dpy), F_SETFD, 1); + + // Notify interested parties that we are now connected to the X display. + QTimer::singleShot(0, this, SIGNAL(connected())); +} + +void X11KeyFaker::readyRead() +{ + if (dpy) { + // Read incoming events and discard them. The only event + // we care about is keyboard mapping changes. Since we + // don't have any active windows, there's nothing more to do. + while (XEventsQueued(dpy, QueuedAfterFlush)) { + XEvent event; + XNextEvent(dpy, &event); + if (event.xany.type == MappingNotify) + XRefreshKeyboardMapping(&event.xmapping); + } + } +} + +QT_END_NAMESPACE diff --git a/tools/qvfb/x11keyfaker.h b/tools/qvfb/x11keyfaker.h new file mode 100644 index 0000000..32417df --- /dev/null +++ b/tools/qvfb/x11keyfaker.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved. +** +** This file is part of the Phone Edition of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef X11KEYFAKER_H +#define X11KEYFAKER_H + +#include <QObject> +#include <QX11Info> +#include <qnamespace.h> + +QT_BEGIN_NAMESPACE + +class X11KeyFaker : public QObject +{ + Q_OBJECT +public: + X11KeyFaker(const QString& displayName, QObject *parent = 0); + ~X11KeyFaker(); + + bool isConnected() const { return dpy != 0; } + + void sendKeyEvent(int qtCode, bool isPress); + +private slots: + void connect(); + void readyRead(); + +signals: + void connected(); + void couldNotConnect(); + +private: + QString displayName; + Display *dpy; + int retryCount; + int shiftKeycode; + int modeSwitchKeycode; + int modifiers; +}; + +QT_END_NAMESPACE + +#endif |