diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2012-02-18 20:12:22 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2012-02-18 20:12:22 +0400 |
commit | 746e712f7a319f8db44fd29f91c88227bfc31cc6 (patch) | |
tree | f5a7af55b14d4a556a13f1f59c0e0837fa6fbde4 /extern | |
parent | 62d09c9103f07c86c484d2a044a8884c337a92a3 (diff) | |
parent | e6b708b36bb77ff2287439f20fc79097c275c822 (diff) |
Merging r44140 through r44226 from trunk into soc-2011-tomato
Diffstat (limited to 'extern')
33 files changed, 2401 insertions, 1347 deletions
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 8442e5d0c71..1d83410a3d7 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -71,3 +71,9 @@ endif() if(WITH_CARVE) add_subdirectory(carve) endif() + +if(WITH_GHOST_XDND) + if(UNIX AND NOT APPLE) + add_subdirectory(xdnd) + endif() +endif() diff --git a/extern/SConscript b/extern/SConscript index 738342b3dcc..67b74e9ee91 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -34,3 +34,8 @@ if env['WITH_BF_LIBMV']: if env['WITH_BF_CARVE']: SConscript(['carve/SConscript']) + +if env['WITH_GHOST_XDND']: + # FreeBSD doesn't seems to support XDND protocol + if env['OURPLATFORM'] in ('linux', 'openbsd3', 'sunos5', 'aix4', 'aix5'): + SConscript(['xdnd/SConscript']) diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 075ff15a798..73c2baa0207 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -41,107 +41,107 @@ set(INC_SYS set(SRC libmv-capi.cpp + libmv/image/array_nd.cc + libmv/image/convolve.cc + libmv/multiview/conditioning.cc + libmv/multiview/euclidean_resection.cc + libmv/multiview/fundamental.cc + libmv/multiview/projection.cc + libmv/multiview/triangulation.cc libmv/numeric/numeric.cc libmv/numeric/poly.cc + libmv/simple_pipeline/bundle.cc libmv/simple_pipeline/callbacks.cc - libmv/simple_pipeline/reconstruction.cc - libmv/simple_pipeline/resect.cc - libmv/simple_pipeline/intersect.cc - libmv/simple_pipeline/initialize_reconstruction.cc libmv/simple_pipeline/camera_intrinsics.cc - libmv/simple_pipeline/pipeline.cc libmv/simple_pipeline/detect.cc + libmv/simple_pipeline/initialize_reconstruction.cc + libmv/simple_pipeline/intersect.cc + libmv/simple_pipeline/pipeline.cc + libmv/simple_pipeline/reconstruction.cc + libmv/simple_pipeline/resect.cc libmv/simple_pipeline/tracks.cc - libmv/simple_pipeline/bundle.cc - libmv/image/convolve.cc - libmv/image/array_nd.cc - libmv/tracking/pyramid_region_tracker.cc - libmv/tracking/sad.cc libmv/tracking/brute_region_tracker.cc - libmv/tracking/hybrid_region_tracker.cc libmv/tracking/esm_region_tracker.cc - libmv/tracking/trklt_region_tracker.cc + libmv/tracking/hybrid_region_tracker.cc libmv/tracking/klt_region_tracker.cc libmv/tracking/lmicklt_region_tracker.cc + libmv/tracking/pyramid_region_tracker.cc libmv/tracking/retrack_region_tracker.cc - libmv/multiview/projection.cc - libmv/multiview/conditioning.cc - libmv/multiview/fundamental.cc - libmv/multiview/euclidean_resection.cc - libmv/multiview/triangulation.cc + libmv/tracking/sad.cc + libmv/tracking/trklt_region_tracker.cc - third_party/ssba/Geometry/v3d_metricbundle.cpp - third_party/ssba/Math/v3d_optimization.cpp - third_party/gflags/gflags.cc - third_party/gflags/gflags_reporting.cc - third_party/gflags/gflags_completions.cc - third_party/fast/fast_9.c third_party/fast/fast_10.c third_party/fast/fast_11.c third_party/fast/fast_12.c + third_party/fast/fast_9.c third_party/fast/fast.c third_party/fast/nonmax.c + third_party/gflags/gflags.cc + third_party/gflags/gflags_completions.cc + third_party/gflags/gflags_reporting.cc third_party/ldl/Source/ldl.c + third_party/ssba/Geometry/v3d_metricbundle.cpp + third_party/ssba/Math/v3d_optimization.cpp libmv-capi.h + libmv/base/id_generator.h + libmv/base/scoped_ptr.h + libmv/base/vector.h + libmv/base/vector_utils.h + libmv/image/array_nd.h + libmv/image/convolve.h + libmv/image/image.h + libmv/image/sample.h + libmv/image/tuple.h libmv/logging/logging.h + libmv/multiview/conditioning.h + libmv/multiview/euclidean_resection.h + libmv/multiview/fundamental.h + libmv/multiview/nviewtriangulation.h + libmv/multiview/projection.h + libmv/multiview/resection.h + libmv/multiview/triangulation.h libmv/numeric/dogleg.h - libmv/numeric/levenberg_marquardt.h - libmv/numeric/poly.h libmv/numeric/function_derivative.h + libmv/numeric/levenberg_marquardt.h libmv/numeric/numeric.h + libmv/numeric/poly.h + libmv/simple_pipeline/bundle.h libmv/simple_pipeline/callbacks.h - libmv/simple_pipeline/resect.h - libmv/simple_pipeline/reconstruction.h libmv/simple_pipeline/camera_intrinsics.h - libmv/simple_pipeline/tracks.h libmv/simple_pipeline/detect.h - libmv/simple_pipeline/pipeline.h - libmv/simple_pipeline/intersect.h - libmv/simple_pipeline/bundle.h libmv/simple_pipeline/initialize_reconstruction.h - libmv/image/convolve.h - libmv/image/tuple.h - libmv/image/array_nd.h - libmv/image/sample.h - libmv/image/image.h - libmv/tracking/region_tracker.h + libmv/simple_pipeline/intersect.h + libmv/simple_pipeline/pipeline.h + libmv/simple_pipeline/reconstruction.h + libmv/simple_pipeline/resect.h + libmv/simple_pipeline/tracks.h libmv/tracking/brute_region_tracker.h + libmv/tracking/esm_region_tracker.h libmv/tracking/hybrid_region_tracker.h + libmv/tracking/klt_region_tracker.h + libmv/tracking/lmicklt_region_tracker.h + libmv/tracking/pyramid_region_tracker.h + libmv/tracking/region_tracker.h libmv/tracking/retrack_region_tracker.h libmv/tracking/sad.h - libmv/tracking/pyramid_region_tracker.h - libmv/tracking/esm_region_tracker.h libmv/tracking/trklt_region_tracker.h - libmv/tracking/klt_region_tracker.h - libmv/tracking/lmicklt_region_tracker.h - libmv/base/id_generator.h - libmv/base/vector.h - libmv/base/scoped_ptr.h - libmv/base/vector_utils.h - libmv/multiview/nviewtriangulation.h - libmv/multiview/resection.h - libmv/multiview/euclidean_resection.h - libmv/multiview/triangulation.h - libmv/multiview/projection.h - libmv/multiview/fundamental.h - libmv/multiview/conditioning.h - third_party/ssba/Geometry/v3d_metricbundle.h - third_party/ssba/Geometry/v3d_cameramatrix.h - third_party/ssba/Geometry/v3d_distortion.h - third_party/ssba/Math/v3d_linear_utils.h - third_party/ssba/Math/v3d_optimization.h - third_party/ssba/Math/v3d_mathutilities.h - third_party/ssba/Math/v3d_linear.h - third_party/gflags/gflags_completions.h - third_party/gflags/mutex.h + third_party/fast/fast.h third_party/gflags/config.h + third_party/gflags/gflags_completions.h third_party/gflags/gflags.h - third_party/fast/fast.h + third_party/gflags/mutex.h third_party/ldl/Include/ldl.h - third_party/msinttypes/stdint.h third_party/msinttypes/inttypes.h + third_party/msinttypes/stdint.h + third_party/ssba/Geometry/v3d_cameramatrix.h + third_party/ssba/Geometry/v3d_distortion.h + third_party/ssba/Geometry/v3d_metricbundle.h + third_party/ssba/Math/v3d_linear.h + third_party/ssba/Math/v3d_linear_utils.h + third_party/ssba/Math/v3d_mathutilities.h + third_party/ssba/Math/v3d_optimization.h ) if(WIN32) @@ -152,23 +152,23 @@ if(WIN32) third_party/glog/src/vlog_is_on.cc third_party/glog/src/windows/port.cc - third_party/glog/src/config.h - third_party/glog/src/stacktrace.h + third_party/glog/src/utilities.h third_party/glog/src/stacktrace_generic-inl.h - third_party/glog/src/stacktrace_libunwind-inl.h - third_party/glog/src/stacktrace_powerpc-inl.h - third_party/glog/src/stacktrace_x86-inl.h + third_party/glog/src/stacktrace.h third_party/glog/src/stacktrace_x86_64-inl.h - third_party/glog/src/utilities.h - third_party/glog/src/base/commandlineflags.h third_party/glog/src/base/googleinit.h third_party/glog/src/base/mutex.h - third_party/glog/src/windows/config.h - third_party/glog/src/windows/port.h - third_party/glog/src/windows/glog/log_severity.h - third_party/glog/src/windows/glog/logging.h + third_party/glog/src/base/commandlineflags.h + third_party/glog/src/stacktrace_powerpc-inl.h + third_party/glog/src/stacktrace_x86-inl.h + third_party/glog/src/config.h + third_party/glog/src/stacktrace_libunwind-inl.h third_party/glog/src/windows/glog/raw_logging.h third_party/glog/src/windows/glog/vlog_is_on.h + third_party/glog/src/windows/glog/logging.h + third_party/glog/src/windows/glog/log_severity.h + third_party/glog/src/windows/port.h + third_party/glog/src/windows/config.h ) list(APPEND INC @@ -190,34 +190,34 @@ if(WIN32) endif() else() list(APPEND SRC - third_party/glog/src/utilities.cc - third_party/glog/src/symbolize.cc - third_party/glog/src/vlog_is_on.cc - third_party/glog/src/signalhandler.cc - third_party/glog/src/logging.cc third_party/glog/src/demangle.cc + third_party/glog/src/logging.cc third_party/glog/src/raw_logging.cc + third_party/glog/src/signalhandler.cc + third_party/glog/src/symbolize.cc + third_party/glog/src/utilities.cc + third_party/glog/src/vlog_is_on.cc - third_party/glog/src/config.h + third_party/glog/src/base/commandlineflags.h + third_party/glog/src/base/googleinit.h + third_party/glog/src/base/mutex.h third_party/glog/src/config_freebsd.h + third_party/glog/src/config.h third_party/glog/src/config_linux.h third_party/glog/src/config_mac.h third_party/glog/src/demangle.h - third_party/glog/src/stacktrace.h + third_party/glog/src/glog/logging.h + third_party/glog/src/glog/log_severity.h + third_party/glog/src/glog/raw_logging.h + third_party/glog/src/glog/vlog_is_on.h third_party/glog/src/stacktrace_generic-inl.h + third_party/glog/src/stacktrace.h third_party/glog/src/stacktrace_libunwind-inl.h third_party/glog/src/stacktrace_powerpc-inl.h - third_party/glog/src/stacktrace_x86-inl.h third_party/glog/src/stacktrace_x86_64-inl.h + third_party/glog/src/stacktrace_x86-inl.h third_party/glog/src/symbolize.h third_party/glog/src/utilities.h - third_party/glog/src/base/commandlineflags.h - third_party/glog/src/base/googleinit.h - third_party/glog/src/base/mutex.h - third_party/glog/src/glog/log_severity.h - third_party/glog/src/glog/logging.h - third_party/glog/src/glog/raw_logging.h - third_party/glog/src/glog/vlog_is_on.h ) list(APPEND INC diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog index 7e10abfead6..f49a07de350 100644 --- a/extern/libmv/ChangeLog +++ b/extern/libmv/ChangeLog @@ -1,3 +1,359 @@ +commit 75b9af405964ff2c7d3f0a44500e27e63b37c91b +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 23:29:11 2012 +0600 + + _USE_MATH_DEFINES is needed to define constants like M_E when building with msvc + Occasionally was removed, but now added comment about this so hopefully it + wouldn't removed again. + +commit f85b1232a9b929f69443b5eed6e7a39908cd6551 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 21:34:40 2012 +0600 + + Picky edit: corrected mode for ssba readme file. + +commit f8c2b223f01551fd81a85f6d5221646165147035 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 21:32:05 2012 +0600 + + Picky edits: corrected EOL + +commit 3f2a4205ec5adadcdfa306b161c705c868a7be93 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 21:30:07 2012 +0600 + + Fixed incorrect access to ucontext on linux. Caused by incorrect merge conflict resolve. + +commit d360a21a5aa125cf9e83dd26b302508688ff7007 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 20:54:13 2012 +0600 + + More Windows -> Unix EOL conversions + +commit 18aeda58bec9556140ba617724e31ada6f5b67c0 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 20:15:42 2012 +0600 + + Looks like this debug output was removed accidentally. + +commit 189dc0cacdee3c1eab68c43263ecb038ed244c09 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 20:11:56 2012 +0600 + + Made V3D verbose again by default + +commit 8b3422d3eec5e450d76243886bf07fb0a3e83a81 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 20:08:01 2012 +0600 + + SAD tracker now can deal with pattern size any size, + Very quick implementation came from Blender before Hybrid tracker was added. + Better to be replaced with brute tracker. + +commit d547c9cfe37d5d3397d33c8b0e58471e1e1c1634 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 20:03:52 2012 +0600 + + Just convert end of lines to unix style. + +commit eb73ddbaec5b9e1ad30331bbf858a6ebc266c4aa +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 20:02:20 2012 +0600 + + Made some function static. Resolves possible linking issues when building with MinGW. + +commit 2930681fafd86e4f4a958054b1db8bfff29623d1 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 19:59:45 2012 +0600 + + Missed this in commit with improvements in camera intrinsics. + +commit 8d31bc767019b05c5bf8c9f309f9545b3428afa1 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 19:57:51 2012 +0600 + + Another step of syncing codebase with Blender. + Mainly fixes for freebsd/osx compilation and aligned memory allocation. + +commit 3214a2df5bfd98021f25d0f1a626a86318bb245f +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 19:48:02 2012 +0600 + + Support compilation on FreeBSD platform + +commit 0e5abe96f543687ccfb3a923ec639cb8f45d54f8 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 19:44:18 2012 +0600 + + Implementation of basic system for progress reporting into callee stuff + + Implemented by using simple callbacks classes which are getting invoked from + places where lots of calculation happens, so applications which are using + libmv may display nice progress bar. + +commit c5e18fe35464618055e0e9761be8d22fae56db49 +Author: Keir Mierle <mierle@gmail.com> +Date: Fri Feb 17 19:25:45 2012 +0600 + + Add support for detecting tracking failure in the ESM tracker component of + libmv. Since both KLT and Hybrid rely on ESM underneath, KLT and Hybrid now + have a minimum correlation setting to match. With this fix, track failures + should get detected quicker, with the issue that sometimes the tracker will + give up too easily. That is fixable by reducing the required correlation (in + the track properties). + +commit ea0fed736ecdcc8c020227aeef8ef4cd3be5e63d +Author: Keir Mierle <mierle@gmail.com> +Date: Fri Feb 17 19:23:50 2012 +0600 + + Add a new hybrid region tracker for motion tracking to libmv, and + add it as an option (under "Hybrid") in the tracking settings. The + region tracker is a combination of brute force tracking for coarse + alignment, then refinement with the ESM/KLT algorithm already in + libmv that gives excellent subpixel precision (typically 1/50'th + of a pixel) + + This also adds a new "brute force" region tracker which does a + brute force search through every pixel position in the destination + for the pattern in the first frame. It leverages SSE if available, + similar to the SAD tracker, to do this quickly. Currently it does + some unnecessary conversions to/from floating point that will get + fixed later. + + The hybrid tracker glues the two trackers (brute & ESM) together + to get an overall better tracker. The algorithm is simple: + + 1. Track from frame 1 to frame 2 with the brute force tracker. + This tries every possible pixel position for the pattern from + frame 1 in frame 2. The position with the smallest + sum-of-absolute-differences is chosen. By definition, this + position is only accurate up to 1 pixel or so. + 2. Using the result from 1, initialize a track with ESM. This does + a least-squares fit with subpixel precision. + 3. If the ESM shift was more than 2 pixels, report failure. + 4. If the ESM track shifted less than 2 pixels, then the track is + good and we're done. The rationale here is that if the + refinement stage shifts more than 1 pixel, then the brute force + result likely found some random position that's not a good fit. + +commit a07fff8431621c01d81ae52595d8dd91a295a776 +Author: Keir Mierle <mierle@gmail.com> +Date: Fri Feb 17 19:19:58 2012 +0600 + + Assorted camera tracker improvements + + - Add support for refining the camera's intrinsic parameters + during a solve. Currently, refining supports only the following + combinations of intrinsic parameters: + + f + f, cx, cy + f, cx, cy, k1, k2 + f, k1 + f, k1, k2 + + This is not the same as autocalibration, since the user must + still make a reasonable initial guess about the focal length and + other parameters, whereas true autocalibration would eliminate + the need for the user specify intrinsic parameters at all. + + However, the solver works well with only rough guesses for the + focal length, so perhaps full autocalibation is not that + important. + + Adding support for the last two combinations, (f, k1) and (f, + k1, k2) required changes to the library libmv depends on for + bundle adjustment, SSBA. These changes should get ported + upstream not just to libmv but to SSBA as well. + + - Improved the region of convergence for bundle adjustment by + increasing the number of Levenberg-Marquardt iterations from 50 + to 500. This way, the solver is able to crawl out of the bad + local minima it gets stuck in when changing from, for example, + bundling k1 and k2 to just k1 and resetting k2 to 0. + + - Add several new region tracker implementations. A region tracker + is a libmv concept, which refers to tracking a template image + pattern through frames. The impact to end users is that tracking + should "just work better". I am reserving a more detailed + writeup, and maybe a paper, for later. + + - Other libmv tweaks, such as detecting that a tracker is headed + outside of the image bounds. + + This includes several changes made directly to the libmv extern + code rather expecting to get those changes through normal libmv + channels, because I, the libmv BDFL, decided it was faster to work + on libmv directly in Blender, then later reverse-port the libmv + changes from Blender back into libmv trunk. The interesting part + is that I added a full Levenberg-Marquardt loop to the region + tracking code, which should lead to a more stable solutions. I + also added a hacky implementation of "Efficient Second-Order + Minimization" for tracking, which works nicely. A more detailed + quantitative evaluation will follow. + +commit 0bf66c009d5022eacfc473d247884a73ffeefa8f +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 19:13:49 2012 +0600 + + Rest of compilation fix with FAST library. + +commit 71b578ca2ba34c528363c514cd1fcc85791d01f3 +Author: Keir Mierle <mierle@gmail.com> +Date: Fri Feb 17 19:00:28 2012 +0600 + + Improve the KLT tracking behaviour and UI + + - Remove the overly-conservative use of libmv's re-track tracker. The re-track + tracker would take a normal tracker such as TRKLT or KLT or pyramid KLT, and + track from frame 1 to 2, then back from the position found in 2 back to 1. + Then, when the reverse-track doesn't match the original track with high + precision, the track is considered "failed". This is a good approach for + fully automatic reconstruction, but is too conservative for supervised + tracking. + + The retrack-tracker will return when fully automatic tracking is added. + + - Always solve for (dx, dy) in the TRKLT loop even if the linear system is + ill-conditioned. The client (Blender in this case) can still use the solved + position, even though it is less reliable. + +commit 7d8a8762f2bc2e36f95b0b6f4fb4ca996f9f0db7 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 18:46:24 2012 +0600 + + Changes in camera intrinsics distortion/undistortion: + + - Distortion/undistortion of scaled images wasn't happening right, + because camera intrinsics are calibrated on an original frame which + has got some particular resolution and trying to apply this model on + an image with another resolution gives totally wrong result. + This is needed to be able to do post-prccessing of render, running + distortion on a scene which might be rendered with higher resolution + than footage itself and then be scaled down. + - Fixed incorrect calculation/applying of precomputed grid when + distortion is high high enough and produces pixel offset higher + than 127 pixels. This might be still not very distorted image, + but if it's a 4K footage "normal" camera will easily give such + a distortion. + - Added support of overscan distortion/undistortion. + +commit ed080785d63bb8e3a13dde51a2dc94fe59b059bb +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 18:38:51 2012 +0600 + + Fast headers now can be included from C++ sources. + Was needed to make it working fine when bundling in Blender but might also + be needed to bundle into another applications. + +commit 5f5a7aa46a2d87b96c8098dfc8682f4d01b5cd40 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 18:36:16 2012 +0600 + + Bring back FAST detector which seems to be working much nicer than Morravec. + Both of them are available in API. + +commit 2cab13c18216fb684b270cec077f7300262584af +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 18:27:36 2012 +0600 + + Revert "Make CameraIntrinsics (and thus Qt tracker) compilable without linking libmv." + + This reverts commit 81613ee0cc94b315f333c9632b18b95d426aad05. + + That commit made inverting intrinsics totally unworkable, so reverted this and + made needed tweaks to qt-tracker project file to make it compilable (was needed + to make it linking together with glog). + + Conflicts: + + src/ui/tracker/tracker.cc + src/ui/tracker/tracker.pro + +commit ec46cae041401b17afb4fe4d9c9343d10797090f +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 17:59:55 2012 +0600 + + Fix compilation error using official MinGW + +commit 6fbc370e922c47cfa35381662b6c439f4891ed74 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 17:38:20 2012 +0600 + + Fix compilation error with MSVC 2010 which is more picky for "missed" STL headers + +commit be9e6b63691d83b551a085f0766878bd84220767 +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 17:36:18 2012 +0600 + + Fix compilation with MSVC where snprintf function is declared as unsafe and _snprintf should be used instead. + + Better to switch to own implementation will ensure string is correctly NULL-terminated. + +commit 1847d9e414ed763cd80668775d7d9f79575fc8ca +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 17:34:45 2012 +0600 + + Fix compilation error on OSX caused by incorrect access to ucontext + +commit 90579b6ffad07672172a1c240499615b30b25549 +Merge: b9aac30 531c79b +Author: Sergey Sharybin <sergey.vfx@gmail.com> +Date: Fri Feb 17 18:32:52 2012 +0600 + + Merge remote-tracking branch 'Matthias-Fauconneau/master' into devel + + Conflicts: + src/libmv/tracking/CMakeLists.txt + +commit b9aac30a9ca6bc8362c09a0e191040964f7c6de2 +Merge: 198894e 6969e1a +Author: Keir Mierle <mierle@gmail.com> +Date: Sat Nov 5 17:38:30 2011 -0700 + + Merge pull request #3 from nathanwiegand/master + + Just a few tiny cleanups + +commit 6969e1a9534291a982749baa5a3672c97bfa506d +Author: Nathan Wiegand <nathanwiegand@gmail.com> +Date: Sat Nov 5 14:26:54 2011 -0700 + + I've added cleaned up a few style issues here an there. Also, I've updated the CMakeLists.txt file so that it can build the image_io library. Note, it's only been tested on OSX 10.6 + +commit 4763f851299050140757bfaa069107a0cf639e56 +Author: Nathan Wiegand <nathanwiegand@gmail.com> +Date: Fri Nov 4 23:59:08 2011 -0700 + + Removed a superfulous comment + +commit a44577c0162e273681e4a9a3cc5f5b37d4315b67 +Author: Nathan Wiegand <nathanwiegand@gmail.com> +Date: Fri Nov 4 23:55:52 2011 -0700 + + Removed a duplicate entry for an author. + +commit 198894e4c4f51c2c1784ad7c02eb45d2d1ada9bc +Merge: c4c67db 6e797d6 +Author: Keir Mierle <mierle@gmail.com> +Date: Fri Nov 4 21:47:05 2011 -0700 + + Merge pull request #2 from nathanwiegand/master + + CMake changes for OSX + +commit 6e797d678c4c19f6a9e21657d66183f412cc995b +Author: Nathan Wiegand <nathanwiegand@gmail.com> +Date: Fri Nov 4 21:43:28 2011 -0700 + + Uncomment the GUI part of the CMake file + +commit 33ef88a33860345d8906f3c9dd22d8dbce3df53e +Author: Nathan Wiegand <nathanwiegand@gmail.com> +Date: Fri Nov 4 21:31:22 2011 -0700 + + Fixed build error on OSX by adding 'glog' to the dependencies in the tracker CMake + commit 531c79bf95fddaaa70707d1abcd4fdafda16bbf0 Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> Date: Sat Aug 20 00:00:42 2011 +0200 @@ -91,222 +447,3 @@ Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> Date: Thu Aug 18 20:51:43 2011 +0200 Fix detect.cc. - -commit ec18cc5ea9ae2e641075a847e82d0aacb8415ad8 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Thu Aug 18 17:45:37 2011 +0200 - - Compute and return Pearson product-moment correlation coefficient between reference and matched pattern. - -commit 21d4245c63a01bfc736192d55baf10983e7c9ec7 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Thu Aug 18 16:18:44 2011 +0200 - - UI and API support for affine tracking. - -commit a4876d8c40dcde615b44009c38c49e9a1b1d4698 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Aug 17 20:26:01 2011 +0200 - - Hack to make sad.cc compile with MSVC on system without support for the SSE instruction set. - -commit 0de723dfce5bbe44dbd19be8cd6dd6e9b03b7924 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Aug 17 20:10:46 2011 +0200 - - Fix slow path (for computers without SSE2). - Heap allocate scores in detect.cc - -commit 65a9d496f81e8b37eae39a4063957b8be9a4e6f0 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Aug 17 19:25:17 2011 +0200 - - Fix compilation on OSX. - -commit d22720e618456329388d2c107422c3b371657cba -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Aug 17 14:14:45 2011 +0200 - - Improve Detect and SAD Tracker API and documentation. - -commit 5d6cd4ad365b061901bad40695b51d568487a0cf -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Aug 17 11:57:29 2011 +0200 - - MSVC support fixes. - -commit 50f0323173c6deebd6aaf9c126f0b51b2a79c3c1 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 23:21:37 2011 +0200 - - Detector can detect features similar to a given pattern. - -commit 5734cc27bbf84c2b6edcfcc1ea736798e12d5820 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 22:53:54 2011 +0200 - - Ensure SAD Tracker is C compatible. - Update Detect API documentation. - -commit 701c42842574064fea992f8822e3899cb9066108 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 21:56:42 2011 +0200 - - Remove FAST detector. - Add Moravec detector. - This detector is more suited to tracking since it try to choose patterns which are unlikely to drift by computing SAD with neighbouring patches. - It could be improved to better avoid edges. - -commit 9bdf93e13fc880c78b6f34397da673388c16040e -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 21:55:08 2011 +0200 - - Fix Qt Tracker GL to work with AMD drivers. - -commit 81613ee0cc94b315f333c9632b18b95d426aad05 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 21:54:12 2011 +0200 - - Make CameraIntrinsics (and thus Qt tracker) compilable without linking libmv. - -commit a1d9a8fa8b01ef7cf2a79b3b891633fc333fc9cf -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 21:24:51 2011 +0200 - - Fix SAD tracker. Pattern was transposed by affine pattern sampler. - -commit c3b794da2e7fd23f2fbdf90dbd71de0e6b3bc811 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 16 21:19:02 2011 +0200 - - Fix SAD tracker. Pattern was transposed by affine pattern sampler. - -commit a9b61bf3356f27174cdd983f562f99c3a6a2cc35 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Sun Aug 14 09:56:51 2011 +0200 - - Clarify CameraIntrinsics documentation. - Edit CameraInstrinsics test to fail. - -commit 10bdad9ad2cea2603896263cde5a5339169a9af0 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Fri Aug 12 21:05:32 2011 +0200 - - Fix out of bound access in warp bilinear sampling. - -commit dd9a418db021a28af2c1198d5e5b9e68fe048a03 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Fri Aug 12 19:14:36 2011 +0200 - - Fix compilation with -funsigned-char. - -commit bd1a268ede39b67f2ba4b360f6fc693419e7cd7f -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Fri Aug 12 18:39:27 2011 +0200 - - CameraIntrinsics fixes. - -commit ae513b39fb779632f96ceff7c1e014fb8e68702a -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 19:38:58 2011 +0200 - - Remove stray QDebug include. - -commit 1e58f55078ce6009a885be30ae0316aec6ed8239 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 14:16:31 2011 +0200 - - Make API future-proof (for an eventual affine or planar tracker). - -commit c2af303e7bf0dddcb02937323ac5846b1801e6cc -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 11:13:29 2011 +0200 - - Remove reconstruction breaking debug code. - -commit 8792a633e5c5f1c1f12e164b9e8897ca0790ac59 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 10:49:18 2011 +0200 - - Remove getchar()s. - -commit 63a9bdee0cbd1197e0315d01c27bfc2361bd5656 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 10:35:07 2011 +0200 - - Adapt patch to new PipelineRoutines code generation strategy. - -commit 096ff1a4070f7212c50fb0a4b2feec7ca9d97158 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 09:54:12 2011 +0200 - - Merge max_image and max_track fix from tomato. - -commit d8450cd3c37278a397482cd36b1e2419f154cfb9 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Tue Aug 9 09:38:49 2011 +0200 - - Synchronize tree with Tomato: Merge patch for better resection, keep deprecated KLT tracker. - -commit e9b2dca920cf9575c15150a4988634b00e343a41 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Mon Aug 8 17:07:08 2011 +0200 - - Fixes, Documentation. - -commit 4fc1c57a2d92442808ac4a3676e6d9a25a51e310 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Sun Aug 7 14:35:08 2011 +0200 - - Improve tracker resilience by penalizing large motion vectors. - -commit cc8e7e8e08cd91f75c080a0091461ca9fe969664 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Sun Aug 7 09:28:09 2011 +0200 - - Leverage SSE2 SAD instruction for 16x speed improvement in integer pixel search resulting in ~1ms per marker for 16x16 pattern on 128x128 region. - -commit f362ab4999a768370fca57552464b459eb9fbddc -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Sun Aug 7 09:06:04 2011 +0200 - - Improve SAD Tracker subpixel precision (avoid drift even when adapting at each frame). - -commit fce7a214c561b5f5f0e17115c31fb48814bde2db -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Sat Aug 6 21:57:06 2011 +0200 - - Track using simple Sum of Absolute Differences matching. - This method is simpler, more robust, faster and accurate. - -commit 620a7a35d9a2818bf6e9dbf5d11debda4be6bc26 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Fri Jul 29 12:35:57 2011 +0200 - - Add Intersect unit test. - -commit a2bf58fa57be11215eb17ff7f7de58f97d480ec3 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Thu Jul 28 11:08:06 2011 +0200 - - Remove tests depending on dead code. - Fix CameraIntrinsics test. - Add Intersect and Resect tests. - -commit 19bddee10b4879c8cd2238ccdf5b8f7620cf8384 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Jul 27 12:07:21 2011 +0200 - - Image Distortion: Fixes and more testing. - -commit 0454d97da328fb0eda8c6c50511ac31864a6d3d6 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Jul 27 10:32:37 2011 +0200 - - Test float image distortion. - -commit 8db01595a8721f766d85931a8d92b780461d8741 -Author: Matthias Fauconneau <matthias.fauconneau@gmail.com> -Date: Wed Jul 27 10:27:07 2011 +0200 - - Image Distortion: Bilinear sampling, Optimization, Instantiate all variants (Distort/Undistort, float/ubyte, 1-4 channels). diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index f5cfcc0d488..f259635035e 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -1,7 +1,8 @@ #!/bin/sh #BRANCH="keir" -BRANCH="Matthias-Fauconneau" +#BRANCH="Matthias-Fauconneau" +BRANCH="Nazg-Gul" if [ -d ./.svn ]; then echo "This script is supposed to work only when using git-svn" @@ -24,7 +25,7 @@ done rm -rf libmv rm -rf third_party -cat "files.txt" | while f=`line`; do +cat "files.txt" | while read f; do mkdir -p `dirname $f` cp $tmp/libmv/src/$f $f done @@ -36,14 +37,14 @@ chmod 664 ./third_party/glog/src/windows/*.cc ./third_party/glog/src/windows/*.h sources=`find ./libmv -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d` headers=`find ./libmv -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` -third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | sed -r 's/^\.\//\t/' | sort` -third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | sed -r 's/^\.\//\t/' | sort` +third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d` +third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d` -third_glog_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort` -third_glog_headers=`find ./third_party -type f -iname '*.h' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort` +third_glog_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d` +third_glog_headers=`find ./third_party -type f -iname '*.h' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d` -src_dir=`find ./libmv -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort | uniq` -src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort | uniq` +src_dir=`find ./libmv -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` +src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq` src="" win_src="" for x in $src_dir $src_third_dir; do @@ -103,7 +104,7 @@ cat > CMakeLists.txt << EOF # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # The Original Code is Copyright (C) 2011, Blender Foundation # All rights reserved. diff --git a/extern/libmv/libmv/base/vector.h b/extern/libmv/libmv/base/vector.h index 9dc48676629..c2a3298087a 100644 --- a/extern/libmv/libmv/base/vector.h +++ b/extern/libmv/libmv/base/vector.h @@ -84,6 +84,8 @@ class vector { T& front() { return data_[0]; } const T& operator[](int n) const { return data_[n]; } T& operator[](int n) { return data_[n]; } + const T& at(int n) const { return data_[n]; } + T& at(int n) { return data_[n]; } const T * begin() const { return data_; } const T * end() const { return data_+size_; } T * begin() { return data_; } diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.cc b/extern/libmv/libmv/simple_pipeline/pipeline.cc index 382365e579f..2e4e5a6491d 100644 --- a/extern/libmv/libmv/simple_pipeline/pipeline.cc +++ b/extern/libmv/libmv/simple_pipeline/pipeline.cc @@ -279,25 +279,7 @@ double InternalReprojectionError(const Tracks &image_tracks, PipelineRoutines::ProjectMarker(*point, *camera, intrinsics); double ex = reprojected_marker.x - markers[i].x; double ey = reprojected_marker.y - markers[i].y; -#if 0 - const int N = 100; - char line[N]; - snprintf(line, N, - "image %-3d track %-3d " - "x %7.1f y %7.1f " - "rx %7.1f ry %7.1f " - "ex %7.1f ey %7.1f" - " e %7.1f", - markers[i].image, - markers[i].track, - markers[i].x, - markers[i].y, - reprojected_marker.x, - reprojected_marker.y, - ex, - ey, - sqrt(ex*ex + ey*ey)); -#endif + total_error += sqrt(ex*ex + ey*ey); } LG << "Skipped " << num_skipped << " markers."; diff --git a/extern/libmv/libmv/simple_pipeline/tracks.h b/extern/libmv/libmv/simple_pipeline/tracks.h index 739c3c4f243..aa0fbaa6e4c 100644 --- a/extern/libmv/libmv/simple_pipeline/tracks.h +++ b/extern/libmv/libmv/simple_pipeline/tracks.h @@ -27,13 +27,13 @@ namespace libmv { /*! A Marker is the 2D location of a tracked point in an image. - + \a x, \a y is the position of the marker in pixels from the top left corner in the image identified by \a image. All markers for to the same target form a track identified by a common \a track number. - + \note Markers are typically aggregated with the help of the \l Tracks class. - + \sa Tracks */ struct Marker { @@ -44,18 +44,18 @@ struct Marker { /*! The Tracks class stores \link Marker reconstruction markers \endlink. - + The Tracks container is intended as the store of correspondences between images, which must get created before any 3D reconstruction can take place. - + The container has several fast lookups for queries typically needed for structure from motion algorithms, such as \l MarkersForTracksInBothImages(). - + \sa Marker */ class Tracks { public: - Tracks() {} + Tracks() { } // Copy constructor for a tracks object. Tracks(const Tracks &other); @@ -67,10 +67,10 @@ class Tracks { Inserts a marker into the set. If there is already a marker for the given \a image and \a track, the existing marker is replaced. If there is no marker for the given \a image and \a track, a new one is added. - + \a image and \a track are the keys used to retrieve the markers with the other methods in this class. - + \note To get an identifier for a new track, use \l MaxTrack() + 1. */ void Insert(int image, int track, double x, double y); @@ -86,7 +86,7 @@ class Tracks { /*! Returns the markers in \a image1 and \a image2 which have a common track. - + This is not the same as the union of the markers in \a image1 and \a image2; each marker is for a track that appears in both images. */ diff --git a/extern/libmv/libmv/tracking/esm_region_tracker.cc b/extern/libmv/libmv/tracking/esm_region_tracker.cc index 9784b61c068..df9c89a46d4 100644 --- a/extern/libmv/libmv/tracking/esm_region_tracker.cc +++ b/extern/libmv/libmv/tracking/esm_region_tracker.cc @@ -18,6 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. +/* needed for M_E when building with msvc */ #define _USE_MATH_DEFINES #include "libmv/tracking/esm_region_tracker.h" diff --git a/extern/libmv/libmv/tracking/trklt_region_tracker.h b/extern/libmv/libmv/tracking/trklt_region_tracker.h index 5046e0f069d..26d0621aa02 100644 --- a/extern/libmv/libmv/tracking/trklt_region_tracker.h +++ b/extern/libmv/libmv/tracking/trklt_region_tracker.h @@ -42,7 +42,7 @@ struct TrkltRegionTracker : public RegionTracker { min_update_squared_distance(1e-6), sigma(0.9), lambda(0.05) {} - + virtual ~TrkltRegionTracker() {} // Tracker interface. diff --git a/extern/libmv/patches/bundle_tweaks.patch b/extern/libmv/patches/bundle_tweaks.patch index f7b06b0a2dd..aebc257f7f9 100644 --- a/extern/libmv/patches/bundle_tweaks.patch +++ b/extern/libmv/patches/bundle_tweaks.patch @@ -11,6 +11,36 @@ index 067da52..af86c4b 100644 #define LG LOG(INFO) #define V0 LOG(INFO) +diff --git a/src/libmv/simple_pipeline/pipeline.cc b/src/libmv/simple_pipeline/pipeline.cc +index 2459d05..2e4e5a6 100644 +--- a/src/libmv/simple_pipeline/pipeline.cc ++++ b/src/libmv/simple_pipeline/pipeline.cc +@@ -280,25 +280,6 @@ double InternalReprojectionError(const Tracks &image_tracks, + double ex = reprojected_marker.x - markers[i].x; + double ey = reprojected_marker.y - markers[i].y; + +- const int N = 100; +- char line[N]; +- snprintf(line, N, +- "image %-3d track %-3d " +- "x %7.1f y %7.1f " +- "rx %7.1f ry %7.1f " +- "ex %7.1f ey %7.1f" +- " e %7.1f", +- markers[i].image, +- markers[i].track, +- markers[i].x, +- markers[i].y, +- reprojected_marker.x, +- reprojected_marker.y, +- ex, +- ey, +- sqrt(ex*ex + ey*ey)); +- LG << line; +- + total_error += sqrt(ex*ex + ey*ey); + } + LG << "Skipped " << num_skipped << " markers."; diff --git a/src/third_party/glog/src/glog/logging.h b/src/third_party/glog/src/glog/logging.h index 57615ef..a58d478 100644 --- a/src/third_party/glog/src/glog/logging.h @@ -65,7 +95,7 @@ index 50c6a71..b179a1e 100644 #ifdef HAVE_STACKTRACE diff --git a/src/third_party/glog/src/utilities.h b/src/third_party/glog/src/utilities.h -index ee54f94..2d4e99e 100644 +index c4ae256..5c841a0 100644 --- a/src/third_party/glog/src/utilities.h +++ b/src/third_party/glog/src/utilities.h @@ -79,7 +79,7 @@ @@ -106,7 +136,7 @@ index 114762e..682a1b9 100755 /* define if you have libunwind */ #undef HAVE_LIB_UNWIND diff --git a/src/third_party/glog/src/windows/glog/logging.h b/src/third_party/glog/src/windows/glog/logging.h -index 7a6df74..de51586 100755 +index 4257375..2f41681 100755 --- a/src/third_party/glog/src/windows/glog/logging.h +++ b/src/third_party/glog/src/windows/glog/logging.h @@ -82,8 +82,8 @@ @@ -119,4 +149,4 @@ index 7a6df74..de51586 100755 +#include "third_party/gflags/gflags.h" #endif - namespace google { + #ifdef __MINGW32__ diff --git a/extern/libmv/patches/config_mac.patch b/extern/libmv/patches/config_mac.patch deleted file mode 100644 index 5a880155bfa..00000000000 --- a/extern/libmv/patches/config_mac.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/third_party/glog/src/config_mac.h b/src/third_party/glog/src/config_mac.h -index a45575b..5f953d1 100644 ---- a/src/third_party/glog/src/config_mac.h -+++ b/src/third_party/glog/src/config_mac.h -@@ -131,7 +131,7 @@ - #define PACKAGE_VERSION "0.3.1" - - /* How to access the PC from a struct ucontext */ --#define PC_FROM_UCONTEXT uc_mcontext->__ss.__rip -+#undef PC_FROM_UCONTEXT - - /* Define to necessary symbol if this constant uses a non-standard name on - your system. */ diff --git a/extern/libmv/patches/detect.patch b/extern/libmv/patches/detect.patch deleted file mode 100644 index 36fea8427db..00000000000 --- a/extern/libmv/patches/detect.patch +++ /dev/null @@ -1,181 +0,0 @@ -diff --git a/src/libmv/simple_pipeline/detect.cc b/src/libmv/simple_pipeline/detect.cc -index 6fc0cdd..8ac42ab 100644 ---- a/src/libmv/simple_pipeline/detect.cc -+++ b/src/libmv/simple_pipeline/detect.cc -@@ -23,15 +23,89 @@ - ****************************************************************************/ - - #include "libmv/simple_pipeline/detect.h" -+#include <third_party/fast/fast.h> - #include <stdlib.h> --#include <string.h> -+#include <memory.h> -+ -+#ifdef __SSE2__ -+#include <emmintrin.h> -+#endif - - namespace libmv { - - typedef unsigned int uint; - -+int featurecmp(const void *a_v, const void *b_v) -+{ -+ Feature *a = (Feature*)a_v; -+ Feature *b = (Feature*)b_v; -+ -+ return b->score - a->score; -+} -+ -+std::vector<Feature> DetectFAST(const unsigned char* data, int width, int height, int stride, -+ int min_trackness, int min_distance) { -+ std::vector<Feature> features; -+ // TODO(MatthiasF): Support targetting a feature count (binary search trackness) -+ int num_features; -+ xy* all = fast9_detect(data, width, height, -+ stride, min_trackness, &num_features); -+ if(num_features == 0) { -+ free(all); -+ return features; -+ } -+ int* scores = fast9_score(data, stride, all, num_features, min_trackness); -+ // TODO: merge with close feature suppression -+ xy* nonmax = nonmax_suppression(all, scores, num_features, &num_features); -+ free(all); -+ // Remove too close features -+ // TODO(MatthiasF): A resolution independent parameter would be better than distance -+ // e.g. a coefficient going from 0 (no minimal distance) to 1 (optimal circle packing) -+ // FIXME(MatthiasF): this method will not necessarily give all maximum markers -+ if(num_features) { -+ Feature *all_features = new Feature[num_features]; -+ -+ for(int i = 0; i < num_features; ++i) { -+ Feature a = { nonmax[i].x, nonmax[i].y, scores[i], 0 }; -+ all_features[i] = a; -+ } -+ -+ qsort((void *)all_features, num_features, sizeof(Feature), featurecmp); -+ -+ features.reserve(num_features); -+ -+ int prev_score = all_features[0].score; -+ for(int i = 0; i < num_features; ++i) { -+ bool ok = true; -+ Feature a = all_features[i]; -+ if(a.score>prev_score) -+ abort(); -+ prev_score = a.score; -+ -+ // compare each feature against filtered set -+ for(int j = 0; j < features.size(); j++) { -+ Feature& b = features[j]; -+ if ( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) < min_distance*min_distance ) { -+ // already a nearby feature -+ ok = false; -+ break; -+ } -+ } -+ -+ if(ok) { -+ // add the new feature -+ features.push_back(a); -+ } -+ } -+ -+ delete [] all_features; -+ } -+ free(scores); -+ free(nonmax); -+ return features; -+} -+ - #ifdef __SSE2__ --#include <emmintrin.h> - static uint SAD(const ubyte* imageA, const ubyte* imageB, int strideA, int strideB) { - __m128i a = _mm_setzero_si128(); - for(int i = 0; i < 16; i++) { -@@ -52,7 +126,7 @@ static uint SAD(const ubyte* imageA, const ubyte* imageB, int strideA, int strid - } - #endif - --void Detect(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance, ubyte* pattern) { -+void DetectMORAVEC(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance, ubyte* pattern) { - unsigned short histogram[256]; - memset(histogram,0,sizeof(histogram)); - ubyte* scores = new ubyte[width*height]; -diff --git a/src/libmv/simple_pipeline/detect.h b/src/libmv/simple_pipeline/detect.h -index 23b239b..bbe7aed 100644 ---- a/src/libmv/simple_pipeline/detect.h -+++ b/src/libmv/simple_pipeline/detect.h -@@ -25,27 +25,52 @@ - #ifndef LIBMV_SIMPLE_PIPELINE_DETECT_H_ - #define LIBMV_SIMPLE_PIPELINE_DETECT_H_ - --#ifdef __cplusplus -+#include <vector> -+ - namespace libmv { --#endif - - typedef unsigned char ubyte; - - /*! -- \a Feature is the 2D location of a detected feature in an image. -+ A Feature is the 2D location of a detected feature in an image. - -- \a x, \a y is the position of the center in pixels (from image top-left). -- \a score is an estimate of how well the pattern will be tracked. -- \a size can be used as an initial size to track the pattern. -+ \a x, \a y is the position of the feature in pixels from the top left corner. -+ \a score is an estimate of how well the feature will be tracked. -+ \a size can be used as an initial pattern size to track the feature. - - \sa Detect - */ - struct Feature { -+ /// Position in pixels (from top-left corner) -+ /// \note libmv might eventually support subpixel precision. - float x, y; -+ /// Trackness of the feature - float score; -+ /// Size of the feature in pixels - float size; - }; -- //radius for non maximal suppression -+ -+/*! -+ Detect features in an image. -+ -+ You need to input a single channel 8-bit image using pointer to image \a data, -+ \a width, \a height and \a stride (i.e bytes per line). -+ -+ You can tweak the count of detected features using \a min_trackness, which is -+ the minimum score to add a feature, and \a min_distance which is the minimal -+ distance accepted between two featuress. -+ -+ \note You can binary search over \a min_trackness to get a given feature count. -+ -+ \note a way to get an uniform distribution of a given feature count is: -+ \a min_distance = \a width * \a height / desired_feature_count ^ 2 -+ -+ \return All detected feartures matching given parameters -+*/ -+std::vector<Feature> DetectFAST(const unsigned char* data, int width, int height, -+ int stride, int min_trackness = 128, -+ int min_distance = 120); -+ - /*! - Detect features in an image. - -@@ -63,10 +88,8 @@ struct Feature { - \note \a You can crop the image (to avoid detecting markers near the borders) without copying: - image += marginY*stride+marginX, width -= 2*marginX, height -= 2*marginY; - */ --void Detect(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance /*=32*/, ubyte* pattern /*=0*/); -+void DetectMORAVEC(ubyte* image, int stride, int width, int height, Feature* detected, int* count, int distance /*=32*/, ubyte* pattern /*=0*/); - --#ifdef __cplusplus - } --#endif - - #endif diff --git a/extern/libmv/patches/fast.patch b/extern/libmv/patches/fast.patch deleted file mode 100644 index 8e0aeb7e721..00000000000 --- a/extern/libmv/patches/fast.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/src/third_party/fast/fast.h b/src/third_party/fast/fast.h -index 2b3825a..06fa90e 100644 ---- a/src/third_party/fast/fast.h -+++ b/src/third_party/fast/fast.h -@@ -1,6 +1,10 @@ - #ifndef FAST_H - #define FAST_H - -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - typedef struct { int x, y; } xy; - typedef unsigned char byte; - -@@ -28,4 +32,8 @@ xy* fast12_detect_nonmax(const byte* im, int xsize, int ysize, int stride, int b - xy* nonmax_suppression(const xy* corners, const int* scores, int num_corners, int* ret_num_nonmax); - - -+#ifdef __cplusplus -+} -+#endif -+ - #endif diff --git a/extern/libmv/patches/function_derivative.patch b/extern/libmv/patches/function_derivative.patch deleted file mode 100644 index be7ccfc911a..00000000000 --- a/extern/libmv/patches/function_derivative.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/src/libmv/numeric/function_derivative.h b/src/libmv/numeric/function_derivative.h -index 0075d23..d7bc437 100644 ---- a/src/libmv/numeric/function_derivative.h -+++ b/src/libmv/numeric/function_derivative.h -@@ -24,6 +24,7 @@ - #include <cmath> - - #include "libmv/numeric/numeric.h" -+#include "libmv/logging/logging.h" - - namespace libmv { - -@@ -97,7 +98,7 @@ bool CheckJacobian(const Function &f, const typename Function::XMatrixType &x) { - - typename NumericJacobian<Function>::JMatrixType J_numeric = j_numeric(x); - typename NumericJacobian<Function>::JMatrixType J_analytic = j_analytic(x); -- //LG << J_numeric - J_analytic; -+ LG << J_numeric - J_analytic; - return true; - } - diff --git a/extern/libmv/patches/high_distortion_crash_fix.patch b/extern/libmv/patches/high_distortion_crash_fix.patch deleted file mode 100644 index 54ab66fa27c..00000000000 --- a/extern/libmv/patches/high_distortion_crash_fix.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/src/libmv/simple_pipeline/camera_intrinsics.cc b/src/libmv/simple_pipeline/camera_intrinsics.cc -index 4e88e1f..f9888ff 100644 ---- a/src/libmv/simple_pipeline/camera_intrinsics.cc -+++ b/src/libmv/simple_pipeline/camera_intrinsics.cc -@@ -160,9 +160,13 @@ void CameraIntrinsics::ComputeLookupGrid(Offset* grid, int width, int height) { - if( iy < 0 ) { iy = 0, fy = 0; } - if( ix >= width-2 ) ix = width-2; - if( iy >= height-2 ) iy = height-2; -- //assert( ix-x > -128 && ix-x < 128 && iy-y > -128 && iy-y < 128 ); -- Offset offset = { ix-x, iy-y, fx, fy }; -- grid[y*width+x] = offset; -+ if ( ix-x > -128 && ix-x < 128 && iy-y > -128 && iy-y < 128 ) { -+ Offset offset = { ix-x, iy-y, fx, fy }; -+ grid[y*width+x] = offset; -+ } else { -+ Offset offset = { 0, 0, 0, 0 }; -+ grid[y*width+x] = offset; -+ } - } - } - } diff --git a/extern/libmv/patches/levenberg_marquardt.patch b/extern/libmv/patches/levenberg_marquardt.patch deleted file mode 100644 index 49ef82d73d2..00000000000 --- a/extern/libmv/patches/levenberg_marquardt.patch +++ /dev/null @@ -1,71 +0,0 @@ -diff --git a/src/libmv/numeric/levenberg_marquardt.h b/src/libmv/numeric/levenberg_marquardt.h -index 6a54f66..4473b72 100644 ---- a/src/libmv/numeric/levenberg_marquardt.h -+++ b/src/libmv/numeric/levenberg_marquardt.h -@@ -33,6 +33,7 @@ - - #include "libmv/numeric/numeric.h" - #include "libmv/numeric/function_derivative.h" -+#include "libmv/logging/logging.h" - - namespace libmv { - -@@ -123,26 +124,40 @@ class LevenbergMarquardt { - Parameters dx, x_new; - int i; - for (i = 0; results.status == RUNNING && i < params.max_iterations; ++i) { -- if (dx.norm() <= params.relative_step_threshold * x.norm()) { -+ VLOG(1) << "iteration: " << i; -+ VLOG(1) << "||f(x)||: " << f_(x).norm(); -+ VLOG(1) << "max(g): " << g.array().abs().maxCoeff(); -+ VLOG(1) << "u: " << u; -+ VLOG(1) << "v: " << v; -+ -+ AMatrixType A_augmented = A + u*AMatrixType::Identity(J.cols(), J.cols()); -+ Solver solver(A_augmented); -+ dx = solver.solve(g); -+ bool solved = (A_augmented * dx).isApprox(g); -+ if (!solved) { -+ LOG(ERROR) << "Failed to solve"; -+ } -+ if (solved && dx.norm() <= params.relative_step_threshold * x.norm()) { - results.status = RELATIVE_STEP_SIZE_TOO_SMALL; - break; -- } -- x_new = x + dx; -- // Rho is the ratio of the actual reduction in error to the reduction -- // in error that would be obtained if the problem was linear. -- // See [1] for details. -- Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm()) -- / dx.dot(u*dx + g)); -- if (rho > 0) { -- // Accept the Gauss-Newton step because the linear model fits well. -- x = x_new; -- results.status = Update(x, params, &J, &A, &error, &g); -- Scalar tmp = Scalar(2*rho-1); -- u = u*std::max(1/3., 1 - (tmp*tmp*tmp)); -- v = 2; -- continue; -- } -- -+ } -+ if (solved) { -+ x_new = x + dx; -+ // Rho is the ratio of the actual reduction in error to the reduction -+ // in error that would be obtained if the problem was linear. -+ // See [1] for details. -+ Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm()) -+ / dx.dot(u*dx + g)); -+ if (rho > 0) { -+ // Accept the Gauss-Newton step because the linear model fits well. -+ x = x_new; -+ results.status = Update(x, params, &J, &A, &error, &g); -+ Scalar tmp = Scalar(2*rho-1); -+ u = u*std::max(1/3., 1 - (tmp*tmp*tmp)); -+ v = 2; -+ continue; -+ } -+ } - // Reject the update because either the normal equations failed to solve - // or the local linear model was not good (rho < 0). Instead, increase u - // to move closer to gradient descent. diff --git a/extern/libmv/patches/mingw.patch b/extern/libmv/patches/mingw.patch deleted file mode 100644 index 029e7d7f979..00000000000 --- a/extern/libmv/patches/mingw.patch +++ /dev/null @@ -1,171 +0,0 @@ -diff --git a/src/libmv/multiview/euclidean_resection.cc b/src/libmv/multiview/euclidean_resection.cc -index 6d918a1..9286251 100644 ---- a/src/libmv/multiview/euclidean_resection.cc -+++ b/src/libmv/multiview/euclidean_resection.cc -@@ -32,6 +32,8 @@ - namespace libmv { - namespace euclidean_resection { - -+typedef unsigned int uint; -+ - bool EuclideanResection(const Mat2X &x_camera, - const Mat3X &X_world, - Mat3 *R, Vec3 *t, -diff --git a/src/libmv/numeric/numeric.h b/src/libmv/numeric/numeric.h -index f39d126..21e0f06 100644 ---- a/src/libmv/numeric/numeric.h -+++ b/src/libmv/numeric/numeric.h -@@ -40,7 +40,7 @@ - } - #endif //_WIN32 || __APPLE__ - --#if _WIN32 -+#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__) - inline long lround(double d) { - return (long)(d>0 ? d+0.5 : ceil(d-0.5)); - } -diff --git a/src/third_party/glog/src/config.h b/src/third_party/glog/src/config.h -index ed8d56e..06ed686 100644 ---- a/src/third_party/glog/src/config.h -+++ b/src/third_party/glog/src/config.h -@@ -4,6 +4,8 @@ - /* Namespace for Google classes */ - #ifdef __APPLE__ - #include "config_mac.h" -+#elif __MINGW32__ -+ #include "windows/config.h" - #elif __GNUC__ - #include "config_linux.h" - #elif _MSC_VER -diff --git a/src/third_party/glog/src/utilities.h b/src/third_party/glog/src/utilities.h -index ee54f94..c4ae256 100644 ---- a/src/third_party/glog/src/utilities.h -+++ b/src/third_party/glog/src/utilities.h -@@ -101,7 +101,9 @@ - // correctly when GetStackTrace() is called with max_depth == 0. - // Some code may do that. - --#if defined(HAVE_LIB_UNWIND) -+#if __MINGW32__ -+# undef STACKTRACE_H -+#elif defined(HAVE_LIB_UNWIND) - # define STACKTRACE_H "stacktrace_libunwind-inl.h" - #elif !defined(NO_FRAME_POINTER) - # if defined(__i386__) && __GNUC__ >= 2 -diff --git a/src/third_party/glog/src/windows/glog/logging.h b/src/third_party/glog/src/windows/glog/logging.h -index 7a6df74..4257375 100755 ---- a/src/third_party/glog/src/windows/glog/logging.h -+++ b/src/third_party/glog/src/windows/glog/logging.h -@@ -59,7 +59,7 @@ - - // Annoying stuff for windows -- makes sure clients can import these functions - #ifndef GOOGLE_GLOG_DLL_DECL --# if defined(_WIN32) && !defined(__CYGWIN__) -+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) - # define GOOGLE_GLOG_DLL_DECL __declspec(dllimport) - # else - # define GOOGLE_GLOG_DLL_DECL -@@ -86,6 +86,15 @@ - #include <gflags/gflags.h> - #endif - -+#ifdef __MINGW32__ -+# include <stdlib.h> -+# include <unistd.h> -+# include <stdint.h> // the normal place uint16_t is defined -+# include <sys/types.h> // the normal place u_int16_t is defined -+# include <inttypes.h> // a third place for uint16_t or u_int16_t -+# define _exit(x) exit(x) -+#endif -+ - namespace google { - - #if 0 // the C99 format -@@ -98,11 +107,16 @@ typedef int32_t int32; - typedef u_int32_t uint32; - typedef int64_t int64; - typedef u_int64_t uint64; --#elif 1 // the windows (vc7) format -+#elif defined(_MSC_VER) - typedef __int32 int32; - typedef unsigned __int32 uint32; - typedef __int64 int64; - typedef unsigned __int64 uint64; -+#elif defined(__MINGW32__) -+typedef int32_t int32; -+typedef uint32_t uint32; -+typedef int64_t int64; -+typedef uint64_t uint64; - #else - #error Do not know how to define a 32-bit integer quantity on your system - #endif -diff --git a/src/third_party/glog/src/windows/port.h b/src/third_party/glog/src/windows/port.h -index d093bf5..d507812 100755 ---- a/src/third_party/glog/src/windows/port.h -+++ b/src/third_party/glog/src/windows/port.h -@@ -59,14 +59,16 @@ - * used by both C and C++ code, so we put all the C++ together. - */ - --/* 4244: otherwise we get problems when substracting two size_t's to an int -- * 4251: it's complaining about a private struct I've chosen not to dllexport -- * 4355: we use this in a constructor, but we do it safely -- * 4715: for some reason VC++ stopped realizing you can't return after abort() -- * 4800: we know we're casting ints/char*'s to bools, and we're ok with that -- * 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror() -- */ --#pragma warning(disable:4244 4251 4355 4715 4800 4996) -+#if _MSC_VER -+ /* 4244: otherwise we get problems when substracting two size_t's to an int -+ * 4251: it's complaining about a private struct I've chosen not to dllexport -+ * 4355: we use this in a constructor, but we do it safely -+ * 4715: for some reason VC++ stopped realizing you can't return after abort() -+ * 4800: we know we're casting ints/char*'s to bools, and we're ok with that -+ * 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror() -+ */ -+# pragma warning(disable:4244 4251 4355 4715 4800 4996) -+#endif - - /* file I/O */ - #define PATH_MAX 1024 -@@ -108,7 +110,9 @@ extern int snprintf(char *str, size_t size, - extern int safe_vsnprintf(char *str, size_t size, - const char *format, va_list ap); - #define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap) -+#if !defined(__MINGW32__) - #define va_copy(dst, src) (dst) = (src) -+#endif - - /* Windows doesn't support specifying the number of buckets as a - * hash_map constructor arg, so we leave this blank. -@@ -130,13 +134,30 @@ enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock - #define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2)) - - inline struct tm* localtime_r(const time_t* timep, struct tm* result) { -+#if __MINGW32__ -+ struct tm *local_result; -+ local_result = localtime (timep); -+ -+ if (local_result == NULL || result == NULL) -+ return NULL; -+ -+ memcpy (result, local_result, sizeof (result)); -+ -+ return result; -+#else - localtime_s(result, timep); - return result; -+#endif - } - - inline char* strerror_r(int errnum, char* buf, size_t buflen) { -+#if __MINGW32__ -+ strncpy(buf, "Not implemented yet", buflen); -+ return buf; -+#else - strerror_s(buf, buflen, errnum); - return buf; -+#endif - } - - #ifndef __cplusplus diff --git a/extern/libmv/patches/msvc2010.patch b/extern/libmv/patches/msvc2010.patch deleted file mode 100644 index c090b070628..00000000000 --- a/extern/libmv/patches/msvc2010.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/src/libmv/simple_pipeline/tracks.cc b/src/libmv/simple_pipeline/tracks.cc -index 0e2a1b6..3fb8ddb 100644 ---- a/src/libmv/simple_pipeline/tracks.cc -+++ b/src/libmv/simple_pipeline/tracks.cc -@@ -20,6 +20,7 @@ - - #include <algorithm> - #include <vector> -+#include <iterator> - - #include "libmv/numeric/numeric.h" - #include "libmv/simple_pipeline/tracks.h" diff --git a/extern/libmv/patches/overscan.patch b/extern/libmv/patches/overscan.patch deleted file mode 100644 index c68f36804ec..00000000000 --- a/extern/libmv/patches/overscan.patch +++ /dev/null @@ -1,182 +0,0 @@ -diff --git a/src/libmv/simple_pipeline/camera_intrinsics.cc b/src/libmv/simple_pipeline/camera_intrinsics.cc -index 110a16d..366129d 100644 ---- a/src/libmv/simple_pipeline/camera_intrinsics.cc -+++ b/src/libmv/simple_pipeline/camera_intrinsics.cc -@@ -31,6 +31,7 @@ struct Offset { - struct Grid { - struct Offset *offset; - int width, height; -+ double overscan; - }; - - static struct Grid *copyGrid(struct Grid *from) -@@ -42,6 +43,7 @@ static struct Grid *copyGrid(struct Grid *from) - - to->width = from->width; - to->height = from->height; -+ to->overscan = from->overscan; - - to->offset = new Offset[to->width*to->height]; - memcpy(to->offset, from->offset, sizeof(struct Offset)*to->width*to->height); -@@ -184,17 +186,19 @@ void CameraIntrinsics::InvertIntrinsics(double image_x, - - // TODO(MatthiasF): downsample lookup - template<typename WarpFunction> --void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height) { -- double aspx = (double)width / image_width_; -- double aspy = (double)height / image_height_; -+void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height, double overscan) { -+ double w = (double)width / (1 + overscan); -+ double h = (double)height / (1 + overscan); -+ double aspx = (double)w / image_width_; -+ double aspy = (double)h / image_height_; - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { -- double src_x = x / aspx, src_y = y / aspy; -+ double src_x = (x - 0.5 * overscan * w) / aspx, src_y = (y - 0.5 * overscan * h) / aspy; - double warp_x, warp_y; - WarpFunction(this,src_x,src_y,&warp_x,&warp_y); -- warp_x = warp_x*aspx; -- warp_y = warp_y*aspy; -+ warp_x = warp_x*aspx + 0.5 * overscan * w; -+ warp_y = warp_y*aspy + 0.5 * overscan * h; - int ix = int(warp_x), iy = int(warp_y); - int fx = round((warp_x-ix)*256), fy = round((warp_y-iy)*256); - if(fx == 256) { fx=0; ix++; } -@@ -264,10 +268,10 @@ struct InvertIntrinsicsFunction { - } - }; - --void CameraIntrinsics::CheckDistortLookupGrid(int width, int height) -+void CameraIntrinsics::CheckDistortLookupGrid(int width, int height, double overscan) - { - if(distort_) { -- if(distort_->width != width || distort_->height != height) { -+ if(distort_->width != width || distort_->height != height || distort_->overscan != overscan) { - delete [] distort_->offset; - distort_->offset = NULL; - } -@@ -278,17 +282,18 @@ void CameraIntrinsics::CheckDistortLookupGrid(int width, int height) - - if(!distort_->offset) { - distort_->offset = new Offset[width*height]; -- ComputeLookupGrid<InvertIntrinsicsFunction>(distort_,width,height); -+ ComputeLookupGrid<InvertIntrinsicsFunction>(distort_,width,height,overscan); - } - - distort_->width = width; - distort_->height = height; -+ distort_->overscan = overscan; - } - --void CameraIntrinsics::CheckUndistortLookupGrid(int width, int height) -+void CameraIntrinsics::CheckUndistortLookupGrid(int width, int height, double overscan) - { - if(undistort_) { -- if(undistort_->width != width || undistort_->height != height) { -+ if(undistort_->width != width || undistort_->height != height || undistort_->overscan != overscan) { - delete [] undistort_->offset; - undistort_->offset = NULL; - } -@@ -299,15 +304,16 @@ void CameraIntrinsics::CheckUndistortLookupGrid(int width, int height) - - if(!undistort_->offset) { - undistort_->offset = new Offset[width*height]; -- ComputeLookupGrid<ApplyIntrinsicsFunction>(undistort_,width,height); -+ ComputeLookupGrid<ApplyIntrinsicsFunction>(undistort_,width,height,overscan); - } - - undistort_->width = width; - undistort_->height = height; -+ undistort_->overscan = overscan; - } - --void CameraIntrinsics::Distort(const float* src, float* dst, int width, int height, int channels) { -- CheckDistortLookupGrid(width, height); -+void CameraIntrinsics::Distort(const float* src, float* dst, int width, int height, double overscan, int channels) { -+ CheckDistortLookupGrid(width, height, overscan); - if(channels==1) Warp<float,1>(distort_,src,dst,width,height); - else if(channels==2) Warp<float,2>(distort_,src,dst,width,height); - else if(channels==3) Warp<float,3>(distort_,src,dst,width,height); -@@ -315,8 +321,8 @@ void CameraIntrinsics::Distort(const float* src, float* dst, int width, int heig - //else assert("channels must be between 1 and 4"); - } - --void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int width, int height, int channels) { -- CheckDistortLookupGrid(width, height); -+void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int width, int height, double overscan, int channels) { -+ CheckDistortLookupGrid(width, height, overscan); - if(channels==1) Warp<unsigned char,1>(distort_,src,dst,width,height); - else if(channels==2) Warp<unsigned char,2>(distort_,src,dst,width,height); - else if(channels==3) Warp<unsigned char,3>(distort_,src,dst,width,height); -@@ -324,8 +330,8 @@ void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int - //else assert("channels must be between 1 and 4"); - } - --void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int height, int channels) { -- CheckUndistortLookupGrid(width, height); -+void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int height, double overscan, int channels) { -+ CheckUndistortLookupGrid(width, height, overscan); - if(channels==1) Warp<float,1>(undistort_,src,dst,width,height); - else if(channels==2) Warp<float,2>(undistort_,src,dst,width,height); - else if(channels==3) Warp<float,3>(undistort_,src,dst,width,height); -@@ -333,8 +339,8 @@ void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int he - //else assert("channels must be between 1 and 4"); - } - --void CameraIntrinsics::Undistort(const unsigned char* src, unsigned char* dst, int width, int height, int channels) { -- CheckUndistortLookupGrid(width, height); -+void CameraIntrinsics::Undistort(const unsigned char* src, unsigned char* dst, int width, int height, double overscan, int channels) { -+ CheckUndistortLookupGrid(width, height, overscan); - if(channels==1) Warp<unsigned char,1>(undistort_,src,dst,width,height); - else if(channels==2) Warp<unsigned char,2>(undistort_,src,dst,width,height); - else if(channels==3) Warp<unsigned char,3>(undistort_,src,dst,width,height); -diff --git a/src/libmv/simple_pipeline/camera_intrinsics.h b/src/libmv/simple_pipeline/camera_intrinsics.h -index f525571..f4bf903 100644 ---- a/src/libmv/simple_pipeline/camera_intrinsics.h -+++ b/src/libmv/simple_pipeline/camera_intrinsics.h -@@ -91,7 +91,7 @@ class CameraIntrinsics { - \note This is the reference implementation using floating point images. - */ - void Distort(const float* src, float* dst, -- int width, int height, int channels); -+ int width, int height, double overscan, int channels); - /*! - Distort an image using the current camera instrinsics - -@@ -101,7 +101,7 @@ class CameraIntrinsics { - \note This version is much faster. - */ - void Distort(const unsigned char* src, unsigned char* dst, -- int width, int height, int channels); -+ int width, int height, double overscan, int channels); - /*! - Undistort an image using the current camera instrinsics - -@@ -111,7 +111,7 @@ class CameraIntrinsics { - \note This is the reference implementation using floating point images. - */ - void Undistort(const float* src, float* dst, -- int width, int height, int channels); -+ int width, int height, double overscan, int channels); - /*! - Undistort an image using the current camera instrinsics - -@@ -121,12 +121,12 @@ class CameraIntrinsics { - \note This version is much faster. - */ - void Undistort(const unsigned char* src, unsigned char* dst, -- int width, int height, int channels); -+ int width, int height, double overscan, int channels); - - private: -- template<typename WarpFunction> void ComputeLookupGrid(struct Grid* grid, int width, int height); -- void CheckUndistortLookupGrid(int width, int height); -- void CheckDistortLookupGrid(int width, int height); -+ template<typename WarpFunction> void ComputeLookupGrid(struct Grid* grid, int width, int height, double overscan); -+ void CheckUndistortLookupGrid(int width, int height, double overscan); -+ void CheckDistortLookupGrid(int width, int height, double overscan); - void FreeLookupGrid(); - - // The traditional intrinsics matrix from x = K[R|t]X. diff --git a/extern/libmv/patches/scaled_distortion.patch b/extern/libmv/patches/scaled_distortion.patch deleted file mode 100644 index 2da832931d1..00000000000 --- a/extern/libmv/patches/scaled_distortion.patch +++ /dev/null @@ -1,261 +0,0 @@ -diff --git a/src/libmv/simple_pipeline/camera_intrinsics.cc b/src/libmv/simple_pipeline/camera_intrinsics.cc -index f9888ff..110a16d 100644 ---- a/src/libmv/simple_pipeline/camera_intrinsics.cc -+++ b/src/libmv/simple_pipeline/camera_intrinsics.cc -@@ -23,7 +23,32 @@ - - namespace libmv { - --struct Offset { signed char ix,iy; unsigned char fx,fy; }; -+struct Offset { -+ signed char ix, iy; -+ unsigned char fx,fy; -+}; -+ -+struct Grid { -+ struct Offset *offset; -+ int width, height; -+}; -+ -+static struct Grid *copyGrid(struct Grid *from) -+{ -+ struct Grid *to = NULL; -+ -+ if (from) { -+ to = new Grid; -+ -+ to->width = from->width; -+ to->height = from->height; -+ -+ to->offset = new Offset[to->width*to->height]; -+ memcpy(to->offset, from->offset, sizeof(struct Offset)*to->width*to->height); -+ } -+ -+ return to; -+} - - CameraIntrinsics::CameraIntrinsics() - : K_(Mat3::Identity()), -@@ -37,9 +62,22 @@ CameraIntrinsics::CameraIntrinsics() - distort_(0), - undistort_(0) {} - -+CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics &from) -+ : K_(from.K_), -+ image_width_(from.image_width_), -+ image_height_(from.image_height_), -+ k1_(from.k1_), -+ k2_(from.k2_), -+ k3_(from.k3_), -+ p1_(from.p1_), -+ p2_(from.p2_) -+{ -+ distort_ = copyGrid(from.distort_); -+ undistort_ = copyGrid(from.undistort_); -+} -+ - CameraIntrinsics::~CameraIntrinsics() { -- if(distort_) delete[] distort_; -- if(undistort_) delete[] undistort_; -+ FreeLookupGrid(); - } - - /// Set the entire calibration matrix at once. -@@ -146,11 +184,17 @@ void CameraIntrinsics::InvertIntrinsics(double image_x, - - // TODO(MatthiasF): downsample lookup - template<typename WarpFunction> --void CameraIntrinsics::ComputeLookupGrid(Offset* grid, int width, int height) { -+void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height) { -+ double aspx = (double)width / image_width_; -+ double aspy = (double)height / image_height_; -+ - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { -+ double src_x = x / aspx, src_y = y / aspy; - double warp_x, warp_y; -- WarpFunction(this,x,y,&warp_x,&warp_y); -+ WarpFunction(this,src_x,src_y,&warp_x,&warp_y); -+ warp_x = warp_x*aspx; -+ warp_y = warp_y*aspy; - int ix = int(warp_x), iy = int(warp_y); - int fx = round((warp_x-ix)*256), fy = round((warp_y-iy)*256); - if(fx == 256) { fx=0; ix++; } -@@ -162,10 +206,10 @@ void CameraIntrinsics::ComputeLookupGrid(Offset* grid, int width, int height) { - if( iy >= height-2 ) iy = height-2; - if ( ix-x > -128 && ix-x < 128 && iy-y > -128 && iy-y < 128 ) { - Offset offset = { ix-x, iy-y, fx, fy }; -- grid[y*width+x] = offset; -+ grid->offset[y*width+x] = offset; - } else { - Offset offset = { 0, 0, 0, 0 }; -- grid[y*width+x] = offset; -+ grid->offset[y*width+x] = offset; - } - } - } -@@ -173,11 +217,11 @@ void CameraIntrinsics::ComputeLookupGrid(Offset* grid, int width, int height) { - - // TODO(MatthiasF): cubic B-Spline image sampling, bilinear lookup - template<typename T,int N> --static void Warp(const Offset* grid, const T* src, T* dst, -+static void Warp(const Grid* grid, const T* src, T* dst, - int width, int height) { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { -- Offset offset = grid[y*width+x]; -+ Offset offset = grid->offset[y*width+x]; - const T* s = &src[((y+offset.iy)*width+(x+offset.ix))*N]; - for (int i = 0; i < N; i++) { - dst[(y*width+x)*N+i] = ((s[ i] * (256-offset.fx) + s[ N+i] * offset.fx) * (256-offset.fy) -@@ -188,8 +232,17 @@ static void Warp(const Offset* grid, const T* src, T* dst, - } - - void CameraIntrinsics::FreeLookupGrid() { -- if(distort_) delete distort_, distort_=0; -- if(undistort_) delete undistort_, undistort_=0; -+ if(distort_) { -+ delete distort_->offset; -+ delete distort_; -+ distort_ = NULL; -+ } -+ -+ if(undistort_) { -+ delete undistort_->offset; -+ delete undistort_; -+ undistort_ = NULL; -+ } - } - - // FIXME: C++ templates limitations makes thing complicated, but maybe there is a simpler method. -@@ -211,11 +264,50 @@ struct InvertIntrinsicsFunction { - } - }; - --void CameraIntrinsics::Distort(const float* src, float* dst, int width, int height, int channels) { -- if(!distort_) { -- distort_ = new Offset[width*height]; -- ComputeLookupGrid<InvertIntrinsicsFunction>(distort_,width,height); -+void CameraIntrinsics::CheckDistortLookupGrid(int width, int height) -+{ -+ if(distort_) { -+ if(distort_->width != width || distort_->height != height) { -+ delete [] distort_->offset; -+ distort_->offset = NULL; -+ } -+ } else { -+ distort_ = new Grid; -+ distort_->offset = NULL; -+ } -+ -+ if(!distort_->offset) { -+ distort_->offset = new Offset[width*height]; -+ ComputeLookupGrid<InvertIntrinsicsFunction>(distort_,width,height); - } -+ -+ distort_->width = width; -+ distort_->height = height; -+} -+ -+void CameraIntrinsics::CheckUndistortLookupGrid(int width, int height) -+{ -+ if(undistort_) { -+ if(undistort_->width != width || undistort_->height != height) { -+ delete [] undistort_->offset; -+ undistort_->offset = NULL; -+ } -+ } else { -+ undistort_ = new Grid; -+ undistort_->offset = NULL; -+ } -+ -+ if(!undistort_->offset) { -+ undistort_->offset = new Offset[width*height]; -+ ComputeLookupGrid<ApplyIntrinsicsFunction>(undistort_,width,height); -+ } -+ -+ undistort_->width = width; -+ undistort_->height = height; -+} -+ -+void CameraIntrinsics::Distort(const float* src, float* dst, int width, int height, int channels) { -+ CheckDistortLookupGrid(width, height); - if(channels==1) Warp<float,1>(distort_,src,dst,width,height); - else if(channels==2) Warp<float,2>(distort_,src,dst,width,height); - else if(channels==3) Warp<float,3>(distort_,src,dst,width,height); -@@ -224,10 +316,7 @@ void CameraIntrinsics::Distort(const float* src, float* dst, int width, int heig - } - - void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int width, int height, int channels) { -- if(!distort_) { -- distort_ = new Offset[width*height]; -- ComputeLookupGrid<InvertIntrinsicsFunction>(distort_,width,height); -- } -+ CheckDistortLookupGrid(width, height); - if(channels==1) Warp<unsigned char,1>(distort_,src,dst,width,height); - else if(channels==2) Warp<unsigned char,2>(distort_,src,dst,width,height); - else if(channels==3) Warp<unsigned char,3>(distort_,src,dst,width,height); -@@ -236,10 +325,7 @@ void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int - } - - void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int height, int channels) { -- if(!undistort_) { -- undistort_ = new Offset[width*height]; -- ComputeLookupGrid<ApplyIntrinsicsFunction>(undistort_,width,height); -- } -+ CheckUndistortLookupGrid(width, height); - if(channels==1) Warp<float,1>(undistort_,src,dst,width,height); - else if(channels==2) Warp<float,2>(undistort_,src,dst,width,height); - else if(channels==3) Warp<float,3>(undistort_,src,dst,width,height); -@@ -248,10 +334,7 @@ void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int he - } - - void CameraIntrinsics::Undistort(const unsigned char* src, unsigned char* dst, int width, int height, int channels) { -- if(!undistort_) { -- undistort_ = new Offset[width*height]; -- ComputeLookupGrid<ApplyIntrinsicsFunction>(undistort_,width,height); -- } -+ CheckUndistortLookupGrid(width, height); - if(channels==1) Warp<unsigned char,1>(undistort_,src,dst,width,height); - else if(channels==2) Warp<unsigned char,2>(undistort_,src,dst,width,height); - else if(channels==3) Warp<unsigned char,3>(undistort_,src,dst,width,height); -diff --git a/src/libmv/simple_pipeline/camera_intrinsics.h b/src/libmv/simple_pipeline/camera_intrinsics.h -index 29bc8a1..f525571 100644 ---- a/src/libmv/simple_pipeline/camera_intrinsics.h -+++ b/src/libmv/simple_pipeline/camera_intrinsics.h -@@ -26,11 +26,12 @@ typedef Eigen::Matrix<double, 3, 3> Mat3; - - namespace libmv { - --struct Offset; -+struct Grid; - - class CameraIntrinsics { - public: - CameraIntrinsics(); -+ CameraIntrinsics(const CameraIntrinsics &from); - ~CameraIntrinsics(); - - const Mat3 &K() const { return K_; } -@@ -123,7 +124,9 @@ class CameraIntrinsics { - int width, int height, int channels); - - private: -- template<typename WarpFunction> void ComputeLookupGrid(Offset* grid, int width, int height); -+ template<typename WarpFunction> void ComputeLookupGrid(struct Grid* grid, int width, int height); -+ void CheckUndistortLookupGrid(int width, int height); -+ void CheckDistortLookupGrid(int width, int height); - void FreeLookupGrid(); - - // The traditional intrinsics matrix from x = K[R|t]X. -@@ -140,8 +143,8 @@ class CameraIntrinsics { - // independent of image size. - double k1_, k2_, k3_, p1_, p2_; - -- Offset* distort_; -- Offset* undistort_; -+ struct Grid *distort_; -+ struct Grid *undistort_; - }; - - } // namespace libmv diff --git a/extern/libmv/patches/series b/extern/libmv/patches/series index 00a52c1cfaa..ca671122a61 100644 --- a/extern/libmv/patches/series +++ b/extern/libmv/patches/series @@ -1,13 +1,2 @@ v3d_verbosity.patch -snrptinf_fix.patch bundle_tweaks.patch -fast.patch -config_mac.patch -levenberg_marquardt.patch -function_derivative.patch -high_distortion_crash_fix.patch -mingw.patch -msvc2010.patch -scaled_distortion.patch -overscan.patch -detect.patch diff --git a/extern/libmv/patches/snrptinf_fix.patch b/extern/libmv/patches/snrptinf_fix.patch deleted file mode 100644 index e886a671de0..00000000000 --- a/extern/libmv/patches/snrptinf_fix.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/src/libmv/simple_pipeline/pipeline.cc b/src/libmv/simple_pipeline/pipeline.cc -index 652d70c..25cd2c2 100644 ---- a/src/libmv/simple_pipeline/pipeline.cc -+++ b/src/libmv/simple_pipeline/pipeline.cc -@@ -28,6 +28,10 @@ - #include "libmv/simple_pipeline/tracks.h" - #include "libmv/simple_pipeline/camera_intrinsics.h" - -+#ifdef _MSC_VER -+# define snprintf _snprintf -+#endif -+ - namespace libmv { - - void CompleteReconstruction(const Tracks &tracks, diff --git a/extern/libmv/patches/v3d_verbosity.patch b/extern/libmv/patches/v3d_verbosity.patch index a54f3dc44be..f5c6afbd0b5 100644 --- a/extern/libmv/patches/v3d_verbosity.patch +++ b/extern/libmv/patches/v3d_verbosity.patch @@ -1,12 +1,12 @@ diff --git a/src/libmv/simple_pipeline/bundle.cc b/src/libmv/simple_pipeline/bundle.cc -index 310660d..f819603 100644 +index fa0b6cc..d382cd5 100644 --- a/src/libmv/simple_pipeline/bundle.cc +++ b/src/libmv/simple_pipeline/bundle.cc -@@ -141,7 +141,6 @@ void Bundle(const Tracks &tracks, Reconstruction *reconstruction) { - v3d_distortion.p2 = 0; +@@ -194,7 +194,6 @@ void EuclideanBundleCommonIntrinsics(const Tracks &tracks, + double v3d_inlier_threshold = 500000.0; // Finally, run the bundle adjustment. - V3D::optimizerVerbosenessLevel = 1; - double const inlierThreshold = 500000.0; - V3D::CommonInternalsMetricBundleOptimizer opt(V3D::FULL_BUNDLE_METRIC, - inlierThreshold, + V3D::CommonInternalsMetricBundleOptimizer opt(v3d_bundle_intrinsics, + v3d_inlier_threshold, + v3d_K, diff --git a/extern/libmv/third_party/glog/src/config_freebsd.h b/extern/libmv/third_party/glog/src/config_freebsd.h index caaef9d998b..28fa1f1c78b 100644 --- a/extern/libmv/third_party/glog/src/config_freebsd.h +++ b/extern/libmv/third_party/glog/src/config_freebsd.h @@ -11,7 +11,7 @@ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the <execinfo.h> header file. */ -#define HAVE_EXECINFO_H 1 +#undef HAVE_EXECINFO_H /* Define if you have the `fcntl' function */ #define HAVE_FCNTL 1 diff --git a/extern/libmv/third_party/glog/src/utilities.h b/extern/libmv/third_party/glog/src/utilities.h index 5c841a0b90b..bbb0eb0746c 100644 --- a/extern/libmv/third_party/glog/src/utilities.h +++ b/extern/libmv/third_party/glog/src/utilities.h @@ -101,7 +101,7 @@ // correctly when GetStackTrace() is called with max_depth == 0. // Some code may do that. -#if __MINGW32__ +#if defined(__MINGW32__) || defined(__FreeBSD__) # undef STACKTRACE_H #elif defined(HAVE_LIB_UNWIND) # define STACKTRACE_H "stacktrace_libunwind-inl.h" diff --git a/extern/libredcode/codec.h b/extern/libredcode/codec.h index 928cab589ed..dd239180c10 100644 --- a/extern/libredcode/codec.h +++ b/extern/libredcode/codec.h @@ -1,5 +1,5 @@ -#ifndef __redcode_codec_h_included__ -#define __redcode_codec_h_included__ +#ifndef __CODEC_H__ +#define __CODEC_H__ struct redcode_frame; diff --git a/extern/libredcode/debayer.h b/extern/libredcode/debayer.h index b58c7678671..43564240cc2 100644 --- a/extern/libredcode/debayer.h +++ b/extern/libredcode/debayer.h @@ -1,5 +1,5 @@ -#ifndef __redcode_debayer_h_included__ -#define __redcode_debayer_h_included__ 1 +#ifndef __DEBAYER_H__ +#define __DEBAYER_H__ void redcode_ycbcr2rgb_fullscale( int ** planes, int width, int height, float * out); diff --git a/extern/libredcode/format.h b/extern/libredcode/format.h index b2c6b2d885b..3cee804aa9d 100644 --- a/extern/libredcode/format.h +++ b/extern/libredcode/format.h @@ -1,5 +1,5 @@ -#ifndef __redcode_format_h_included__ -#define __redcode_format_h_included__ +#ifndef __FORMAT_H__ +#define __FORMAT_H__ struct redcode_handle; struct redcode_frame { diff --git a/extern/xdnd/CMakeLists.txt b/extern/xdnd/CMakeLists.txt new file mode 100644 index 00000000000..f7eded73d42 --- /dev/null +++ b/extern/xdnd/CMakeLists.txt @@ -0,0 +1,43 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Sergey Sharybin. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS + +) + +set(SRC + xdnd.c + xdnd.h +) + +add_definitions( + -DHAVE_SYS_TIME_H +) + +blender_add_lib(extern_xdnd "${SRC}" "${INC}" "${INC_SYS}") diff --git a/extern/xdnd/SConscript b/extern/xdnd/SConscript new file mode 100644 index 00000000000..6f1fe72cc28 --- /dev/null +++ b/extern/xdnd/SConscript @@ -0,0 +1,10 @@ +#!/usr/bin/python + +Import('env') + +defs = ['HAVE_SYS_TIME_H'] +sources = env.Glob('*.c') + +incs = '.' + +env.BlenderLib ( 'extern_xdnd', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185]) diff --git a/extern/xdnd/xdnd.c b/extern/xdnd/xdnd.c new file mode 100644 index 00000000000..9bdee89c1ce --- /dev/null +++ b/extern/xdnd/xdnd.c @@ -0,0 +1,1599 @@ +/* xdnd.c, xdnd.h - C program library for handling the Xdnd protocol + Copyright (C) 1996-2000 Paul Sheer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + */ + + +/* + Released 1998-08-07 + Changes: + + 2000-08-08: INCR protocol implemented. + +*/ + +/* + DONE: + - INCR protocol now implemented + + TODO: + - action_choose_dialog not yet supported (never called) + - widget_delete_selection not yet supported and DELETE requests are ignored + - not yet tested with applications that only supported XDND 0 or 1 +*/ + +#include <X11/Xlib.h> +#include <X11/X.h> +#include <X11/Xatom.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif + +#include "xdnd.h" + +static void xdnd_send_enter (DndClass * dnd, Window window, Window from, Atom * typelist); +static void xdnd_send_position (DndClass * dnd, Window window, Window from, Atom action, int x, int y, + unsigned long etime); +static void xdnd_send_status (DndClass * dnd, Window window, Window from, int will_accept, int want_position, + int x, int y, int w, int h, Atom action); +static void xdnd_send_leave (DndClass * dnd, Window window, Window from); +static void xdnd_send_drop (DndClass * dnd, Window window, Window from, unsigned long etime); +static void xdnd_send_finished (DndClass * dnd, Window window, Window from, int error); +static int xdnd_convert_selection (DndClass * dnd, Window window, Window requester, Atom type); +static void xdnd_selection_send (DndClass * dnd, XSelectionRequestEvent * request, unsigned char *data, + int length); +static int xdnd_get_selection (DndClass * dnd, Window from, Atom property, Window insert); + + +/* just to remind us : */ + +#if 0 +typedef struct { + int type; + unsigned long serial; + Bool send_event; + Display *display; + Window window; + Atom message_type; + int format; + union { + char b[20]; + short s[10]; + long l[5]; + } data; +} XClientMessageEvent; +XClientMessageEvent xclient; +#endif + +/* #define DND_DEBUG */ + +#define xdnd_xfree(x) {if (x) { free (x); x = 0; }} + +#ifdef DND_DEBUG + +#include <sys/time.h> +#include <unistd.h> + +char *xdnd_debug_milliseconds (void) +{ + struct timeval tv; + static char r[22]; + gettimeofday (&tv, 0); + sprintf (r, "%.2ld.%.3ld", tv.tv_sec % 100L, tv.tv_usec / 1000L); + return r; +} + +#define dnd_debug1(a) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds ()) +#define dnd_debug2(a,b) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds (), b) +#define dnd_debug3(a,b,c) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds (), b, c) +#define dnd_debug4(a,b,c,d) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds (), b, c, d) +#else +#define dnd_debug1(a) +#define dnd_debug2(a,b) +#define dnd_debug3(a,b,c) +#define dnd_debug4(a,b,c,d) +#endif + +#define dnd_warning(a) fprintf (stderr, a) + +#define dnd_version_at_least(a,b) ((a) >= (b)) + +static unsigned char dnd_copy_cursor_bits[] = +{ + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, + 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0xe8, 0x0f, + 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, + 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, + 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, + 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, + 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static unsigned char dnd_copy_mask_bits[] = +{ + 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, + 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, + 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, + 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, + 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, + 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, + 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, + 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, + 0x00, 0x80, 0x01, 0x00}; + +static unsigned char dnd_move_cursor_bits[] = +{ + 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, + 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, + 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x04, 0x08, 0x02, 0x0c, 0x08, + 0x02, 0x1c, 0x08, 0x02, 0x3c, 0x08, 0x02, 0x7c, 0x08, 0x02, 0xfc, 0x08, + 0x02, 0xfc, 0x09, 0x02, 0xfc, 0x0b, 0x02, 0x7c, 0x08, 0xfe, 0x6d, 0x0f, + 0x00, 0xc4, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x00}; + +static unsigned char dnd_move_mask_bits[] = +{ + 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0x07, 0x00, 0x1c, + 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, + 0x07, 0x00, 0x1c, 0x07, 0x06, 0x1c, 0x07, 0x0e, 0x1c, 0x07, 0x1e, 0x1c, + 0x07, 0x3e, 0x1c, 0x07, 0x7e, 0x1c, 0x07, 0xfe, 0x1c, 0x07, 0xfe, 0x1d, + 0x07, 0xfe, 0x1f, 0x07, 0xfe, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1e, + 0xff, 0xef, 0x1f, 0x00, 0xe6, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, + 0x00, 0x80, 0x01}; + +static unsigned char dnd_link_cursor_bits[] = +{ + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, + 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0xe8, 0x0f, + 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x08, 0x01, + 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, + 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, + 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, + 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static unsigned char dnd_link_mask_bits[] = +{ + 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, + 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, + 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, + 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, + 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, + 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, + 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, + 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, + 0x00, 0x80, 0x01, 0x00}; + +static unsigned char dnd_ask_cursor_bits[] = +{ + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x88, 0x03, + 0x02, 0x00, 0x48, 0x04, 0x02, 0x00, 0x08, 0x04, 0x02, 0x00, 0x08, 0x02, + 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, + 0x02, 0x00, 0x08, 0x01, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, + 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, + 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, + 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +static unsigned char dnd_ask_mask_bits[] = +{ + 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, + 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, + 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, + 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, + 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, + 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, + 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, + 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, + 0x00, 0x80, 0x01, 0x00}; + +static DndCursor dnd_cursors[] = +{ + {29, 25, 10, 10, dnd_copy_cursor_bits, dnd_copy_mask_bits, "XdndActionCopy", 0, 0, 0, 0}, + {21, 25, 10, 10, dnd_move_cursor_bits, dnd_move_mask_bits, "XdndActionMove", 0, 0, 0, 0}, + {29, 25, 10, 10, dnd_link_cursor_bits, dnd_link_mask_bits, "XdndActionLink", 0, 0, 0, 0}, + {29, 25, 10, 10, dnd_ask_cursor_bits, dnd_ask_mask_bits, "XdndActionAsk", 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +void xdnd_reset (DndClass * dnd) +{ + dnd->stage = XDND_DROP_STAGE_IDLE; + dnd->dragging_version = 0; + dnd->internal_drag = 0; + dnd->want_position = 0; + dnd->ready_to_drop = 0; + dnd->will_accept = 0; + dnd->rectangle.x = dnd->rectangle.y = 0; + dnd->rectangle.width = dnd->rectangle.height = 0; + dnd->dropper_window = 0; + dnd->dropper_toplevel = 0; + dnd->dragger_window = 0; + dnd->dragger_typelist = 0; + dnd->desired_type = 0; + dnd->time = 0; +} + +void xdnd_init (DndClass * dnd, Display * display) +{ + DndCursor *cursor; + XColor black, white; + memset (dnd, 0, sizeof (*dnd)); + + dnd->display = display; + dnd->root_window = DefaultRootWindow (display); + dnd->version = XDND_VERSION; + + dnd->XdndAware = XInternAtom (dnd->display, "XdndAware", False); + dnd->XdndSelection = XInternAtom (dnd->display, "XdndSelection", False); + dnd->XdndEnter = XInternAtom (dnd->display, "XdndEnter", False); + dnd->XdndLeave = XInternAtom (dnd->display, "XdndLeave", False); + dnd->XdndPosition = XInternAtom (dnd->display, "XdndPosition", False); + dnd->XdndDrop = XInternAtom (dnd->display, "XdndDrop", False); + dnd->XdndFinished = XInternAtom (dnd->display, "XdndFinished", False); + dnd->XdndStatus = XInternAtom (dnd->display, "XdndStatus", False); + dnd->XdndActionCopy = XInternAtom (dnd->display, "XdndActionCopy", False); + dnd->XdndActionMove = XInternAtom (dnd->display, "XdndActionMove", False); + dnd->XdndActionLink = XInternAtom (dnd->display, "XdndActionLink", False); + dnd->XdndActionAsk = XInternAtom (dnd->display, "XdndActionAsk", False); + dnd->XdndActionPrivate = XInternAtom (dnd->display, "XdndActionPrivate", False); + dnd->XdndTypeList = XInternAtom (dnd->display, "XdndTypeList", False); + dnd->XdndActionList = XInternAtom (dnd->display, "XdndActionList", False); + dnd->XdndActionDescription = XInternAtom (dnd->display, "XdndActionDescription", False); + + dnd->Xdnd_NON_PROTOCOL_ATOM = XInternAtom (dnd->display, "JXSelectionWindowProperty", False); + + xdnd_reset (dnd); + + dnd->cursors = dnd_cursors; + + black.pixel = BlackPixel (dnd->display, DefaultScreen (dnd->display)); + white.pixel = WhitePixel (dnd->display, DefaultScreen (dnd->display)); + + XQueryColor (dnd->display, DefaultColormap (dnd->display, DefaultScreen (dnd->display)), &black); + XQueryColor (dnd->display, DefaultColormap (dnd->display, DefaultScreen (dnd->display)), &white); + + for (cursor = &dnd->cursors[0]; cursor->width; cursor++) { + cursor->image_pixmap = XCreateBitmapFromData \ + (dnd->display, dnd->root_window, (char *) cursor->image_data, cursor->width, cursor->height); + cursor->mask_pixmap = XCreateBitmapFromData \ + (dnd->display, dnd->root_window, (char *) cursor->mask_data, cursor->width, cursor->height); + cursor->cursor = XCreatePixmapCursor (dnd->display, cursor->image_pixmap, + cursor->mask_pixmap, &black, &white, cursor->x, cursor->y); + XFreePixmap (dnd->display, cursor->image_pixmap); + XFreePixmap (dnd->display, cursor->mask_pixmap); + cursor->action = XInternAtom (dnd->display, cursor->_action, False); + } +} + +void xdnd_shut (DndClass * dnd) +{ + DndCursor *cursor; + for (cursor = &dnd->cursors[0]; cursor->width; cursor++) + XFreeCursor (dnd->display, cursor->cursor); + memset (dnd, 0, sizeof (*dnd)); + return; +} + + +/* typelist is a null terminated array */ +static int array_length (Atom * a) +{ + int n; + for (n = 0; a[n]; n++); + return n; +} + +void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist) +{ + Window root_return, parent; + unsigned int nchildren_return; + Window *children_return = 0; + int r, s; + if(!window) return; + if (dnd->widget_exists) + if (!(*dnd->widget_exists) (dnd, window)) + return; + s = XChangeProperty (dnd->display, window, dnd->XdndAware, XA_ATOM, 32, PropModeReplace, + (unsigned char *) &dnd->version, 1); +#if 1 + dnd_debug4 ("XChangeProperty() = %d, window = %ld, widget = %s", s, window, "<WIDGET>"); +#endif + if (s && typelist) { + int n; + n = array_length (typelist); + if (n) + s = XChangeProperty (dnd->display, window, dnd->XdndAware, XA_ATOM, 32, PropModeAppend, + (unsigned char *) typelist, n); + } + r = + XQueryTree (dnd->display, window, &root_return, &parent, &children_return, + &nchildren_return); + if (children_return) + XFree (children_return); + if (r) + xdnd_set_dnd_aware (dnd, parent, typelist); +} + +int xdnd_is_dnd_aware (DndClass * dnd, Window window, int *version, Atom * typelist) +{ + Atom actual; + int format; + unsigned long count, remaining; + unsigned char *data = 0; + Atom *types, *t; + int result = 1; + + *version = 0; + XGetWindowProperty (dnd->display, window, dnd->XdndAware, + 0, 0x8000000L, False, XA_ATOM, + &actual, &format, + &count, &remaining, &data); + + if (actual != XA_ATOM || format != 32 || count == 0 || !data) { + dnd_debug2 ("XGetWindowProperty failed in xdnd_is_dnd_aware - XdndAware = %ld", dnd->XdndAware); + if (data) + XFree (data); + return 0; + } + types = (Atom *) data; +#if XDND_VERSION >= 3 + if (types[0] < 3) { + if (data) + XFree (data); + return 0; + } +#endif + *version = dnd->version < types[0] ? dnd->version : types[0]; /* minimum */ + dnd_debug2 ("Using XDND version %d", *version); + if (count > 1) { + result = 0; + for (t = typelist; *t; t++) { + int j; + for (j = 1; j < count; j++) { + if (types[j] == *t) { + result = 1; + break; + } + } + if (result) + break; + } + } + XFree (data); + return result; +} + +void xdnd_set_type_list (DndClass * dnd, Window window, Atom * typelist) +{ + int n; + n = array_length (typelist); + XChangeProperty (dnd->display, window, dnd->XdndTypeList, XA_ATOM, 32, + PropModeReplace, (unsigned char *) typelist, n); +} + +/* result must be free'd */ +void xdnd_get_type_list (DndClass * dnd, Window window, Atom ** typelist) +{ + Atom type, *a; + int format, i; + unsigned long count, remaining; + unsigned char *data = NULL; + + *typelist = 0; + + XGetWindowProperty (dnd->display, window, dnd->XdndTypeList, + 0, 0x8000000L, False, XA_ATOM, + &type, &format, &count, &remaining, &data); + + if (type != XA_ATOM || format != 32 || count == 0 || !data) { + if (data) + XFree (data); + dnd_debug2 ("XGetWindowProperty failed in xdnd_get_type_list - dnd->XdndTypeList = %ld", dnd->XdndTypeList); + return; + } + *typelist = malloc ((count + 1) * sizeof (Atom)); + a = (Atom *) data; + for (i = 0; i < count; i++) + (*typelist)[i] = a[i]; + (*typelist)[count] = 0; + + XFree (data); +} + +void xdnd_get_three_types (DndClass * dnd, XEvent * xevent, Atom ** typelist) +{ + int i; + *typelist = malloc ((XDND_THREE + 1) * sizeof (Atom)); + for (i = 0; i < XDND_THREE; i++) + (*typelist)[i] = XDND_ENTER_TYPE (xevent, i); + (*typelist)[XDND_THREE] = 0; /* although (*typelist)[1] or (*typelist)[2] may also be set to nill */ +} + +/* result must be free'd */ +static char *concat_string_list (char **t, int *bytes) +{ + int l, n; + char *s; + for (l = n = 0;; n++) { + if (!t[n]) + break; + if (!t[n][0]) + break; + l += strlen (t[n]) + 1; + } + s = malloc (l + 1); + for (l = n = 0;; n++) { + if (!t[n]) + break; + if (!(t[n][0])) + break; + strcpy (s + l, t[n]); + l += strlen (t[n]) + 1; + } + *bytes = l; + s[l] = '\0'; + return s; +} + +void xdnd_set_actions (DndClass * dnd, Window window, Atom * actions, char **descriptions) +{ + int n, l; + char *s; + n = array_length (actions); + + XChangeProperty (dnd->display, window, dnd->XdndActionList, XA_ATOM, 32, + PropModeReplace, (unsigned char *) actions, n); + + s = concat_string_list (descriptions, &l); + XChangeProperty (dnd->display, window, dnd->XdndActionList, XA_STRING, 8, + PropModeReplace, (unsigned char *) s, l); + xdnd_xfree (s); +} + +/* returns 1 on error or no actions, otherwise result must be free'd + xdnd_get_actions (window, &actions, &descriptions); + free (actions); free (descriptions); */ +int xdnd_get_actions (DndClass * dnd, Window window, Atom ** actions, char ***descriptions) +{ + Atom type, *a; + int format, i; + unsigned long count, dcount, remaining; + unsigned char *data = 0, *r; + + *actions = 0; + *descriptions = 0; + XGetWindowProperty (dnd->display, window, dnd->XdndActionList, + 0, 0x8000000L, False, XA_ATOM, + &type, &format, &count, &remaining, &data); + + if (type != XA_ATOM || format != 32 || count == 0 || !data) { + if (data) + XFree (data); + return 1; + } + *actions = malloc ((count + 1) * sizeof (Atom)); + a = (Atom *) data; + for (i = 0; i < count; i++) + (*actions)[i] = a[i]; + (*actions)[count] = 0; + + XFree (data); + + data = 0; + XGetWindowProperty (dnd->display, window, dnd->XdndActionDescription, + 0, 0x8000000L, False, XA_STRING, &type, &format, + &dcount, &remaining, &data); + + if (type != XA_STRING || format != 8 || dcount == 0) { + if (data) + XFree (data); + *descriptions = malloc ((count + 1) * sizeof (char *)); + dnd_warning ("XGetWindowProperty no property or wrong format for action descriptions"); + for (i = 0; i < count; i++) + (*descriptions)[i] = ""; + (*descriptions)[count] = 0; + } else { + int l; + l = (count + 1) * sizeof (char *); + *descriptions = malloc (l + dcount); + memcpy (*descriptions + l, data, dcount); + XFree (data); + data = (unsigned char *) *descriptions; + data += l; + l = 0; + for (i = 0, r = data;; r += l + 1, i++) { + l = strlen ((char *) r); + if (!l || i >= count) + break; + (*descriptions)[i] = (char *) r; + } + for (; i < count; i++) { + (*descriptions)[i] = ""; + } + (*descriptions)[count] = 0; + } + return 0; +} + +/* returns non-zero on cancel */ +int xdnd_choose_action_dialog (DndClass * dnd, Atom * actions, char **descriptions, Atom * result) +{ + if (!actions[0]) + return 1; + if (!dnd->action_choose_dialog) { /* default to return the first action if no dialog set */ + *result = actions[0]; + return 0; + } + return (*dnd->action_choose_dialog) (dnd, descriptions, actions, result); +} + +static void xdnd_send_event (DndClass * dnd, Window window, XEvent * xevent) +{ + dnd_debug4 ("xdnd_send_event(), window = %ld, l[0] = %ld, l[4] = %ld", + window, xevent->xclient.data.l[0], xevent->xclient.data.l[4]); + dnd_debug2 ("xdnd_send_event(), from widget widget %s", (char *) "<WIDGET>"); + XSendEvent (dnd->display, window, 0, 0, xevent); +} + +static void xdnd_send_enter (DndClass * dnd, Window window, Window from, Atom * typelist) +{ + XEvent xevent; + int n, i; + n = array_length (typelist); + + memset (&xevent, 0, sizeof (xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = dnd->display; + xevent.xclient.window = window; + xevent.xclient.message_type = dnd->XdndEnter; + xevent.xclient.format = 32; + + XDND_ENTER_SOURCE_WIN (&xevent) = from; + XDND_ENTER_THREE_TYPES_SET (&xevent, n > XDND_THREE); + XDND_ENTER_VERSION_SET (&xevent, dnd->version); + for (i = 0; i < n && i < XDND_THREE; i++) + XDND_ENTER_TYPE (&xevent, i) = typelist[i]; + xdnd_send_event (dnd, window, &xevent); +} + +static void xdnd_send_position (DndClass * dnd, Window window, Window from, Atom action, int x, int y, unsigned long time) +{ + XEvent xevent; + + memset (&xevent, 0, sizeof (xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = dnd->display; + xevent.xclient.window = window; + xevent.xclient.message_type = dnd->XdndPosition; + xevent.xclient.format = 32; + + XDND_POSITION_SOURCE_WIN (&xevent) = from; + XDND_POSITION_ROOT_SET (&xevent, x, y); + if (dnd_version_at_least (dnd->dragging_version, 1)) + XDND_POSITION_TIME (&xevent) = time; + if (dnd_version_at_least (dnd->dragging_version, 2)) + XDND_POSITION_ACTION (&xevent) = action; + + xdnd_send_event (dnd, window, &xevent); +} + +static void xdnd_send_status (DndClass * dnd, Window window, Window from, int will_accept, \ + int want_position, int x, int y, int w, int h, Atom action) +{ + XEvent xevent; + + memset (&xevent, 0, sizeof (xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = dnd->display; + xevent.xclient.window = window; + xevent.xclient.message_type = dnd->XdndStatus; + xevent.xclient.format = 32; + + XDND_STATUS_TARGET_WIN (&xevent) = from; + XDND_STATUS_WILL_ACCEPT_SET (&xevent, will_accept); + if (will_accept) + XDND_STATUS_WANT_POSITION_SET (&xevent, want_position); + if (want_position) + XDND_STATUS_RECT_SET (&xevent, x, y, w, h); + if (dnd_version_at_least (dnd->dragging_version, 2)) + if (will_accept) + XDND_STATUS_ACTION (&xevent) = action; + + xdnd_send_event (dnd, window, &xevent); +} + +static void xdnd_send_leave (DndClass * dnd, Window window, Window from) +{ + XEvent xevent; + + memset (&xevent, 0, sizeof (xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = dnd->display; + xevent.xclient.window = window; + xevent.xclient.message_type = dnd->XdndLeave; + xevent.xclient.format = 32; + + XDND_LEAVE_SOURCE_WIN (&xevent) = from; + + xdnd_send_event (dnd, window, &xevent); +} + +static void xdnd_send_drop (DndClass * dnd, Window window, Window from, unsigned long time) +{ + XEvent xevent; + + memset (&xevent, 0, sizeof (xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = dnd->display; + xevent.xclient.window = window; + xevent.xclient.message_type = dnd->XdndDrop; + xevent.xclient.format = 32; + + XDND_DROP_SOURCE_WIN (&xevent) = from; + if (dnd_version_at_least (dnd->dragging_version, 1)) + XDND_DROP_TIME (&xevent) = time; + + xdnd_send_event (dnd, window, &xevent); +} + +/* error is not actually used, i think future versions of the protocol should return an error status + to the calling window with the XdndFinished client message */ +static void xdnd_send_finished (DndClass * dnd, Window window, Window from, int error) +{ + XEvent xevent; + + memset (&xevent, 0, sizeof (xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = dnd->display; + xevent.xclient.window = window; + xevent.xclient.message_type = dnd->XdndFinished; + xevent.xclient.format = 32; + + XDND_FINISHED_TARGET_WIN (&xevent) = from; + + xdnd_send_event (dnd, window, &xevent); +} + +/* returns non-zero on error - i.e. no selection owner set. Type is of course the mime type */ +static int xdnd_convert_selection (DndClass * dnd, Window window, Window requester, Atom type) +{ + if (!(window = XGetSelectionOwner (dnd->display, dnd->XdndSelection))) { + dnd_debug1 ("xdnd_convert_selection(): XGetSelectionOwner failed"); + return 1; + } + XConvertSelection (dnd->display, dnd->XdndSelection, type, + dnd->Xdnd_NON_PROTOCOL_ATOM, requester, CurrentTime); + return 0; +} + +/* returns non-zero on error */ +static int xdnd_set_selection_owner (DndClass * dnd, Window window, Atom type, Time time) +{ + if (!XSetSelectionOwner (dnd->display, dnd->XdndSelection, window, time)) { + dnd_debug1 ("xdnd_set_selection_owner(): XSetSelectionOwner failed"); + return 1; + } + return 0; +} + +static void xdnd_selection_send (DndClass * dnd, XSelectionRequestEvent * request, unsigned char *data, int length) +{ + XEvent xevent; + dnd_debug2 (" requestor = %ld", request->requestor); + dnd_debug2 (" property = %ld", request->property); + dnd_debug2 (" length = %d", length); + XChangeProperty (dnd->display, request->requestor, request->property, + request->target, 8, PropModeReplace, data, length); + xevent.xselection.type = SelectionNotify; + xevent.xselection.property = request->property; + xevent.xselection.display = request->display; + xevent.xselection.requestor = request->requestor; + xevent.xselection.selection = request->selection; + xevent.xselection.target = request->target; + xevent.xselection.time = request->time; + xdnd_send_event (dnd, request->requestor, &xevent); +} + +#if 0 +/* respond to a notification that a primary selection has been sent */ +int xdnd_get_selection (DndClass * dnd, Window from, Atom property, Window insert) +{ + long read; + int error = 0; + unsigned long remaining; + if (!property) + return 1; + read = 0; + do { + unsigned char *s; + Atom actual; + int format; + unsigned long count; + if (XGetWindowProperty (dnd->display, insert, property, read / 4, 65536, 1, + AnyPropertyType, &actual, &format, + &count, &remaining, + &s) != Success) { + XFree (s); + return 1; + } + read += count; + if (dnd->widget_insert_drop && !error) + error = (*dnd->widget_insert_drop) (dnd, s, count, remaining, insert, from, actual); + XFree (s); + } while (remaining); + return error; +} +#endif + +static int paste_prop_internal (DndClass * dnd, Window from, Window insert, unsigned long prop, int delete_prop) +{ + long nread = 0; + unsigned long nitems; + unsigned long bytes_after; + int error = 0; + do { + Atom actual_type; + int actual_fmt; + unsigned char *s = 0; + if (XGetWindowProperty (dnd->display, insert, prop, + nread / 4, 65536, delete_prop, + AnyPropertyType, &actual_type, &actual_fmt, + &nitems, &bytes_after, &s) != Success) { + XFree (s); + return 1; + } + nread += nitems; + if (dnd->widget_insert_drop && !error) + error = (*dnd->widget_insert_drop) (dnd, s, nitems, bytes_after, insert, from, actual_fmt); + XFree (s); + } while (bytes_after); + if (!nread) + return 1; + return 0; +} + +/* + * Respond to a notification that a primary selection has been sent (supports INCR) + */ +static int xdnd_get_selection (DndClass * dnd, Window from, Atom prop, Window insert) +{ + struct timeval tv, tv_start; + unsigned long bytes_after; + Atom actual_type; + int actual_fmt; + unsigned long nitems; + unsigned char *s = 0; + if (prop == None) + return 1; + if (XGetWindowProperty + (dnd->display, insert, prop, 0, 8, False, AnyPropertyType, &actual_type, &actual_fmt, + &nitems, &bytes_after, &s) != Success) { + XFree (s); + return 1; + } + XFree (s); + if (actual_type != XInternAtom (dnd->display, "INCR", False)) + return paste_prop_internal (dnd, from, insert, prop, True); + XDeleteProperty (dnd->display, insert, prop); + gettimeofday (&tv_start, 0); + for (;;) { + long t; + fd_set r; + XEvent xe; + if (XCheckMaskEvent (dnd->display, PropertyChangeMask, &xe)) { + if (xe.type == PropertyNotify && xe.xproperty.state == PropertyNewValue) { +/* time between arrivals of data */ + gettimeofday (&tv_start, 0); + if (paste_prop_internal (dnd, from, insert, prop, True)) + break; + } + } else { + tv.tv_sec = 0; + tv.tv_usec = 10000; + FD_ZERO (&r); + FD_SET (ConnectionNumber (dnd->display), &r); + select (ConnectionNumber (dnd->display) + 1, &r, 0, 0, &tv); + if (FD_ISSET (ConnectionNumber (dnd->display), &r)) + continue; + } + gettimeofday (&tv, 0); + t = (tv.tv_sec - tv_start.tv_sec) * 1000000L + (tv.tv_usec - tv_start.tv_usec); +/* no data for five seconds, so quit */ + if (t > 5000000L) + return 1; + } + return 0; +} + + +int outside_rectangle (int x, int y, XRectangle * r) +{ + return (x < r->x || y < r->y || x >= r->x + r->width || y >= r->y + r->height); +} + +/* avoids linking with the maths library */ +static float xdnd_sqrt (float x) +{ + float last_ans, ans = 2, a; + if (x <= 0.0) + return 0.0; + do { + last_ans = ans; + ans = (ans + x / ans) / 2; + a = (ans - last_ans) / ans; + if (a < 0.0) + a = (-a); + } while (a > 0.001); + return ans; +} + +#define print_marks print_win_marks(from,__FILE__,__LINE__); + +/* returns action on success, 0 otherwise */ +Atom xdnd_drag (DndClass * dnd, Window from, Atom action, Atom * typelist) +{ + XEvent xevent, xevent_temp; + Window over_window = 0, last_window = 0; +#if XDND_VERSION >= 3 + Window last_dropper_toplevel = 0; + int internal_dropable = 1; +#endif + int n; + DndCursor *cursor; + float x_mouse, y_mouse; + int result = 0, dnd_aware; + + if (!typelist) + dnd_warning ("xdnd_drag() called with typelist = 0"); + +/* first wait until the mouse moves more than five pixels */ + do { + XNextEvent (dnd->display, &xevent); + if (xevent.type == ButtonRelease) { + dnd_debug1 ("button release - no motion"); + XSendEvent (dnd->display, xevent.xany.window, 0, ButtonReleaseMask, &xevent); + return 0; + } + } while (xevent.type != MotionNotify); + + x_mouse = (float) xevent.xmotion.x_root; + y_mouse = (float) xevent.xmotion.y_root; + + if (!dnd->drag_threshold) + dnd->drag_threshold = 4.0; + for (;;) { + XNextEvent (dnd->display, &xevent); + if (xevent.type == MotionNotify) + if (xdnd_sqrt ((x_mouse - xevent.xmotion.x_root) * (x_mouse - xevent.xmotion.x_root) + + (y_mouse - xevent.xmotion.y_root) * (y_mouse - xevent.xmotion.y_root)) > dnd->drag_threshold) + break; + if (xevent.type == ButtonRelease) { + XSendEvent (dnd->display, xevent.xany.window, 0, ButtonReleaseMask, &xevent); + return 0; + } + } + + dnd_debug1 ("moved 5 pixels - going to drag"); + + n = array_length (typelist); + if (n > XDND_THREE) + xdnd_set_type_list (dnd, from, typelist); + + xdnd_reset (dnd); + + dnd->stage = XDND_DRAG_STAGE_DRAGGING; + + for (cursor = &dnd->cursors[0]; cursor->width; cursor++) + if (cursor->action == action) + break; + if (!cursor->width) + cursor = &dnd->cursors[0]; + +/* the mouse has been dragged a little, so this is a drag proper */ + if (XGrabPointer (dnd->display, dnd->root_window, False, + ButtonMotionMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, None, + cursor->cursor, CurrentTime) != GrabSuccess) + dnd_debug1 ("Unable to grab pointer"); + + + while (xevent.xany.type != ButtonRelease) { + XAllowEvents (dnd->display, SyncPointer, CurrentTime); + XNextEvent (dnd->display, &xevent); + switch (xevent.type) { + case Expose: + if (dnd->handle_expose_events) + (*dnd->handle_expose_events) (dnd, &xevent); + break; + case EnterNotify: +/* this event is not actually reported, so we find out by ourselves from motion events */ + break; + case LeaveNotify: +/* this event is not actually reported, so we find out by ourselves from motion events */ + break; + case ButtonRelease: +/* done, but must send a leave event */ + dnd_debug1 ("ButtonRelease - exiting event loop"); + break; + case MotionNotify: + dnd_aware = 0; + dnd->dropper_toplevel = 0; + memcpy (&xevent_temp, &xevent, sizeof (xevent)); + xevent.xmotion.subwindow = xevent.xmotion.window; + { + Window root_return, child_return; + int x_temp, y_temp; + unsigned int mask_return; + while (XQueryPointer (dnd->display, xevent.xmotion.subwindow, &root_return, &child_return, + &x_temp, &y_temp, &xevent.xmotion.x, + &xevent.xmotion.y, &mask_return)) { +#if XDND_VERSION >= 3 + if (!dnd_aware) { + if ((dnd_aware = xdnd_is_dnd_aware (dnd, xevent.xmotion.subwindow, &dnd->dragging_version, typelist))) { + dnd->dropper_toplevel = xevent.xmotion.subwindow; + xevent.xmotion.x_root = x_temp; + xevent.xmotion.y_root = y_temp; + } + } +#else + xevent.xmotion.x_root = x_temp; + xevent.xmotion.y_root = y_temp; +#endif + if (!child_return) + goto found_descendent; + xevent.xmotion.subwindow = child_return; + } + break; + } + found_descendent: + +/* last_window is just for debug purposes */ + if (last_window != xevent.xmotion.subwindow) { + dnd_debug2 ("window crossing to %ld", xevent.xmotion.subwindow); + dnd_debug2 (" current window is %ld", over_window); + dnd_debug3 (" last_window = %ld, xmotion.subwindow = %ld", last_window, xevent.xmotion.subwindow); +#if XDND_VERSION >= 3 + dnd_debug3 (" dropper_toplevel = %ld, last_dropper_toplevel.subwindow = %ld", dnd->dropper_toplevel, last_dropper_toplevel); +#endif + dnd_debug3 (" dnd_aware = %d, dnd->options & XDND_OPTION_NO_HYSTERESIS = %ld", dnd_aware, (long) dnd->options & XDND_OPTION_NO_HYSTERESIS); + } + +#if XDND_VERSION < 3 +/* is the new window dnd aware? if not stay in the old window */ + if (over_window != xevent.xmotion.subwindow && + last_window != xevent.xmotion.subwindow && + ( + (dnd_aware = xdnd_is_dnd_aware (dnd, xevent.xmotion.subwindow, &dnd->dragging_version, typelist)) + || + (dnd->options & XDND_OPTION_NO_HYSTERESIS) + )) +#else + internal_dropable = 1; + if (dnd->widget_exists && (*dnd->widget_exists) (dnd, xevent.xmotion.subwindow)) + if (!xdnd_is_dnd_aware (dnd, xevent.xmotion.subwindow, &dnd->dragging_version, typelist)) + internal_dropable = 0; + dnd_debug3 ("dnd->dropper_toplevel = %ld, last_dropper_toplevel = %ld\n", dnd->dropper_toplevel, last_dropper_toplevel); + if ((dnd->dropper_toplevel != last_dropper_toplevel || + last_window != xevent.xmotion.subwindow) && internal_dropable && + ( + (dnd_aware) + || + (dnd->options & XDND_OPTION_NO_HYSTERESIS) + )) +#endif + { +/* leaving window we were over */ + if (over_window) { + if (dnd->stage == XDND_DRAG_STAGE_ENTERED) { + dnd_debug1 ("got leave at right stage"); + dnd->stage = XDND_DRAG_STAGE_DRAGGING; + if (dnd->internal_drag) { + dnd_debug1 (" our own widget"); + if (dnd->widget_apply_leave) + (*dnd->widget_apply_leave) (dnd, over_window); + } else { + dnd_debug1 (" not our widget - sending XdndLeave"); +#if XDND_VERSION < 3 + xdnd_send_leave (dnd, over_window, from); +#else + if (dnd->dropper_toplevel != last_dropper_toplevel) { + xdnd_send_leave (dnd, last_dropper_toplevel, from); + } else { + dnd_debug1 (" not sending leave --> dnd->dropper_toplevel == last_dropper_toplevel"); + } +#endif + } + dnd->internal_drag = 0; + dnd->dropper_window = 0; + dnd->ready_to_drop = 0; + } else { + dnd_debug1 ("got leave at wrong stage - ignoring"); + } + } +/* entering window we are currently over */ + over_window = xevent.xmotion.subwindow; + if (dnd_aware) { + dnd_debug1 (" is dnd aware"); + dnd->stage = XDND_DRAG_STAGE_ENTERED; + if (dnd->widget_exists && (*dnd->widget_exists) (dnd, over_window)) + dnd->internal_drag = 1; + if (dnd->internal_drag) { + dnd_debug1 (" our own widget"); + } else { + dnd_debug2 (" not our widget - sending XdndEnter to %ld", over_window); +#if XDND_VERSION < 3 + xdnd_send_enter (dnd, over_window, from, typelist); +#else + if (dnd->dropper_toplevel != last_dropper_toplevel) + xdnd_send_enter (dnd, dnd->dropper_toplevel, from, typelist); +#endif + } + dnd->want_position = 1; + dnd->ready_to_drop = 0; + dnd->rectangle.width = dnd->rectangle.height = 0; + dnd->dropper_window = over_window; +/* we want an additional motion event in case the pointer enters and then stops */ + XSendEvent (dnd->display, from, 0, ButtonMotionMask, &xevent_temp); + XSync (dnd->display, 0); + } +#if XDND_VERSION >= 3 + last_dropper_toplevel = dnd->dropper_toplevel; +#endif +/* we are now officially in a new window */ + } else { +/* got here, so we are just moving `inside' the same window */ + if (dnd->stage == XDND_DRAG_STAGE_ENTERED) { + dnd->supported_action = dnd->XdndActionCopy; + dnd_debug1 ("got motion at right stage"); + dnd->x = xevent.xmotion.x_root; + dnd->y = xevent.xmotion.y_root; + if (dnd->want_position || outside_rectangle (dnd->x, dnd->y, &dnd->rectangle)) { + dnd_debug1 (" want position and outside rectangle"); + if (dnd->internal_drag) { + dnd_debug1 (" our own widget"); + dnd->ready_to_drop = (*dnd->widget_apply_position) (dnd, over_window, from, + action, dnd->x, dnd->y, xevent.xmotion.time, typelist, + &dnd->want_position, &dnd->supported_action, &dnd->desired_type, &dnd->rectangle); + /* if not ready, keep sending positions, this check is repeated below for XdndStatus from external widgets */ + if (!dnd->ready_to_drop) { + dnd->want_position = 1; + dnd->rectangle.width = dnd->rectangle.height = 0; + } + dnd_debug2 (" return action=%ld", dnd->supported_action); + } else { +#if XDND_VERSION < 3 + dnd_debug3 (" not our own widget - sending XdndPosition to %ld, action %ld", over_window, action); + xdnd_send_position (dnd, over_window, from, action, dnd->x, dnd->y, xevent.xmotion.time); +#else + dnd_debug3 (" not our own widget - sending XdndPosition to %ld, action %ld", dnd->dropper_toplevel, action); + xdnd_send_position (dnd, dnd->dropper_toplevel, from, action, dnd->x, dnd->y, xevent.xmotion.time); +#endif + } + } else if (dnd->want_position) { + dnd_debug1 (" inside rectangle"); + } else { + dnd_debug1 (" doesn't want position"); + } + } + } + last_window = xevent.xmotion.subwindow; + break; + case ClientMessage: + dnd_debug1 ("ClientMessage recieved"); + if (xevent.xclient.message_type == dnd->XdndStatus && !dnd->internal_drag) { + dnd_debug1 (" XdndStatus recieved"); + if (dnd->stage == XDND_DRAG_STAGE_ENTERED +#if XDND_VERSION < 3 + && XDND_STATUS_TARGET_WIN (&xevent) == dnd->dropper_window +#endif + ) { + dnd_debug1 (" XdndStatus stage correct, dropper window correct"); + dnd->want_position = XDND_STATUS_WANT_POSITION (&xevent); + dnd->ready_to_drop = XDND_STATUS_WILL_ACCEPT (&xevent); + dnd->rectangle.x = XDND_STATUS_RECT_X (&xevent); + dnd->rectangle.y = XDND_STATUS_RECT_Y (&xevent); + dnd->rectangle.width = XDND_STATUS_RECT_WIDTH (&xevent); + dnd->rectangle.height = XDND_STATUS_RECT_HEIGHT (&xevent); + dnd->supported_action = dnd->XdndActionCopy; + if (dnd_version_at_least (dnd->dragging_version, 2)) + dnd->supported_action = XDND_STATUS_ACTION (&xevent); + dnd_debug3 (" return action=%ld, ready=%d", dnd->supported_action, dnd->ready_to_drop); + /* if not ready, keep sending positions, this check is repeated above for internal widgets */ + if (!dnd->ready_to_drop) { + dnd->want_position = 1; + dnd->rectangle.width = dnd->rectangle.height = 0; + } + dnd_debug3 (" rectangle = (x=%d, y=%d, ", dnd->rectangle.x, dnd->rectangle.y); + dnd_debug4 ("w=%d, h=%d), want_position=%d\n", dnd->rectangle.width, dnd->rectangle.height, dnd->want_position); + } +#if XDND_VERSION < 3 + else if (XDND_STATUS_TARGET_WIN (&xevent) != dnd->dropper_window) { + dnd_debug3 (" XdndStatus XDND_STATUS_TARGET_WIN (&xevent) = %ld, dnd->dropper_window = %ld", XDND_STATUS_TARGET_WIN (&xevent), dnd->dropper_window); + } +#endif + else { + dnd_debug2 (" XdndStatus stage incorrect dnd->stage = %d", dnd->stage); + } + } + break; + case SelectionRequest:{ +/* the target widget MAY request data, so wait for SelectionRequest */ + int length = 0; + unsigned char *data = 0; + dnd_debug1 ("SelectionRequest - getting widget data"); + + (*dnd->widget_get_data) (dnd, from, &data, &length, xevent.xselectionrequest.target); + if (data) { + dnd_debug1 (" sending selection"); + xdnd_selection_send (dnd, &xevent.xselectionrequest, data, length); + xdnd_xfree (data); + } + } + break; + } + } + + if (dnd->ready_to_drop) { + Time time; + dnd_debug1 ("ready_to_drop - sending XdndDrop"); + time = xevent.xbutton.time; + if (dnd->internal_drag) { +/* we are dealing with our own widget, no need to send drop events, just put the data straight */ + int length = 0; + unsigned char *data = 0; + if (dnd->widget_insert_drop) { + (*dnd->widget_get_data) (dnd, from, &data, &length, dnd->desired_type); + if (data) { + if (!(*dnd->widget_insert_drop) (dnd, data, length, 0, dnd->dropper_window, from, dnd->desired_type)) { + result = dnd->supported_action; /* success - so return action to caller */ + dnd_debug1 (" inserted data into widget - success"); + } else { + dnd_debug1 (" inserted data into widget - failed"); + } + xdnd_xfree (data); + } else { + dnd_debug1 (" got data from widget, but data is null"); + } + } + } else { + xdnd_set_selection_owner (dnd, from, dnd->desired_type, time); +#if XDND_VERSION < 3 + xdnd_send_drop (dnd, dnd->dropper_window, from, time); +#else + xdnd_send_drop (dnd, dnd->dropper_toplevel, from, time); +#endif + } + if (!dnd->internal_drag) + for (;;) { + XAllowEvents (dnd->display, SyncPointer, CurrentTime); + XNextEvent (dnd->display, &xevent); + if (xevent.type == ClientMessage && xevent.xclient.message_type == dnd->XdndFinished) { + dnd_debug1 ("XdndFinished"); +#if XDND_VERSION < 3 + if (XDND_FINISHED_TARGET_WIN (&xevent) == dnd->dropper_window) { +#endif + dnd_debug2 (" source correct - exiting event loop, action=%ld", dnd->supported_action); + result = dnd->supported_action; /* success - so return action to caller */ + break; +#if XDND_VERSION < 3 + } +#endif + } else if (xevent.type == Expose) { + if (dnd->handle_expose_events) + (*dnd->handle_expose_events) (dnd, &xevent); + } else if (xevent.type == MotionNotify) { + if (xevent.xmotion.time > time + (dnd->time_out ? dnd->time_out * 1000 : 10000)) { /* allow a ten second timeout as default */ + dnd_debug1 ("timeout - exiting event loop"); + break; + } + } else if (xevent.type == SelectionRequest && xevent.xselectionrequest.selection == dnd->XdndSelection) { +/* the target widget is going to request data, so check for SelectionRequest events */ + int length = 0; + unsigned char *data = 0; + + dnd_debug1 ("SelectionRequest - getting widget data"); + (*dnd->widget_get_data) (dnd, from, &data, &length, xevent.xselectionrequest.target); + if (data) { + dnd_debug1 (" sending selection"); + xdnd_selection_send (dnd, &xevent.xselectionrequest, data, length); + xdnd_xfree (data); + } +/* don't wait for a XdndFinished event */ + if (!dnd_version_at_least (dnd->dragging_version, 2)) + break; + } + } + } else { + dnd_debug1 ("not ready_to_drop - ungrabbing pointer"); + } + XUngrabPointer (dnd->display, CurrentTime); + xdnd_reset (dnd); + return result; +} + +/* returns non-zero if event is handled */ +int xdnd_handle_drop_events (DndClass * dnd, XEvent * xevent) +{ + int result = 0; + if (xevent->type == SelectionNotify) { + dnd_debug1 ("got SelectionNotify"); + if (xevent->xselection.property == dnd->Xdnd_NON_PROTOCOL_ATOM && dnd->stage == XDND_DROP_STAGE_CONVERTING) { + int error; + dnd_debug1 (" property is Xdnd_NON_PROTOCOL_ATOM - getting selection"); + error = xdnd_get_selection (dnd, dnd->dragger_window, xevent->xselection.property, xevent->xany.window); +/* error is not actually used, i think future versions of the protocol maybe should return + an error status to the calling window with the XdndFinished client message */ + if (dnd_version_at_least (dnd->dragging_version, 2)) { +#if XDND_VERSION >= 3 + xdnd_send_finished (dnd, dnd->dragger_window, dnd->dropper_toplevel, error); +#else + xdnd_send_finished (dnd, dnd->dragger_window, dnd->dropper_window, error); +#endif + dnd_debug1 (" sending finished"); + } + xdnd_xfree (dnd->dragger_typelist); + xdnd_reset (dnd); + dnd->stage = XDND_DROP_STAGE_IDLE; + result = 1; + } else { + dnd_debug1 (" property is not Xdnd_NON_PROTOCOL_ATOM - ignoring"); + } + } else if (xevent->type == ClientMessage) { + dnd_debug2 ("got ClientMessage to xevent->xany.window = %ld", xevent->xany.window); + if (xevent->xclient.message_type == dnd->XdndEnter) { + dnd_debug2 (" message_type is XdndEnter, version = %ld", XDND_ENTER_VERSION (xevent)); +#if XDND_VERSION >= 3 + if (XDND_ENTER_VERSION (xevent) < 3) + return 0; +#endif + xdnd_reset (dnd); + dnd->dragger_window = XDND_ENTER_SOURCE_WIN (xevent); +#if XDND_VERSION >= 3 + dnd->dropper_toplevel = xevent->xany.window; + dnd->dropper_window = 0; /* enter goes to the top level window only, + so we don't really know what the + sub window is yet */ +#else + dnd->dropper_window = xevent->xany.window; +#endif + xdnd_xfree (dnd->dragger_typelist); + if (XDND_ENTER_THREE_TYPES (xevent)) { + dnd_debug1 (" three types only"); + xdnd_get_three_types (dnd, xevent, &dnd->dragger_typelist); + } else { + dnd_debug1 (" more than three types - getting list"); + xdnd_get_type_list (dnd, dnd->dragger_window, &dnd->dragger_typelist); + } + if (dnd->dragger_typelist) + dnd->stage = XDND_DROP_STAGE_ENTERED; + else + dnd_debug1 (" typelist returned as zero!"); + dnd->dragging_version = XDND_ENTER_VERSION (xevent); + result = 1; + } else if (xevent->xclient.message_type == dnd->XdndLeave) { +#if XDND_VERSION >= 3 + if (xevent->xany.window == dnd->dropper_toplevel && dnd->dropper_window) + xevent->xany.window = dnd->dropper_window; +#endif + dnd_debug1 (" message_type is XdndLeave"); + if (dnd->dragger_window == XDND_LEAVE_SOURCE_WIN (xevent) && dnd->stage == XDND_DROP_STAGE_ENTERED) { + dnd_debug1 (" leaving"); + if (dnd->widget_apply_leave) + (*dnd->widget_apply_leave) (dnd, xevent->xany.window); + dnd->stage = XDND_DROP_STAGE_IDLE; + xdnd_xfree (dnd->dragger_typelist); + result = 1; + dnd->dropper_toplevel = dnd->dropper_window = 0; + } else { + dnd_debug1 (" wrong stage or from wrong window"); + } + } else if (xevent->xclient.message_type == dnd->XdndPosition) { + dnd_debug2 (" message_type is XdndPosition to %ld", xevent->xany.window); + if (dnd->dragger_window == XDND_POSITION_SOURCE_WIN (xevent) && dnd->stage == XDND_DROP_STAGE_ENTERED) { + int want_position; + Atom action; + XRectangle rectangle; + Window last_window; + last_window = dnd->dropper_window; +#if XDND_VERSION >= 3 +/* version 3 gives us the top-level window only. WE have to find the child that the pointer is over: */ + if (1 || xevent->xany.window != dnd->dropper_toplevel || !dnd->dropper_window) { + Window parent, child, new_child = 0; + dnd->dropper_toplevel = xevent->xany.window; + parent = dnd->root_window; + child = dnd->dropper_toplevel; + for (;;) { + int xd, yd; + new_child = 0; + if (!XTranslateCoordinates (dnd->display, parent, child, + XDND_POSITION_ROOT_X (xevent), XDND_POSITION_ROOT_Y (xevent), + &xd, &yd, &new_child)) + break; + if (!new_child) + break; + child = new_child; + } + dnd->dropper_window = xevent->xany.window = child; + dnd_debug2 (" child window translates to %ld", dnd->dropper_window); + } else if (xevent->xany.window == dnd->dropper_toplevel && dnd->dropper_window) { + xevent->xany.window = dnd->dropper_window; + dnd_debug2 (" child window previously found: %ld", dnd->dropper_window); + } +#endif + action = dnd->XdndActionCopy; + dnd->supported_action = dnd->XdndActionCopy; + dnd->x = XDND_POSITION_ROOT_X (xevent); + dnd->y = XDND_POSITION_ROOT_Y (xevent); + dnd->time = CurrentTime; + if (dnd_version_at_least (dnd->dragging_version, 1)) + dnd->time = XDND_POSITION_TIME (xevent); + if (dnd_version_at_least (dnd->dragging_version, 1)) + action = XDND_POSITION_ACTION (xevent); +#if XDND_VERSION >= 3 + if (last_window && last_window != xevent->xany.window) + if (dnd->widget_apply_leave) + (*dnd->widget_apply_leave) (dnd, last_window); +#endif + dnd->will_accept = (*dnd->widget_apply_position) (dnd, xevent->xany.window, dnd->dragger_window, + action, dnd->x, dnd->y, dnd->time, dnd->dragger_typelist, + &want_position, &dnd->supported_action, &dnd->desired_type, &rectangle); + dnd_debug2 (" will accept = %d", dnd->will_accept); +#if XDND_VERSION >= 3 + dnd_debug2 (" sending status of %ld", dnd->dropper_toplevel); + xdnd_send_status (dnd, dnd->dragger_window, dnd->dropper_toplevel, dnd->will_accept, + want_position, rectangle.x, rectangle.y, rectangle.width, rectangle.height, dnd->supported_action); +#else + dnd_debug2 (" sending status of %ld", xevent->xany.window); + xdnd_send_status (dnd, dnd->dragger_window, xevent->xany.window, dnd->will_accept, + want_position, rectangle.x, rectangle.y, rectangle.width, rectangle.height, dnd->supported_action); +#endif + result = 1; + } else { + dnd_debug1 (" wrong stage or from wrong window"); + } + } else if (xevent->xclient.message_type == dnd->XdndDrop) { +#if XDND_VERSION >= 3 + if (xevent->xany.window == dnd->dropper_toplevel && dnd->dropper_window) + xevent->xany.window = dnd->dropper_window; +#endif + dnd_debug1 (" message_type is XdndDrop"); + if (dnd->dragger_window == XDND_DROP_SOURCE_WIN (xevent) && dnd->stage == XDND_DROP_STAGE_ENTERED) { + dnd->time = CurrentTime; + if (dnd_version_at_least (dnd->dragging_version, 1)) + dnd->time = XDND_DROP_TIME (xevent); + if (dnd->will_accept) { + dnd_debug1 (" will_accept is true - converting selectiong"); + dnd_debug2 (" my window is %ld", dnd->dropper_window); + dnd_debug2 (" source window is %ld", dnd->dragger_window); + xdnd_convert_selection (dnd, dnd->dragger_window, dnd->dropper_window, dnd->desired_type); + dnd->stage = XDND_DROP_STAGE_CONVERTING; + } else { + dnd_debug1 (" will_accept is false - sending finished"); + if (dnd_version_at_least (dnd->dragging_version, 2)) { +#if XDND_VERSION >= 3 + xdnd_send_finished (dnd, dnd->dragger_window, dnd->dropper_toplevel, 1); +#else + xdnd_send_finished (dnd, dnd->dragger_window, xevent->xany.window, 1); +#endif + } + xdnd_xfree (dnd->dragger_typelist); + xdnd_reset (dnd); + dnd->stage = XDND_DROP_STAGE_IDLE; + } + result = 1; + } else { + dnd_debug1 (" wrong stage or from wrong window"); + } + } + } + return result; +} + +/* + Following here is a sample implementation: Suppose we want a window + to recieve drops, but do not want to be concerned with setting up all + the DndClass methods. All we then do is call xdnd_get_drop() whenever a + ClientMessage is recieved. If the message has nothing to do with XDND, + xdnd_get_drop quickly returns 0. If it is a XdndEnter message, then + xdnd_get_drop enters its own XNextEvent loop and handles all XDND + protocol messages internally, returning the action requested. + + You should pass a desired typelist and actionlist to xdnd_get_type. + These must be null terminated arrays of atoms, or a null pointer + if you would like any action or type to be accepted. If typelist + is null then the first type of the dragging widgets typelist will + be the one used. If actionlist is null, then only XdndActionCopy will + be accepted. + + The result is stored in *data, length, type, x and y. + *data must be free'd. + */ + +struct xdnd_get_drop_info { + unsigned char *drop_data; + int drop_data_length; + int x, y; + Atom return_type; + Atom return_action; + Atom *typelist; + Atom *actionlist; +}; + +static int widget_insert_drop (DndClass * dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type) +{ + struct xdnd_get_drop_info *i; + i = (struct xdnd_get_drop_info *) dnd->user_hook1; + if (!i->drop_data) { + i->drop_data = malloc (length); + if (!i->drop_data) + return 1; + memcpy (i->drop_data, data, length); + i->drop_data_length = length; + } else { + unsigned char *t; + t = malloc (i->drop_data_length + length); + if (!t) { + free (i->drop_data); + i->drop_data = 0; + return 1; + } + memcpy (t, i->drop_data, i->drop_data_length); + memcpy (t + i->drop_data_length, data, length); + free (i->drop_data); + i->drop_data = t; + i->drop_data_length += length; + } + return 0; +} + +static int widget_apply_position (DndClass * dnd, Window widgets_window, Window from, + Atom action, int x, int y, Time t, Atom * typelist, + int *want_position, Atom * supported_action_return, Atom * desired_type, + XRectangle * rectangle) +{ + int i, j; + struct xdnd_get_drop_info *info; + Atom *dropper_typelist, supported_type = 0; + Atom *supported_actions, supported_action = 0; + + info = (struct xdnd_get_drop_info *) dnd->user_hook1; + dropper_typelist = info->typelist; + supported_actions = info->actionlist; + + if (dropper_typelist) { +/* find a correlation: */ + for (j = 0; dropper_typelist[j]; j++) { + for (i = 0; typelist[i]; i++) { + if (typelist[i] == dropper_typelist[j]) { + supported_type = typelist[i]; + break; + } + } + if (supported_type) + break; + } + } else { +/* user did not specify, so return first type */ + supported_type = typelist[0]; + } +/* not supported, so return false */ + if (!supported_type) + return 0; + + if (supported_actions) { + for (j = 0; supported_actions[j]; j++) { + if (action == supported_actions[j]) { + supported_action = action; + break; + } + } + } else { +/* user did not specify */ + if (action == dnd->XdndActionCopy) + supported_action = action; + } + if (!supported_action) + return 0; + + *want_position = 1; + rectangle->x = rectangle->y = 0; + rectangle->width = rectangle->height = 0; + + info->return_action = *supported_action_return = supported_action; + info->return_type = *desired_type = supported_type; + info->x = x; + info->y = y; + + return 1; +} + +Atom xdnd_get_drop (Display * display, XEvent * xevent, Atom * typelist, Atom * actionlist, + unsigned char **data, int *length, Atom * type, int *x, int *y) +{ + Atom action = 0; + static int initialised = 0; + static DndClass dnd; + if (!initialised) { + xdnd_init (&dnd, display); + initialised = 1; + } + if (xevent->type != ClientMessage || xevent->xclient.message_type != dnd.XdndEnter) { + return 0; + } else { + struct xdnd_get_drop_info i; + +/* setup user structure */ + memset (&i, 0, sizeof (i)); + i.actionlist = actionlist; + i.typelist = typelist; + dnd.user_hook1 = &i; + +/* setup methods */ + dnd.widget_insert_drop = widget_insert_drop; + dnd.widget_apply_position = widget_apply_position; + +/* main loop */ + for (;;) { + xdnd_handle_drop_events (&dnd, xevent); + if (dnd.stage == XDND_DROP_STAGE_IDLE) + break; + XNextEvent (dnd.display, xevent); + } + +/* return results */ + if (i.drop_data) { + *length = i.drop_data_length; + *data = i.drop_data; + action = i.return_action; + *type = i.return_type; + *x = i.x; + *y = i.y; + } + } + return action; +} + + diff --git a/extern/xdnd/xdnd.h b/extern/xdnd/xdnd.h new file mode 100644 index 00000000000..c903b51c8d0 --- /dev/null +++ b/extern/xdnd/xdnd.h @@ -0,0 +1,221 @@ +/* xdnd.c, xdnd.h - C program library for handling the Xdnd protocol + Copyright (C) 1996-2000 Paul Sheer + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + */ + +#ifndef _X_DND_H +#define _X_DND_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* you can set this to either 2 (which support 0 and 1 as well) or 3 */ +/* #define XDND_VERSION 2 */ +#define XDND_VERSION 3 + + +/* XdndEnter */ +#define XDND_THREE 3 +#define XDND_ENTER_SOURCE_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_ENTER_THREE_TYPES(e) (((e)->xclient.data.l[1] & 0x1UL) == 0) +#define XDND_ENTER_THREE_TYPES_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL) +#define XDND_ENTER_VERSION(e) ((e)->xclient.data.l[1] >> 24) +#define XDND_ENTER_VERSION_SET(e,v) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~(0xFF << 24)) | ((v) << 24) +#define XDND_ENTER_TYPE(e,i) ((e)->xclient.data.l[2 + i]) /* i => (0, 1, 2) */ + +/* XdndPosition */ +#define XDND_POSITION_SOURCE_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_POSITION_ROOT_X(e) ((e)->xclient.data.l[2] >> 16) +#define XDND_POSITION_ROOT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFUL) +#define XDND_POSITION_ROOT_SET(e,x,y) (e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL) +#define XDND_POSITION_TIME(e) ((e)->xclient.data.l[3]) +#define XDND_POSITION_ACTION(e) ((e)->xclient.data.l[4]) + +/* XdndStatus */ +#define XDND_STATUS_TARGET_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_STATUS_WILL_ACCEPT(e) ((e)->xclient.data.l[1] & 0x1L) +#define XDND_STATUS_WILL_ACCEPT_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x1UL) | (((b) == 0) ? 0 : 0x1UL) +#define XDND_STATUS_WANT_POSITION(e) ((e)->xclient.data.l[1] & 0x2UL) +#define XDND_STATUS_WANT_POSITION_SET(e,b) (e)->xclient.data.l[1] = ((e)->xclient.data.l[1] & ~0x2UL) | (((b) == 0) ? 0 : 0x2UL) +#define XDND_STATUS_RECT_X(e) ((e)->xclient.data.l[2] >> 16) +#define XDND_STATUS_RECT_Y(e) ((e)->xclient.data.l[2] & 0xFFFFL) +#define XDND_STATUS_RECT_WIDTH(e) ((e)->xclient.data.l[3] >> 16) +#define XDND_STATUS_RECT_HEIGHT(e) ((e)->xclient.data.l[3] & 0xFFFFL) +#define XDND_STATUS_RECT_SET(e,x,y,w,h) {(e)->xclient.data.l[2] = ((x) << 16) | ((y) & 0xFFFFUL); (e)->xclient.data.l[3] = ((w) << 16) | ((h) & 0xFFFFUL); } +#define XDND_STATUS_ACTION(e) ((e)->xclient.data.l[4]) + +/* XdndLeave */ +#define XDND_LEAVE_SOURCE_WIN(e) ((e)->xclient.data.l[0]) + +/* XdndDrop */ +#define XDND_DROP_SOURCE_WIN(e) ((e)->xclient.data.l[0]) +#define XDND_DROP_TIME(e) ((e)->xclient.data.l[2]) + +/* XdndFinished */ +#define XDND_FINISHED_TARGET_WIN(e) ((e)->xclient.data.l[0]) + +struct _DndCursor { + int width, height; + int x, y; + unsigned char *image_data, *mask_data; + char *_action; + Pixmap image_pixmap, mask_pixmap; + Cursor cursor; + Atom action; +}; + +typedef struct _DndCursor DndCursor; +typedef struct _DndClass DndClass; + +struct _DndClass { +/* insert chars sequentionally into the target widget, type will be the same as `desired_type' + returned from widget_apply_position. This may be called several times in succession + with sequention blocks of data. Must return non-zero on failure */ + int (*widget_insert_drop) (DndClass * dnd, unsigned char *data, int length, int remaining, Window into, Window from, Atom type); + +/* In response to DELETE requests : FIXME - not yet used */ + int (*widget_delete_selection) (DndClass * dnd, Window window, Window from); + +/* returns 1 if widget exists, zero otherwise. If this method is not + set then the code assumes that no widgets have support for recieving drops. + In this case none of the widget methods need be set. */ + int (*widget_exists) (DndClass * dnd, Window window); + +/* must update the widgets border to its default appearance */ + void (*widget_apply_leave) (DndClass * dnd, Window widgets_window); + +/* must update the widgets border to give the appearance of being able to recieve a drop, + plus return all data to pointers. As per the protocol, if the widget cannot + perform the action specified by `action' then it should return either XdndActionPrivate + or XdndActionCopy into supported_action (leaving 0 supported_action unchanged is equivalent + to XdndActionCopy). Returns 1 if ready to ok drop */ + int (*widget_apply_position) (DndClass * dnd, Window widgets_window, Window from, + Atom action, int x, int y, Time t, Atom * typelist, + int *want_position, Atom * supported_action, Atom * desired_type, + XRectangle * rectangle); + +/* returns drag data of the specified type. This will be one of `typelist' given to xdnd_drag */ + void (*widget_get_data) (DndClass * dnd, Window window, unsigned char **data, int *length, Atom type); + +/* this is called from with the main event loop if an expose event is recieved and is optional */ + void (*handle_expose_events) (DndClass * dnd, XEvent * xevent); + +/* creates a chooser dialog if the action is XdndActionAsk. Returns non-zero on cancel */ + int (*action_choose_dialog) (DndClass * dnd, char **descriptions, Atom * actions, Atom * result); + +#if 0 /* implemented internally */ +/* returns a widget that is dnd aware within a parent widget that lies under the point x, y */ + Window (*widget_get_child_widget) (DndClass * dnd, Window parent, int x, int y); +#endif + + void *pad1[8]; + + DndCursor *cursors; + + Display *display; + + Atom XdndAware; + Atom XdndSelection; + Atom XdndEnter; + Atom XdndLeave; + Atom XdndPosition; + Atom XdndDrop; + Atom XdndFinished; + Atom XdndStatus; + Atom XdndActionCopy; + Atom XdndActionMove; + Atom XdndActionLink; + Atom XdndActionAsk; + Atom XdndActionPrivate; + Atom XdndTypeList; + Atom XdndActionList; + Atom XdndActionDescription; + + Atom Xdnd_NON_PROTOCOL_ATOM; + Atom version; + + Atom pad2[16]; + + Window root_window; + +#define XDND_DROP_STAGE_IDLE 0 +#define XDND_DRAG_STAGE_DRAGGING 1 +#define XDND_DRAG_STAGE_ENTERED 2 +#define XDND_DROP_STAGE_CONVERTING 3 +#define XDND_DROP_STAGE_ENTERED 4 + int stage; + int dragging_version; + int internal_drag; + int want_position; + int ready_to_drop; + int will_accept; + XRectangle rectangle; + Window dropper_window, dragger_window; + Atom *dragger_typelist; + Atom desired_type; + Atom supported_action; + Time time; +/* drop position from last XdndPosition */ + int x, y; + int pad3[16]; + +/* move euclidian pixels before considering this to be an actual drag */ + float drag_threshold; + +/* block for only this many seconds on not receiving a XdndFinished from target, default : 10 */ + int time_out; + +#define XDND_OPTION_NO_HYSTERESIS (1<<0) + int options; + +/* user hooks */ + void *user_hook1; + void *user_hook2; + void *user_hook3; + Window dropper_toplevel; + void *pad4[15]; +}; + + +void xdnd_init (DndClass * dnd, Display * display); +void xdnd_shut (DndClass * dnd); +/* for nested widgets where parent and child receive drops of different +types; then always pass typelist as null */ +void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist); +int xdnd_is_dnd_aware (DndClass * dnd, Window window, int *version, Atom * typelist); +void xdnd_set_type_list (DndClass * dnd, Window window, Atom * typelist); +void xdnd_set_actions (DndClass * dnd, Window window, Atom * actions, char **descriptions); +int xdnd_get_actions (DndClass * dnd, Window window, Atom ** actions, char ***descriptions); +int xdnd_choose_action_dialog (DndClass * dnd, Atom * actions, char **descriptions, Atom * result); +Atom xdnd_drag (DndClass * dnd, Window from, Atom action, Atom * typelist); + +/* Returns 1 if event is handled, This must be placed in the widget +libraries main event loop and be called if the event type is +ClientMessage or SelectionNotify */ +int xdnd_handle_drop_events (DndClass * dnd, XEvent * xevent); +Atom xdnd_get_drop (Display * display, XEvent * xevent, Atom * typelist, Atom * actionlist, + unsigned char **data, int *length, Atom * type, int *x, int *y); + + +#ifdef __cplusplus +} +#endif + +#endif /* !_X_DND_H */ + + |