| 1 | Synergy Developer and Porting Guide
|
|---|
| 2 | ===================================
|
|---|
| 3 |
|
|---|
| 4 | This document is under development.
|
|---|
| 5 |
|
|---|
| 6 | Code Organization
|
|---|
| 7 | -----------------
|
|---|
| 8 |
|
|---|
| 9 | The synergy source code organization is:
|
|---|
| 10 |
|
|---|
| 11 | . -- root makefiles, some standard documentation
|
|---|
| 12 | cmd -- program source code
|
|---|
| 13 | launcher -- synergy launcher for Windows
|
|---|
| 14 | synergyc -- synergy client
|
|---|
| 15 | synergys -- synergy server
|
|---|
| 16 | config -- stuff for autoconf/automake
|
|---|
| 17 | dist -- files for creating distributions
|
|---|
| 18 | nullsoft -- files for creating Nullsoft NSIS installer (Windows)
|
|---|
| 19 | rpm -- files for creating RPMs
|
|---|
| 20 | doc -- placeholder for documentation
|
|---|
| 21 | examples -- example files
|
|---|
| 22 | lib -- library source code
|
|---|
| 23 | arch -- platform dependent utility library
|
|---|
| 24 | base -- simple utilities
|
|---|
| 25 | client -- synergy client library
|
|---|
| 26 | common -- commonly needed header files
|
|---|
| 27 | io -- I/O
|
|---|
| 28 | mt -- multithreading
|
|---|
| 29 | net -- networking
|
|---|
| 30 | platform -- platform dependent display/window/event stuff
|
|---|
| 31 | server -- synergy server library
|
|---|
| 32 | synergy -- synergy shared client/server code library
|
|---|
| 33 |
|
|---|
| 34 | Note how the utility code required by the programs is placed into
|
|---|
| 35 | separate library directories. This makes the makefiles a little
|
|---|
| 36 | more awkward but makes for a cleaner organization. The top level
|
|---|
| 37 | directory has only the standard documentation files and the files
|
|---|
| 38 | necessary to configure and build the rest of the project.
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 | Coding Style Guide
|
|---|
| 42 | ------------------
|
|---|
| 43 |
|
|---|
| 44 | Synergy uses many coding conventions. Contributed code should
|
|---|
| 45 | following these guidelines.
|
|---|
| 46 |
|
|---|
| 47 | - Symbol Naming
|
|---|
| 48 | Names always begin with a letter (never an underscore). The first
|
|---|
| 49 | letter of interior names are always capitalized. Acronyms should
|
|---|
| 50 | be all uppercase. For example: myTextAsASCII.
|
|---|
| 51 |
|
|---|
| 52 | Names come it two flavors: leading capital and leading lowercase.
|
|---|
| 53 | The former have the first character capitalized and the latter
|
|---|
| 54 | don't. In the following table, leading capital names are indicated
|
|---|
| 55 | by `Name' and leading lowercase names by `name'.
|
|---|
| 56 |
|
|---|
| 57 | The naming convention for various things are:
|
|---|
| 58 |
|
|---|
| 59 | * Exceptions -- X + Name XMyException
|
|---|
| 60 | * Interfaces -- I + Name IMyInterface
|
|---|
| 61 | * Template Classes -- T + Name TMyTemplate<>
|
|---|
| 62 | * Other Classes -- C + Name CMyClass
|
|---|
| 63 | * Enumerations -- E + Name EMyEnumeration
|
|---|
| 64 | * Constants -- k + Name kMyConstant
|
|---|
| 65 | * Data Members -- m_ + name m_myDataMember
|
|---|
| 66 | * Methods -- name myMethod
|
|---|
| 67 | * Functions -- name myFunction
|
|---|
| 68 | * Variables -- name myVariable
|
|---|
| 69 |
|
|---|
| 70 | Exceptions are types that get thrown and are generally derived
|
|---|
| 71 | (possibly indirectly) from XBase. Interfaces are derived (possibly
|
|---|
| 72 | indirectly) from IInterface and have only pure virtual functions.
|
|---|
| 73 | Other classes are classes that aren't exceptions or interfaces.
|
|---|
| 74 | Constants include global constants and enumerants.
|
|---|
| 75 |
|
|---|
| 76 | Method names should usually have the form `verbObject'. For example:
|
|---|
| 77 | * isGameOn()
|
|---|
| 78 | * getBeer()
|
|---|
| 79 | * pressPowerButton()
|
|---|
| 80 | * setChannel()
|
|---|
| 81 | In general, use `get' and `set' to read and write state but use `is'
|
|---|
| 82 | to read boolean state. Note that classes that contain only `is',
|
|---|
| 83 | `get', and `set' are probably plain old data; you might want to
|
|---|
| 84 | consider using public data members only or, better, refactor your
|
|---|
| 85 | design to have classes that actually do something more than just
|
|---|
| 86 | hold data.
|
|---|
| 87 |
|
|---|
| 88 | - File Naming
|
|---|
| 89 | Each class should have one source and one header file. If the
|
|---|
| 90 | class is named `CMyClass' then the source file should be named
|
|---|
| 91 | `CMyClass.cpp' and the header file `CMyClass.h'.
|
|---|
| 92 |
|
|---|
| 93 | Headers files not containing a class should have some meaningful
|
|---|
| 94 | name with a leading capital (e.g. `Version.h').
|
|---|
| 95 |
|
|---|
| 96 | Source files without a header file have a leading lowercase name.
|
|---|
| 97 | Only files containing the entry point for an application should
|
|---|
| 98 | lack a header file.
|
|---|
| 99 |
|
|---|
| 100 | - Dependencies
|
|---|
| 101 | * No circular library dependencies
|
|---|
| 102 | Library dependencies form an acyclic graph. Conceptually
|
|---|
| 103 | libraries can be arranged in layers where each library only
|
|---|
| 104 | references libraries in layers below it, not in the same layer
|
|---|
| 105 | or layers above it. The makefiles build the lowest layer
|
|---|
| 106 | libraries first and work upwards.
|
|---|
| 107 |
|
|---|
| 108 | * Avoid circular uses-a relationships
|
|---|
| 109 | When possible, design classes with one-way uses-a relationships
|
|---|
| 110 | and avoid cycles. This makes it easier to understand the code.
|
|---|
| 111 | However, sometimes it's not always practical so it is permitted.
|
|---|
| 112 |
|
|---|
| 113 | * Included files in headers
|
|---|
| 114 | Headers should #include only the necessary headers. In
|
|---|
| 115 | particular, if a class is referenced in a header file only as a
|
|---|
| 116 | pointer or a reference then use `class COtherClass;' instead of
|
|---|
| 117 | `#include "COtherClass.h".'
|
|---|
| 118 |
|
|---|
| 119 | * #include syntax
|
|---|
| 120 | Non-synergy header files must be included using angle brackets
|
|---|
| 121 | while synergy header files must be included using double quotes.
|
|---|
| 122 | #include "CSynergyHeader.h"
|
|---|
| 123 | #include <systemheader.h>
|
|---|
| 124 | The file name in a #include must not be a relative path unless
|
|---|
| 125 | it's a system header file and it's customary to use a relative
|
|---|
| 126 | path, e.g. `#include <sys/types.h>'. Use compiler options to
|
|---|
| 127 | add necessary directories to the include search path.
|
|---|
| 128 |
|
|---|
| 129 | * Included file ordering
|
|---|
| 130 | Files should be included in the following order:
|
|---|
| 131 | * Header for source file
|
|---|
| 132 | The first include for CMyClass.cpp must be CMyClass.h.
|
|---|
| 133 | * Other headers in directory, sorted alphabetically
|
|---|
| 134 | * Headers for each library, sorted alphabetically per library
|
|---|
| 135 | Include headers from the library closest in the dependency graph
|
|---|
| 136 | first, then the next farthest, etc. Sort alphabetically within
|
|---|
| 137 | each library.
|
|---|
| 138 | * System headers
|
|---|
| 139 |
|
|---|
| 140 | - C++
|
|---|
| 141 | * C++ features
|
|---|
| 142 | Synergy uses the following more recent C++ features:
|
|---|
| 143 | * bool
|
|---|
| 144 | * templates
|
|---|
| 145 | * exceptions
|
|---|
| 146 | * mutable
|
|---|
| 147 | * new scoping rules
|
|---|
| 148 | * the standard C++ library
|
|---|
| 149 |
|
|---|
| 150 | Do not use the following C++ features:
|
|---|
| 151 | * dynamic_cast
|
|---|
| 152 | * run time type information
|
|---|
| 153 | * namespaces and using (use std:: where necessary)
|
|---|
| 154 |
|
|---|
| 155 | The new scoping rules say that the scope of a variable declared
|
|---|
| 156 | in a for statement is limited to the for loop. For example:
|
|---|
| 157 |
|
|---|
| 158 | for (int i = 0; i < 10; ++i) {
|
|---|
| 159 | // i is in scope here
|
|---|
| 160 | }
|
|---|
| 161 | // i is not in scope here
|
|---|
| 162 |
|
|---|
| 163 | for (int i = -10; i < 0; ++i) {
|
|---|
| 164 | // an entirely new i is in scope here
|
|---|
| 165 | }
|
|---|
| 166 | // i is not in scope here
|
|---|
| 167 |
|
|---|
| 168 | This is used routinely in synergy, but only in for loops. There
|
|---|
| 169 | is a macro for `for' in lib/base/common.h when building under
|
|---|
| 170 | Microsoft Visual C++ that works around the fact that that compiler
|
|---|
| 171 | doesn't follow the new scoping rules. Use the macro if your
|
|---|
| 172 | compiler uses the old scoping rules.
|
|---|
| 173 |
|
|---|
| 174 | * Standard C++ library
|
|---|
| 175 | The standard C++ library containers should always be used in favor
|
|---|
| 176 | of custom containers wherever reasonable. std::string is used
|
|---|
| 177 | throughout synergy but only as the CString typedef; always use
|
|---|
| 178 | CString, never std::string except in the arch library. Synergy
|
|---|
| 179 | avoids using auto_ptr due to some portability problems. Synergy
|
|---|
| 180 | makes limited use of standard algorithms and streams but they can
|
|---|
| 181 | be freely used in new code.
|
|---|
| 182 |
|
|---|
| 183 | * Limited multiple inheritance
|
|---|
| 184 | Classes should inherit implementation from at most one superclass.
|
|---|
| 185 | Inheriting implementation from multiple classes can have unpleasant
|
|---|
| 186 | consequences in C++ due to it's limited capabilities. Classes can
|
|---|
| 187 | inherit from any number of interface classes. An interface class
|
|---|
| 188 | provides only pure virtual methods. Synergy breaks this rule in
|
|---|
| 189 | IInterface which implements the virtual destructor for convenience.
|
|---|
| 190 |
|
|---|
| 191 | * No globals
|
|---|
| 192 | Avoid global variables. All global variables must be static, making
|
|---|
| 193 | it visible only with its source file. Most uses of global variables
|
|---|
| 194 | are better served by static data members of a class. Global
|
|---|
| 195 | constants are permitted in some circumstances.
|
|---|
| 196 |
|
|---|
| 197 | Also avoid global functions. Use public static member functions in
|
|---|
| 198 | a class instead.
|
|---|
| 199 |
|
|---|
| 200 | These rules are violated by the main source file for each program
|
|---|
| 201 | (except that the globals are still static). They could easily be
|
|---|
| 202 | rewritten to put all the variables and functions into a class but
|
|---|
| 203 | there's little to be gained by that.
|
|---|
| 204 |
|
|---|
| 205 | * Private data only
|
|---|
| 206 | If a class is plain-old-data (i.e. it has no methods) all of its
|
|---|
| 207 | data members should be public. Otherwise all of its data members
|
|---|
| 208 | should be private, not public or protected. This makes it much
|
|---|
| 209 | easier to track the use of a member when reading code. Protected
|
|---|
| 210 | data is not allowed because `protected' is a synonym for `public
|
|---|
| 211 | to my subclasses' and public data is a Bad Thing. While it might
|
|---|
| 212 | seem okay in this limited situation, the situation is not at all
|
|---|
| 213 | limited since an arbitrary number of classes can be derived,
|
|---|
| 214 | directly or indirectly, from the class and any of those classes
|
|---|
| 215 | have full access to the protected data.
|
|---|
| 216 |
|
|---|
| 217 | * Plain old data
|
|---|
| 218 | A class that merely contains data and doesn't perform operations
|
|---|
| 219 | on that data (other than reads and writes) is plain old data (POD).
|
|---|
| 220 | POD should have only public data members and non-copy constructors.
|
|---|
| 221 | It must not have any methods other than constructors, not even a
|
|---|
| 222 | destructor or assignment operators, nor protected or private data.
|
|---|
| 223 | Note that this definition of POD is not the definition used in the
|
|---|
| 224 | C++ standard, which limits the contained data types to types that
|
|---|
| 225 | have no constructors, destructors, or methods.
|
|---|
| 226 |
|
|---|
| 227 | * Avoid using friend
|
|---|
| 228 | Avoid declaring friend functions or classes. They're sometimes
|
|---|
| 229 | necessary for operator overloading. If you find it necessary to
|
|---|
| 230 | add friends to some class C, consider creating a utility class U.
|
|---|
| 231 | A utility class is declared as the only friend of C and provides
|
|---|
| 232 | only static methods. Each method forwards to a private method on
|
|---|
| 233 | an object of C type (passed as a parameter to the U's method).
|
|---|
| 234 | This makes maintenance easier since only U has friend access to C
|
|---|
| 235 | and finding any call to U is trivial (they're prefixed by U::).
|
|---|
| 236 |
|
|---|
| 237 | * Don't test for NULL when using `delete' or `delete[]'
|
|---|
| 238 | It's unnecessary since delete does it anyway.
|
|---|
| 239 |
|
|---|
| 240 | - Makefiles
|
|---|
| 241 | Automake's makefiles (named Makefile.am) have a few requirements:
|
|---|
| 242 | * Define the following macro at the top of the file:
|
|---|
| 243 | NULL =
|
|---|
| 244 | * Lists should have one item per line and end in $(NULL). For
|
|---|
| 245 | example:
|
|---|
| 246 | EXTRA_DIST = \
|
|---|
| 247 | kiwi.txt \
|
|---|
| 248 | mango.cpp \
|
|---|
| 249 | papaya.h \
|
|---|
| 250 | $(NULL)
|
|---|
| 251 | Indentation must use tabs in a makefile. Line continuations
|
|---|
| 252 | (backslashes) should be aligned using tabs.
|
|---|
| 253 | * Lists of files should be sorted alphabetically in groups (e..g
|
|---|
| 254 | source files, header files, then other files). Lists of
|
|---|
| 255 | subdirectories must be in the desired build order.
|
|---|
| 256 |
|
|---|
| 257 | - Source Formatting
|
|---|
| 258 | Every project has its own formatting style and no style satisfies
|
|---|
| 259 | everyone. New code should be consistent with existing code:
|
|---|
| 260 |
|
|---|
| 261 | * All files should include the copyright and license notice
|
|---|
| 262 | * Use tabs to indent
|
|---|
| 263 | * Tabs are 4 columns
|
|---|
| 264 | * Lines should not extend past the 80th column
|
|---|
| 265 | * Open braces ({) go on same line as introducing statement
|
|---|
| 266 | `for (i = 0; i < 10; ++i) {' not
|
|---|
| 267 | for (i = 0; i < 10; ++i)
|
|---|
| 268 | {
|
|---|
| 269 | * Close braces line up with introducing statement
|
|---|
| 270 | * Open brace for function is on a line by itself in first column
|
|---|
| 271 | * Close brace for function lines up with open brace
|
|---|
| 272 | * Always use braces on: if, else, for, while, do, switch
|
|---|
| 273 | * `else {' goes on its own line
|
|---|
| 274 | * Always explicitly test pointers against NULL
|
|---|
| 275 | e.g. `if (ptr == NULL)' not `if (ptr)'
|
|---|
| 276 | * Always explicitly test integral values against 0
|
|---|
| 277 | e.g. `if (i == 0)' not `if (i)'
|
|---|
| 278 | * Put spaces around binary operators and after statements
|
|---|
| 279 | e.g. `if (a == b) {' not `if(a==b){'
|
|---|
| 280 | * C'tor initializers are one per line, indented one tab stop
|
|---|
| 281 | * Other indentation should follow existing practice
|
|---|
| 282 | * Use Qt style comments for extraction by doxygen (i.e. //! and /*!)
|
|---|
| 283 | * Mark incomplete or buggy code with `FIXME'
|
|---|
| 284 |
|
|---|
| 285 | - Other
|
|---|
| 286 | * calls to LOG() should always be all on one line (even past column 80)
|
|---|
| 287 |
|
|---|
| 288 |
|
|---|
| 289 | Class Relationships
|
|---|
| 290 | -------------------
|
|---|
| 291 |
|
|---|
| 292 | The doxygen documentation can help in understanding the relationships
|
|---|
| 293 | between objects. Use `make doxygen' in the top level directory to
|
|---|
| 294 | create the doxygen documentation into doc/doxygen/html. You must have
|
|---|
| 295 | doxygen installed, of course.
|
|---|
| 296 |
|
|---|
| 297 | FIXME -- high level overview of class relationships
|
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 | Portability
|
|---|
| 301 | -----------
|
|---|
| 302 |
|
|---|
| 303 | Synergy is mostly platform independent code but necessarily has
|
|---|
| 304 | platform dependent parts. The mundane platform dependent parts
|
|---|
| 305 | come from the usual suspects: networking, multithreading, file
|
|---|
| 306 | system, high resolution clocks, system logging, etc. Porting
|
|---|
| 307 | these parts is relatively straightforward.
|
|---|
| 308 |
|
|---|
| 309 | Synergy also has more esoteric platform dependent code. The
|
|---|
| 310 | functions for low-level event interception and insertion,
|
|---|
| 311 | warping the cursor position, character to keyboard event
|
|---|
| 312 | translation, clipboard manipulation, and screen saver control
|
|---|
| 313 | are often obscure and poorly documented. Unfortunately, these
|
|---|
| 314 | are exactly the functions synergy requires to do its magic.
|
|---|
| 315 |
|
|---|
| 316 | Porting synergy to a new platform requires the following steps:
|
|---|
| 317 |
|
|---|
| 318 | - Setting up the build
|
|---|
| 319 | - Adjusting lib/common/common.h
|
|---|
| 320 | - Implementing lib/arch
|
|---|
| 321 | - Implementing lib/platform
|
|---|
| 322 | - Tweaks
|
|---|
| 323 |
|
|---|
| 324 | Setting up the build:
|
|---|
| 325 |
|
|---|
| 326 | The first phase is simply to create the files necessary to build the
|
|---|
| 327 | other files. On Unix, synergy uses autoconf/automake which produces
|
|---|
| 328 | a `configure' script that generates makefiles. On Windows, synergy
|
|---|
| 329 | uses Visual C++ workspace and project files. If you're porting to
|
|---|
| 330 | another Unix variant, you may need to adjust `configure.in',
|
|---|
| 331 | `acinclude.m4', and Unix flavor dependent code in lib/arch. Note
|
|---|
| 332 | especially the SYSAPI_* and WINAPI_* macro definitions in
|
|---|
| 333 | ARCH_CFLAGS. Exactly one of each must be defined. It should also
|
|---|
| 334 | add AM_CONDITIONALs if a new SYSAPI_* or WINAPI_* was added.
|
|---|
| 335 |
|
|---|
| 336 | Adjusting lib/common/common.h:
|
|---|
| 337 |
|
|---|
| 338 | The lib/common/common.h header file is included directly or indirectly
|
|---|
| 339 | by every other file. Its primary job is to include config.h, which
|
|---|
| 340 | defines macros depending on what the 'configure' script discovered
|
|---|
| 341 | about the system. If the platform does not use the 'configure' script
|
|---|
| 342 | it must define the appropriate SYSAPI_* and WINAPI_* macro. It may
|
|---|
| 343 | also do other platform specific setup.
|
|---|
| 344 |
|
|---|
| 345 | Adjusting lib/common/BasicTypes.h:
|
|---|
| 346 |
|
|---|
| 347 | No changes should be necessary in BasicTypes.h. However, if the
|
|---|
| 348 | platform's system header files define SInt8, et al. you may need
|
|---|
| 349 | to adjust the typedefs to match the system's definitions.
|
|---|
| 350 |
|
|---|
| 351 | Implementing lib/arch:
|
|---|
| 352 |
|
|---|
| 353 | Much platform dependent code lives in lib/arch. There are several
|
|---|
| 354 | interface classes there and they must all be implemented for each
|
|---|
| 355 | platform. See the interface header files for more information.
|
|---|
| 356 |
|
|---|
| 357 | Platforms requiring special functions should create a class named
|
|---|
| 358 | CArchMiscXXX where XXX is the platform name. The class should have
|
|---|
| 359 | only static methods. Clients can include the appropriate header
|
|---|
| 360 | file and make calls directly, surrounded by a suitable #ifdef/#endif.
|
|---|
| 361 |
|
|---|
| 362 | If using automake, the Makefile.am should list the system specific
|
|---|
| 363 | files in a XXX_SOURCE_FILES macro where XXX matches the appropriate
|
|---|
| 364 | AM_CONDITIONAL symbol. XXX_SOURCE_FILES must be added to EXTRA_DIST
|
|---|
| 365 | and the following added above the INCLUDES macro:
|
|---|
| 366 |
|
|---|
| 367 | if XXX
|
|---|
| 368 | libarch_a_SOURCES = \
|
|---|
| 369 | $(COMMON_SOURCE_FILES) \
|
|---|
| 370 | $(XXX_SOURCE_FILES) \
|
|---|
| 371 | $(NULL)
|
|---|
| 372 | endif
|
|---|
| 373 |
|
|---|
| 374 | Implementing lib/platform:
|
|---|
| 375 |
|
|---|
| 376 | Most of the remaining platform dependent code lives in lib/platform.
|
|---|
| 377 | The code there implements platform dependent window, clipboard, keyboard
|
|---|
| 378 | and screen saver handling. If a platform is named XXX then the following
|
|---|
| 379 | classes should be derived and implemented:
|
|---|
| 380 |
|
|---|
| 381 | * CXXXClipboard : IClipboard
|
|---|
| 382 | Provides clipboard operations. Typically, this class will
|
|---|
| 383 | have helper classes for converting between various clipboard
|
|---|
| 384 | data formats.
|
|---|
| 385 |
|
|---|
| 386 | * CXXXEventQueueBuffer : IEventQueueBuffer
|
|---|
| 387 | Provides operations for waiting for, posting and retrieving events.
|
|---|
| 388 | Also provides operations for creating and deleting timers.
|
|---|
| 389 |
|
|---|
| 390 | * CXXXKeyState : CKeyState
|
|---|
| 391 | Provides operations for synthesizing key events and for mapping a
|
|---|
| 392 | key ID to a sequence of events to generate that key.
|
|---|
| 393 |
|
|---|
| 394 | * CXXXScreen : IScreen, IPrimaryScreen, ISecondaryScreen, IPlatformScreen
|
|---|
| 395 | Provides screen operations.
|
|---|
| 396 |
|
|---|
| 397 | * CXXXScreenSaver : IScreenSaver
|
|---|
| 398 | Provides screen saver operations.
|
|---|
| 399 |
|
|---|
| 400 | If using automake, the Makefile.am should list the window system
|
|---|
| 401 | specific files in a XXX_SOURCE_FILES macro where XXX matches the
|
|---|
| 402 | appropriate AM_CONDITIONAL symbol. XXX_SOURCE_FILES must be added
|
|---|
| 403 | to EXTRA_DIST and the following added above the INCLUDES macro:
|
|---|
| 404 |
|
|---|
| 405 | if XXX
|
|---|
| 406 | libplatform_a_SOURCES = $(XXX_SOURCE_FILES)
|
|---|
| 407 | endif
|
|---|
| 408 |
|
|---|
| 409 | Tweaks:
|
|---|
| 410 |
|
|---|
| 411 | Finally, each platform typically requires various adjustments here
|
|---|
| 412 | and there. In particular, synergyc.cpp and synergys.cpp usually
|
|---|
| 413 | require platform dependent code for the main entry point, parsing
|
|---|
| 414 | arguments, and reporting errors. Also, some platforms may benefit
|
|---|
| 415 | from a graphical user interface front end. These are generally
|
|---|
| 416 | not portable and synergy doesn't provide any infrastructure for
|
|---|
| 417 | the code common to any platform, though it may do so someday.
|
|---|
| 418 | There is, however, an implementation of a GUI front end for Windows
|
|---|
| 419 | that serves as an example.
|
|---|