Merge lp:~dandrader/geis/lp1045785 into lp:geis

Proposed by Daniel d'Andrada
Status: Merged
Merged at revision: 283
Proposed branch: lp:~dandrader/geis/lp1045785
Merge into: lp:geis
Diff against target: 1186 lines (+617/-177)
16 files modified
libgeis/backend/dbus/geis_dbus_backend.c (+6/-0)
libgeis/backend/grail/geis_grail_backend.c (+263/-132)
libgeis/backend/grail/geis_grail_backend.h (+7/-0)
libgeis/backend/grail/geis_grail_token.c (+10/-0)
libgeis/backend/grail/geis_ugsubscription_store.c (+50/-37)
libgeis/backend/grail/geis_ugsubscription_store.h (+22/-4)
libgeis/backend/test_fixture/geis_backend_test_fixture.c (+7/-0)
libgeis/geis_backend_protected.h (+1/-0)
libgeis/geis_backend_token.c (+9/-1)
libgeis/geis_backend_token.h (+11/-0)
libgeis/geis_subscription.c (+15/-2)
testsuite/geis2/Makefile.am (+1/-0)
testsuite/geis2/gtest_gbe_configure_new_devices.cpp (+201/-0)
testsuite/geis2/gtest_grail_backend.cpp (+3/-0)
testsuite/geis2/gtest_grail_backend.h (+3/-1)
testsuite/x11_mocks/x11_mocks.c (+8/-0)
To merge this branch: bzr merge lp:~dandrader/geis/lp1045785
Reviewer Review Type Date Requested Status
Chase Douglas (community) Approve
Review via email: mp+122898@code.launchpad.net

Description of the change

Fixes bug 1045785.

Improved handling of gesture configuration options for GeisSubscriptions

- You can now call geis_subscription_set_configuration() independently of whether the subscription is active or not. Before that, setting configuration options on an inactive subscription would fail.

- configuration options remain valid for devices that become available *after* the subscription is configured.

Also a number of memory leaks were plugged along the way.

To post a comment you must log in.
Revision history for this message
Chase Douglas (chasedouglas) wrote :

* It doesn't make much sense to include the current actual outcome in the test description because it will no longer be the actual outcome after the branch is merged :). The test could also fail in other ways in the future.

* Typo in a test comment: "Set a huge threshold (in meters) so that there's no *change* a drag can be"

Everything else looks good to me! This is a great improvement over the current functionality :).

review: Approve
lp:~dandrader/geis/lp1045785 updated
289. By Daniel d'Andrada

Fix comments in tests

* Remove the "actual outcome" from the test description. It doesn't make sense
to have it there and it's also no longer the actual outcome.

* Correct comment on the drag threshold

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libgeis/backend/dbus/geis_dbus_backend.c'
--- libgeis/backend/dbus/geis_dbus_backend.c 2012-07-24 16:04:12 +0000
+++ libgeis/backend/dbus/geis_dbus_backend.c 2012-09-05 18:11:18 +0000
@@ -156,6 +156,11 @@
156 return GEIS_STATUS_UNKNOWN_ERROR;156 return GEIS_STATUS_UNKNOWN_ERROR;
157}157}
158158
159static void
160_geis_dbus_token_free_subscription_pdata(GeisBackendToken token GEIS_UNUSED,
161 GeisSubscription subscription GEIS_UNUSED)
162{
163}
159164
160static struct GeisBackendTokenVtable _token_vtbl = {165static struct GeisBackendTokenVtable _token_vtbl = {
161 _geis_dbus_token_clone,166 _geis_dbus_token_clone,
@@ -163,6 +168,7 @@
163 _geis_dbus_token_compose,168 _geis_dbus_token_compose,
164 _geis_dbus_token_activate,169 _geis_dbus_token_activate,
165 _geis_dbus_token_deactivate,170 _geis_dbus_token_deactivate,
171 _geis_dbus_token_free_subscription_pdata
166};172};
167173
168174
169175
=== modified file 'libgeis/backend/grail/geis_grail_backend.c'
--- libgeis/backend/grail/geis_grail_backend.c 2012-08-27 21:58:31 +0000
+++ libgeis/backend/grail/geis_grail_backend.c 2012-09-05 18:11:18 +0000
@@ -106,29 +106,27 @@
106 GeisBoolean send_synchronous_events;106 GeisBoolean send_synchronous_events;
107};107};
108108
109
110/**109/**
111 * A table of supported grail cofiguration properties and their GEIS110 Holds backend-specific information regarding a GeisSubscription
112 * equivalents.
113 */111 */
114static const struct GeisGrailConfigProperties112struct GeisGrailSubscriptionData
115{113{
116 GeisString geis_config_name;114 GeisUGSubscriptionStore ugstore;
117 GeisAttrType geis_value_type;115
118 UGSubscriptionProperty grail_property_name;116 /* configuration options
119} _grail_be_config_properties[] = {117 NULL if not set by user, in which case grail defaults are used */
120 { GEIS_CONFIG_DRAG_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyDragTimeout },118 uint64_t *drag_timeout;
121 { GEIS_CONFIG_DRAG_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyDragThreshold },119 float *drag_threshold;
122 { GEIS_CONFIG_PINCH_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyPinchTimeout },120 uint64_t *pinch_timeout;
123 { GEIS_CONFIG_PINCH_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyPinchThreshold },121 float *pinch_threshold;
124 { GEIS_CONFIG_ROTATE_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyRotateTimeout },122 uint64_t *rotate_timeout;
125 { GEIS_CONFIG_ROTATE_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyRotateThreshold },123 float *rotate_threshold;
126 { GEIS_CONFIG_TAP_TIMEOUT, GEIS_ATTR_TYPE_INTEGER, UGSubscriptionPropertyTapTimeout },124 uint64_t *tap_timeout;
127 { GEIS_CONFIG_TAP_THRESHOLD, GEIS_ATTR_TYPE_FLOAT, UGSubscriptionPropertyTapThreshold },125 float *tap_threshold;
128 { NULL, 0, 0 }
129};126};
130127
131128
129
132static GeisStatus130static GeisStatus
133_grail_be_activate_for_device(GeisGrailBackend gbe,131_grail_be_activate_for_device(GeisGrailBackend gbe,
134 GeisFilter filter,132 GeisFilter filter,
@@ -839,7 +837,8 @@
839 it != geis_subscription_bag_end(gbe->subscription_bag);837 it != geis_subscription_bag_end(gbe->subscription_bag);
840 it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it))838 it = geis_subscription_bag_iterator_next(gbe->subscription_bag, it))
841 {839 {
842 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(*it);840 struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(*it);
841 GeisUGSubscriptionStore ugstore = subscription_data->ugstore;
843 for (GeisFilterIterator fit = geis_subscription_filter_begin(*it);842 for (GeisFilterIterator fit = geis_subscription_filter_begin(*it);
844 fit != geis_subscription_filter_end(*it);843 fit != geis_subscription_filter_end(*it);
845 fit = geis_subscription_filter_next(*it, fit))844 fit = geis_subscription_filter_next(*it, fit))
@@ -1702,12 +1701,11 @@
1702 * subscriptions have the same property value setting.1701 * subscriptions have the same property value setting.
1703 */1702 */
1704static GeisStatus1703static GeisStatus
1705_grail_be_get_ugsub_property(GeisSubscription geis_subscription,1704_grail_be_get_ugsub_property(GeisUGSubscriptionStore ugstore,
1706 UGSubscriptionProperty grail_property,1705 UGSubscriptionProperty grail_property,
1707 GeisPointer grail_value)1706 GeisPointer grail_value)
1708{1707{
1709 GeisStatus retval = GEIS_STATUS_UNKNOWN_ERROR;1708 GeisStatus retval = GEIS_STATUS_UNKNOWN_ERROR;
1710 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(geis_subscription);
1711 if (ugstore)1709 if (ugstore)
1712 {1710 {
1713 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)1711 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
@@ -1731,29 +1729,65 @@
1731 * Sets a given grail property to a specified value.1729 * Sets a given grail property to a specified value.
1732 */1730 */
1733static GeisStatus1731static GeisStatus
1734_grail_be_set_ugsub_property(GeisSubscription geis_subscription,1732_grail_be_set_ugsub_property(GeisUGSubscriptionStore ugstore,
1735 UGSubscriptionProperty grail_property,1733 UGSubscriptionProperty grail_property,
1736 GeisPointer grail_value)1734 GeisPointer grail_value)
1737{1735{
1738 GeisStatus retval = GEIS_STATUS_UNKNOWN_ERROR;1736 /* OBS: it's still a success if there's no grail subscription */
1739 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(geis_subscription);1737 GeisStatus retval = GEIS_STATUS_SUCCESS;
1740 if (ugstore)1738 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
1741 {1739 {
1742 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)1740 UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore,
1743 {1741 i);
1744 UGSubscription ugsub = geis_ugsubscription_get_ugsubscription_at(ugstore,1742 if (UGStatusSuccess == grail_subscription_set_property(ugsub,
1745 i);1743 grail_property,
1746 if (UGStatusSuccess == grail_subscription_set_property(ugsub,1744 grail_value))
1747 grail_property,1745 {
1748 grail_value))1746 retval = GEIS_STATUS_SUCCESS;
1749 {1747 }
1750 retval = GEIS_STATUS_SUCCESS;1748 else
1751 }1749 {
1750 retval = GEIS_STATUS_UNKNOWN_ERROR;
1752 }1751 }
1753 }1752 }
1754 return retval;1753 return retval;
1755}1754}
17561755
1756static GeisStatus
1757_grail_be_get_integer_configuration(GeisUGSubscriptionStore ugstore,
1758 uint64_t *prop,
1759 UGSubscriptionProperty grail_prop,
1760 GeisPointer geis_value)
1761{
1762 if (prop)
1763 {
1764 *((GeisInteger*)geis_value) = *prop;
1765 return GEIS_STATUS_SUCCESS;
1766 }
1767 else
1768 {
1769 return _grail_be_get_ugsub_property(ugstore, grail_prop, geis_value);
1770 }
1771
1772}
1773
1774static GeisStatus
1775_grail_be_get_float_configuration(GeisUGSubscriptionStore ugstore,
1776 float *prop,
1777 UGSubscriptionProperty grail_prop,
1778 GeisPointer geis_value)
1779{
1780 if (prop)
1781 {
1782 *((GeisFloat*)geis_value) = *prop;
1783 return GEIS_STATUS_SUCCESS;
1784 }
1785 else
1786 {
1787 return _grail_be_get_ugsub_property(ugstore, grail_prop, geis_value);
1788 }
1789
1790}
17571791
1758/*1792/*
1759 * Dispatches the get-configuration call.1793 * Dispatches the get-configuration call.
@@ -1765,42 +1799,75 @@
1765 GeisPointer item_value)1799 GeisPointer item_value)
1766{1800{
1767 GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED;1801 GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED;
1768 for (int i = 0; _grail_be_config_properties[i].geis_config_name; ++i)1802
1803 struct GeisGrailSubscriptionData *subscription_data =
1804 geis_subscription_pdata(subscription);
1805 if (!subscription_data)
1769 {1806 {
1770 if (0 == strcmp(item_name, _grail_be_config_properties[i].geis_config_name))1807 return retval;
1771 {1808 }
1772 switch (_grail_be_config_properties[i].geis_value_type)1809
1773 {1810 #define GEIS_GRAIL_CHECK_GESTURE_CONFIG(gesture, Gesture, GESTURE) \
1774 case GEIS_ATTR_TYPE_INTEGER:1811 if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_TIMEOUT) == 0) \
1775 {1812 { \
1776 uint64_t value;1813 retval = _grail_be_get_integer_configuration( \
1777 retval = _grail_be_get_ugsub_property(subscription,1814 subscription_data->ugstore, \
1778 _grail_be_config_properties[i].grail_property_name,1815 subscription_data->gesture##_timeout, \
1779 &value);1816 UGSubscriptionProperty##Gesture##Timeout, \
1780 *(GeisInteger*)item_value = value;1817 item_value); \
1781 break;1818 } \
1782 }1819 else if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_THRESHOLD) == 0) \
1783 case GEIS_ATTR_TYPE_FLOAT:1820 { \
1784 {1821 retval = _grail_be_get_float_configuration( \
1785 float value;1822 subscription_data->ugstore, \
1786 retval = _grail_be_get_ugsub_property(subscription,1823 subscription_data->gesture##_threshold, \
1787 _grail_be_config_properties[i].grail_property_name,1824 UGSubscriptionProperty##Gesture##Threshold, \
1788 &value);1825 item_value); \
1789 *(GeisFloat*)item_value = value;1826 }
1790 break;1827
1791 }1828 GEIS_GRAIL_CHECK_GESTURE_CONFIG(drag, Drag, DRAG)
1792 default:1829 else GEIS_GRAIL_CHECK_GESTURE_CONFIG(pinch, Pinch, PINCH)
1793 geis_error("configuration value of unknown type requested");1830 else GEIS_GRAIL_CHECK_GESTURE_CONFIG(rotate, Rotate, ROTATE)
1794 retval = GEIS_STATUS_UNKNOWN_ERROR;1831 else GEIS_GRAIL_CHECK_GESTURE_CONFIG(tap, Tap, TAP)
1795 break;1832
1796 }1833 #undef GEIS_GRAIL_CHECK_GESTURE_CONFIG
1797 break;
1798 }
1799 }
18001834
1801 return retval;1835 return retval;
1802}1836}
18031837
1838static GeisStatus
1839_grail_be_set_integer_configuration(GeisUGSubscriptionStore ugstore,
1840 uint64_t **prop,
1841 UGSubscriptionProperty grail_prop,
1842 GeisPointer geis_value)
1843{
1844 if (!*prop)
1845 *prop = malloc(sizeof(uint64_t));
1846
1847 **prop = *((GeisInteger*)geis_value);
1848
1849 if (ugstore)
1850 return _grail_be_set_ugsub_property(ugstore, grail_prop, *prop);
1851 else
1852 return GEIS_STATUS_SUCCESS;
1853}
1854
1855static GeisStatus
1856_grail_be_set_float_configuration(GeisUGSubscriptionStore ugstore,
1857 float **prop,
1858 UGSubscriptionProperty grail_prop,
1859 GeisPointer geis_value)
1860{
1861 if (!*prop)
1862 *prop = malloc(sizeof(float));
1863
1864 **prop = *((GeisFloat*)geis_value);
1865
1866 if (ugstore)
1867 return _grail_be_set_ugsub_property(ugstore, grail_prop, *prop);
1868 else
1869 return GEIS_STATUS_SUCCESS;
1870}
18041871
1805/*1872/*
1806 * Dispatches the set-configuration call.1873 * Dispatches the set-configuration call.
@@ -1813,41 +1880,42 @@
1813{1880{
1814 GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED;1881 GeisStatus retval = GEIS_STATUS_NOT_SUPPORTED;
18151882
1816 for (int i = 0; _grail_be_config_properties[i].geis_config_name; ++i)1883 struct GeisGrailSubscriptionData *subscription_data =
1884 geis_subscription_pdata(subscription);
1885 if (!subscription_data)
1817 {1886 {
1818 if (0 == strcmp(item_name, _grail_be_config_properties[i].geis_config_name))1887 subscription_data = calloc(1, sizeof(struct GeisGrailSubscriptionData));
1819 {1888 geis_subscription_set_pdata(subscription, subscription_data);
1820 switch (_grail_be_config_properties[i].geis_value_type)1889 }
1821 {1890
1822 case GEIS_ATTR_TYPE_INTEGER:1891 #define GEIS_GRAIL_CHECK_GESTURE_CONFIG(gesture, Gesture, GESTURE) \
1823 {1892 if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_TIMEOUT) == 0) \
1824 uint64_t value = *(GeisInteger *)item_value;1893 { \
1825 retval = _grail_be_set_ugsub_property(subscription,1894 retval = _grail_be_set_integer_configuration( \
1826 _grail_be_config_properties[i].grail_property_name,1895 subscription_data->ugstore, \
1827 &value);1896 &(subscription_data->gesture##_timeout), \
1828 break;1897 UGSubscriptionProperty##Gesture##Timeout, \
1829 }1898 item_value); \
1830 case GEIS_ATTR_TYPE_FLOAT:1899 } \
1831 {1900 else if (strcmp(item_name, GEIS_CONFIG_##GESTURE##_THRESHOLD) == 0) \
1832 float value = *(GeisFloat *)item_value;1901 { \
1833 retval = _grail_be_set_ugsub_property(subscription,1902 retval = _grail_be_set_float_configuration( \
1834 _grail_be_config_properties[i].grail_property_name,1903 subscription_data->ugstore, \
1835 &value);1904 &(subscription_data->gesture##_threshold), \
1836 break;1905 UGSubscriptionProperty##Gesture##Threshold, \
1837 }1906 item_value); \
1838 default:1907 }
1839 geis_error("configuration value of unknown type requested");1908
1840 retval = GEIS_STATUS_UNKNOWN_ERROR;1909 GEIS_GRAIL_CHECK_GESTURE_CONFIG(drag, Drag, DRAG)
1841 break;1910 else GEIS_GRAIL_CHECK_GESTURE_CONFIG(pinch, Pinch, PINCH)
1842 }1911 else GEIS_GRAIL_CHECK_GESTURE_CONFIG(rotate, Rotate, ROTATE)
1843 break;1912 else GEIS_GRAIL_CHECK_GESTURE_CONFIG(tap, Tap, TAP)
1844 }1913
1845 }1914 #undef GEIS_GRAIL_CHECK_GESTURE_CONFIG
18461915
1847 return retval;1916 return retval;
1848}1917}
18491918
1850
1851static struct GeisBackendVtable gbe_vtbl = {1919static struct GeisBackendVtable gbe_vtbl = {
1852 _geis_grail_backend_construct,1920 _geis_grail_backend_construct,
1853 _geis_grail_backend_finalize,1921 _geis_grail_backend_finalize,
@@ -1855,10 +1923,9 @@
1855 _grail_be_accept_gesture,1923 _grail_be_accept_gesture,
1856 _grail_be_reject_gesture,1924 _grail_be_reject_gesture,
1857 _grail_be_get_configuration,1925 _grail_be_get_configuration,
1858 _grail_be_set_configuration,1926 _grail_be_set_configuration
1859};1927};
18601928
1861
1862static GeisStatus1929static GeisStatus
1863_geis_grail_filter_gestures(GeisGrailBackend gbe,1930_geis_grail_filter_gestures(GeisGrailBackend gbe,
1864 GeisFilter filter,1931 GeisFilter filter,
@@ -2029,6 +2096,45 @@
2029}2096}
20302097
20312098
2099static void
2100_geis_grail_set_ugsubscription_properties(GeisGrailBackend gbe,
2101 UGSubscription ugsub,
2102 GeisSubscription subscription)
2103{
2104 struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription);
2105
2106 GeisBoolean geis_use_atomic_gestures = GEIS_FALSE;
2107 geis_get_configuration(gbe->geis,
2108 GEIS_CONFIG_ATOMIC_GESTURES,
2109 &geis_use_atomic_gestures);
2110 int grail_use_atomic_gestures = (geis_use_atomic_gestures == GEIS_TRUE);
2111 grail_subscription_set_property(ugsub,
2112 UGSubscriptionPropertyAtomicGestures,
2113 &grail_use_atomic_gestures);
2114
2115
2116 #define GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(gesture, Gesture) \
2117 if (subscription_data->gesture##_timeout) \
2118 { \
2119 grail_subscription_set_property(ugsub, \
2120 UGSubscriptionProperty##Gesture##Timeout, \
2121 subscription_data->gesture##_timeout); \
2122 } \
2123 if (subscription_data->gesture##_threshold) \
2124 { \
2125 grail_subscription_set_property(ugsub, \
2126 UGSubscriptionProperty##Gesture##Threshold, \
2127 subscription_data->gesture##_threshold); \
2128 }
2129
2130 GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(drag, Drag);
2131 GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(pinch, Pinch);
2132 GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(rotate, Rotate);
2133 GEIS_GRAIL_SYNC_GESTURE_PROPERTIES(tap, Tap);
2134
2135 #undef GEIS_GRAIL_SYNC_GESTURE_PROPERTIES
2136}
2137
2032/**2138/**
2033 * Activates a subscription for a (device, region).2139 * Activates a subscription for a (device, region).
2034 */2140 */
@@ -2042,56 +2148,45 @@
2042 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;2148 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
2043 GeisInteger device_id = geis_device_id(device);2149 GeisInteger device_id = geis_device_id(device);
2044 UFDevice ufdevice = _grail_be_ufdevice_from_device_id(gbe, device_id);2150 UFDevice ufdevice = _grail_be_ufdevice_from_device_id(gbe, device_id);
2045 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);2151 struct GeisGrailSubscriptionData *subscription_data = geis_subscription_pdata(subscription);
2152 GeisUGSubscriptionStore ugstore = subscription_data->ugstore;
2046 UGSubscription ugsub = geis_ugsubscription_get_ugsubscription(ugstore,2153 UGSubscription ugsub = geis_ugsubscription_get_ugsubscription(ugstore,
2047 filter,2154 filter,
2048 ufdevice,2155 ufdevice,
2049 window_id);2156 window_id);
2157
2158 if (!ugsub)
2159 {
2160 ugsub = geis_ugsubscription_create_ugsubscription(ugstore,
2161 filter,
2162 ufdevice,
2163 window_id);
2164 _geis_grail_set_ugsubscription_properties(gbe, ugsub, subscription);
2165 }
2166
2050 if (!ugsub)2167 if (!ugsub)
2051 {2168 {
2052 geis_error("can not retrieve UGSubscription for (device, window)");2169 geis_error("can not retrieve UGSubscription for (device, window)");
2053 goto final_exit;2170 goto final_exit;
2054 }2171 }
20552172
2056 UGStatus ugstatus = UGStatusErrorGeneric;
2057 GeisBoolean geis_use_atomic_gestures = GEIS_FALSE;
2058 geis_get_configuration(gbe->geis,
2059 GEIS_CONFIG_ATOMIC_GESTURES,
2060 &geis_use_atomic_gestures);
2061 int grail_use_atomic_gestures = (geis_use_atomic_gestures == GEIS_TRUE);
2062 ugstatus = grail_subscription_set_property(ugsub,
2063 UGSubscriptionPropertyAtomicGestures,
2064 &grail_use_atomic_gestures);
2065
2066 status = _geis_grail_filter_gestures(gbe, filter, subscription, ugsub);2173 status = _geis_grail_filter_gestures(gbe, filter, subscription, ugsub);
20672174
2068 UGGestureTypeMask ugmask;
2069 ugstatus = grail_subscription_get_property(ugsub,
2070 UGSubscriptionPropertyMask,
2071 &ugmask);
2072 if (ugstatus != UGStatusSuccess)
2073 {
2074 geis_error("failed to get UGSubscription mask");
2075 goto final_exit;
2076 }
2077
2078 if (filter)2175 if (filter)
2079 geis_debug("subscription='%s' filter='%s' device=%d '%s' window=0x%08x "2176 geis_debug("subscription='%s' filter='%s' device=%d '%s' window=0x%08x "
2080 "ugsub=%p atomic=%d",2177 "ugsub=%p",
2081 geis_subscription_name(subscription),2178 geis_subscription_name(subscription),
2082 geis_filter_name(filter),2179 geis_filter_name(filter),
2083 device_id, geis_device_name(device),2180 device_id, geis_device_name(device),
2084 window_id,2181 window_id,
2085 (void *)ugsub,2182 (void *)ugsub);
2086 grail_use_atomic_gestures);
2087 else2183 else
2088 geis_debug("subscription='%s' no-filter device=%d '%s' window=0x%08x "2184 geis_debug("subscription='%s' no-filter device=%d '%s' window=0x%08x "
2089 "ugsub=%p atomic=%d",2185 "ugsub=%p",
2090 geis_subscription_name(subscription),2186 geis_subscription_name(subscription),
2091 device_id, geis_device_name(device),2187 device_id, geis_device_name(device),
2092 window_id,2188 window_id,
2093 (void *)ugsub,2189 (void *)ugsub);
2094 grail_use_atomic_gestures);
20952190
2096 status = geis_grail_window_grab_store_grab(gbe->window_grabs, window_id);2191 status = geis_grail_window_grab_store_grab(gbe->window_grabs, window_id);
2097 if (status != GEIS_STATUS_SUCCESS)2192 if (status != GEIS_STATUS_SUCCESS)
@@ -2100,7 +2195,7 @@
2100 goto final_exit;2195 goto final_exit;
2101 }2196 }
21022197
2103 ugstatus = grail_subscription_activate(gbe->grail, ugsub);2198 UGStatus ugstatus = grail_subscription_activate(gbe->grail, ugsub);
2104 if (ugstatus != UGStatusSuccess)2199 if (ugstatus != UGStatusSuccess)
2105 {2200 {
2106 status = GEIS_STATUS_UNKNOWN_ERROR;2201 status = GEIS_STATUS_UNKNOWN_ERROR;
@@ -2264,16 +2359,22 @@
2264 goto final_exit;2359 goto final_exit;
2265 }2360 }
22662361
2267 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);2362 struct GeisGrailSubscriptionData *subscription_data =
2268 if (ugstore == NULL)2363 geis_subscription_pdata(subscription);
2269 {2364 if (!subscription_data)
2270 ugstore = geis_ugsubscription_store_new();2365 {
2271 if (!ugstore)2366 subscription_data = calloc(1, sizeof(struct GeisGrailSubscriptionData));
2367 geis_subscription_set_pdata(subscription, subscription_data);
2368 }
2369
2370 if (subscription_data->ugstore == NULL)
2371 {
2372 subscription_data->ugstore = geis_ugsubscription_store_new();
2373 if (!subscription_data->ugstore)
2272 {2374 {
2273 geis_error("error creating grail subscription store");2375 geis_error("error creating grail subscription store");
2274 goto final_exit;2376 goto final_exit;
2275 }2377 }
2276 geis_subscription_set_pdata(subscription, ugstore);
2277 }2378 }
22782379
2279 if (geis_subscription_filter_count(subscription) > 0)2380 if (geis_subscription_filter_count(subscription) > 0)
@@ -2313,7 +2414,9 @@
2313 goto final_exit;2414 goto final_exit;
2314 }2415 }
23152416
2316 GeisUGSubscriptionStore ugstore = geis_subscription_pdata(subscription);2417 struct GeisGrailSubscriptionData *subscription_data =
2418 geis_subscription_pdata(subscription);
2419 GeisUGSubscriptionStore ugstore = subscription_data->ugstore;
2317 if (ugstore)2420 if (ugstore)
2318 {2421 {
2319 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)2422 for (GeisSize i = 0; i < geis_ugsubscription_count(ugstore); ++i)
@@ -2347,6 +2450,34 @@
2347 return status;2450 return status;
2348}2451}
23492452
2453/*
2454 Frees the memory allocated for the GEIS subscription private data
2455 */
2456void
2457geis_grail_backend_free_subscription_pdata(GeisGrailBackend gbe GEIS_UNUSED,
2458 GeisSubscription subscription)
2459{
2460 struct GeisGrailSubscriptionData *subscription_data =
2461 geis_subscription_pdata(subscription);
2462 if (!subscription_data)
2463 return;
2464
2465 if (subscription_data->ugstore)
2466 geis_ugsubscription_delete(subscription_data->ugstore);
2467
2468 free(subscription_data->drag_timeout);
2469 free(subscription_data->drag_threshold);
2470 free(subscription_data->pinch_timeout);
2471 free(subscription_data->pinch_threshold);
2472 free(subscription_data->rotate_timeout);
2473 free(subscription_data->rotate_threshold);
2474 free(subscription_data->tap_timeout);
2475 free(subscription_data->tap_threshold);
2476
2477 free(subscription_data);
2478
2479 geis_subscription_set_pdata(subscription, NULL);
2480}
23502481
2351/**2482/**
2352 * Registers the back end with the GEIS back end registry.2483 * Registers the back end with the GEIS back end registry.
23532484
=== modified file 'libgeis/backend/grail/geis_grail_backend.h'
--- libgeis/backend/grail/geis_grail_backend.h 2012-03-31 16:15:35 +0000
+++ libgeis/backend/grail/geis_grail_backend.h 2012-09-05 18:11:18 +0000
@@ -40,4 +40,11 @@
40geis_grail_backend_deactivate_subscription(GeisGrailBackend gbe,40geis_grail_backend_deactivate_subscription(GeisGrailBackend gbe,
41 GeisSubscription subscription);41 GeisSubscription subscription);
4242
43/**
44 * Frees the memory allocated for the GEIS subscription private data
45 */
46void
47geis_grail_backend_free_subscription_pdata(GeisGrailBackend gbe,
48 GeisSubscription subscription);
49
43#endif /* GEIS_BACKEND_GRAIL_BACKEND_H_ */50#endif /* GEIS_BACKEND_GRAIL_BACKEND_H_ */
4451
=== modified file 'libgeis/backend/grail/geis_grail_token.c'
--- libgeis/backend/grail/geis_grail_token.c 2012-03-31 16:15:35 +0000
+++ libgeis/backend/grail/geis_grail_token.c 2012-09-05 18:11:18 +0000
@@ -126,6 +126,15 @@
126 return status;126 return status;
127}127}
128128
129/**
130 * Frees the memory allocated for the GEIS subscription private data
131 */
132static void
133_geis_grail_token_free_subscription_pdata(GeisBackendToken token, GeisSubscription sub)
134{
135 GeisGrailToken gdt = _geis_grail_token_from_geis_token(token);
136 geis_grail_backend_free_subscription_pdata(gdt->be, sub);
137}
129138
130/**139/**
131 * Creates Grail-back-end-specific back end token.140 * Creates Grail-back-end-specific back end token.
@@ -140,6 +149,7 @@
140 _geis_grail_token_compose,149 _geis_grail_token_compose,
141 _geis_grail_token_activate,150 _geis_grail_token_activate,
142 _geis_grail_token_deactivate,151 _geis_grail_token_deactivate,
152 _geis_grail_token_free_subscription_pdata
143 };153 };
144154
145 GeisGrailToken token = _geis_grail_token_allocate();155 GeisGrailToken token = _geis_grail_token_allocate();
146156
=== modified file 'libgeis/backend/grail/geis_ugsubscription_store.c'
--- libgeis/backend/grail/geis_ugsubscription_store.c 2012-06-21 21:17:25 +0000
+++ libgeis/backend/grail/geis_ugsubscription_store.c 2012-09-05 18:11:18 +0000
@@ -59,7 +59,8 @@
59{59{
60 for (GeisSize i = 0; i < geis_bag_count(store); ++i)60 for (GeisSize i = 0; i < geis_bag_count(store); ++i)
61 {61 {
62 grail_subscription_delete(*(UGSubscription*)geis_bag_at(store, i));62 struct GeisUGSubscription * s = (struct GeisUGSubscription *)geis_bag_at(store, i);
63 grail_subscription_delete(s->ugsub);
63 }64 }
64 geis_bag_delete(store);65 geis_bag_delete(store);
65}66}
@@ -86,6 +87,53 @@
86 return ((GeisUGSubscription)geis_bag_at(store, index))->ugsub;87 return ((GeisUGSubscription)geis_bag_at(store, index))->ugsub;
87}88}
8889
90/*
91 * Creates a new UGSubscription and adds it to the store.
92 */
93UGSubscription
94geis_ugsubscription_create_ugsubscription(GeisUGSubscriptionStore store,
95 GeisFilter filter,
96 UFDevice device,
97 GeisInteger region_id)
98{
99 UGSubscription ugsub = NULL;
100
101 UGStatus ugstatus = grail_subscription_new(&ugsub);
102 if (ugstatus != UGStatusSuccess)
103 {
104 geis_error("failed to create grail subscription");
105 goto final_exit;
106 }
107
108 ugstatus = grail_subscription_set_property(ugsub,
109 UGSubscriptionPropertyDevice,
110 &device);
111 if (ugstatus != UGStatusSuccess)
112 {
113 geis_error("failed to set UGSubscription device property");
114 }
115
116 UFWindowId window_id = frame_x11_create_window_id(region_id);
117 ugstatus = grail_subscription_set_property(ugsub,
118 UGSubscriptionPropertyWindow,
119 &window_id);
120 if (ugstatus != UGStatusSuccess)
121 {
122 geis_error("failed to set UGSubscription window property");
123 }
124
125 struct GeisUGSubscription s = {
126 .filter = filter,
127 .device = device,
128 .region_id = region_id,
129 .ugsub = ugsub
130 };
131 geis_bag_append(store, &s);
132
133 final_exit:
134 return ugsub;
135}
136
89137
90/*138/*
91 * Gets a UGSubscription from the store.139 * Gets a UGSubscription from the store.
@@ -97,6 +145,7 @@
97 GeisInteger region_id)145 GeisInteger region_id)
98{146{
99 UGSubscription ugsub = NULL;147 UGSubscription ugsub = NULL;
148
100 for (GeisSize i = 0; i < geis_bag_count(store); ++i)149 for (GeisSize i = 0; i < geis_bag_count(store); ++i)
101 {150 {
102 GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i);151 GeisUGSubscription s = (GeisUGSubscription)geis_bag_at(store, i);
@@ -107,42 +156,6 @@
107 }156 }
108 }157 }
109158
110 if (!ugsub)
111 {
112 UGStatus ugstatus = grail_subscription_new(&ugsub);
113 if (ugstatus != UGStatusSuccess)
114 {
115 geis_error("failed to create grail subscription");
116 goto final_exit;
117 }
118
119 ugstatus = grail_subscription_set_property(ugsub,
120 UGSubscriptionPropertyDevice,
121 &device);
122 if (ugstatus != UGStatusSuccess)
123 {
124 geis_error("failed to set UGSubscription device property");
125 }
126
127 UFWindowId window_id = frame_x11_create_window_id(region_id);
128 ugstatus = grail_subscription_set_property(ugsub,
129 UGSubscriptionPropertyWindow,
130 &window_id);
131 if (ugstatus != UGStatusSuccess)
132 {
133 geis_error("failed to set UGSubscription window property");
134 }
135
136 struct GeisUGSubscription s = {
137 .filter = filter,
138 .device = device,
139 .region_id = region_id,
140 .ugsub = ugsub
141 };
142 geis_bag_append(store, &s);
143 }
144
145final_exit:
146 return ugsub;159 return ugsub;
147}160}
148161
149162
=== modified file 'libgeis/backend/grail/geis_ugsubscription_store.h'
--- libgeis/backend/grail/geis_ugsubscription_store.h 2012-06-21 21:17:25 +0000
+++ libgeis/backend/grail/geis_ugsubscription_store.h 2012-09-05 18:11:18 +0000
@@ -64,8 +64,7 @@
64 * @param[in] store The grail subscription store.64 * @param[in] store The grail subscription store.
65 * @param[in] index Indicates a ugsub.65 * @param[in] index Indicates a ugsub.
66 *66 *
67 * Gets a UGSubscription from the store for the identified device and region.67 * Gets a UGSubscription from the store at the given index.
68 * If no such UGSubscription is available, it creates one first.
69 *68 *
70 * @returns a valid UGSubscription or NULL to indicate failure.69 * @returns a valid UGSubscription or NULL to indicate failure.
71 */70 */
@@ -73,6 +72,27 @@
73geis_ugsubscription_get_ugsubscription_at(GeisUGSubscriptionStore store,72geis_ugsubscription_get_ugsubscription_at(GeisUGSubscriptionStore store,
74 GeisSize index);73 GeisSize index);
7574
75/*
76 * Creates a new UGSubscription and adds it to the store.
77 * @param[in] store The grail subscription store.
78 * @param[in] filter Identifies a filter.
79 * @param[in] device Identifies a device.
80 * @param[in] region_id Identifies a region.
81 *
82 * Creates a new UGSubscription for the identified filter, device,
83 * and region. It's added to the store. A separate grail subscription
84 * is required for each (filter, device, window) because filters on a
85 * geis subscription are ORed, meaning each filter may have a different
86 * minimum touch requirement.
87 *
88 * @returns a valid UGSubscription or NULL to indicate failure.
89 */
90UGSubscription
91geis_ugsubscription_create_ugsubscription(GeisUGSubscriptionStore store,
92 GeisFilter filter,
93 UFDevice device,
94 GeisInteger region_id);
95
76/**96/**
77 * Gets a UGSubscription from the store.97 * Gets a UGSubscription from the store.
78 * @param[in] store The grail subscription store.98 * @param[in] store The grail subscription store.
@@ -85,8 +105,6 @@
85 * device, window) because filters on a geis subscription are ORed, meaning each105 * device, window) because filters on a geis subscription are ORed, meaning each
86 * filter may have a different minimum touch requirement.106 * filter may have a different minimum touch requirement.
87 *107 *
88 * If no such UGSubscription is available, it creates one first.
89 *
90 * @returns a valid UGSubscription or NULL to indicate failure.108 * @returns a valid UGSubscription or NULL to indicate failure.
91 */109 */
92UGSubscription110UGSubscription
93111
=== modified file 'libgeis/backend/test_fixture/geis_backend_test_fixture.c'
--- libgeis/backend/test_fixture/geis_backend_test_fixture.c 2012-07-24 16:04:12 +0000
+++ libgeis/backend/test_fixture/geis_backend_test_fixture.c 2012-09-05 18:11:18 +0000
@@ -82,6 +82,7 @@
82static void _token_compose(GeisBackendToken, GeisBackendToken);82static void _token_compose(GeisBackendToken, GeisBackendToken);
83static GeisStatus _token_activate(GeisBackendToken, GeisSubscription);83static GeisStatus _token_activate(GeisBackendToken, GeisSubscription);
84static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription);84static GeisStatus _token_deactivate(GeisBackendToken, GeisSubscription);
85static void _token_free_subscription_pdata(GeisBackendToken, GeisSubscription);
8586
86static struct GeisBackendTokenVtable _token_vtbl = {87static struct GeisBackendTokenVtable _token_vtbl = {
87 _token_clone,88 _token_clone,
@@ -89,6 +90,7 @@
89 _token_compose,90 _token_compose,
90 _token_activate,91 _token_activate,
91 _token_deactivate,92 _token_deactivate,
93 _token_free_subscription_pdata
92};94};
9395
94static GeisGestureClass g_poke_class = NULL;96static GeisGestureClass g_poke_class = NULL;
@@ -424,6 +426,11 @@
424 return status;426 return status;
425}427}
426428
429void
430_token_free_subscription_pdata(GeisBackendToken gbtoken GEIS_UNUSED,
431 GeisSubscription subscription GEIS_UNUSED)
432{
433}
427434
428__attribute__((constructor))435__attribute__((constructor))
429static void _register_test_fixture()436static void _register_test_fixture()
430437
=== modified file 'libgeis/geis_backend_protected.h'
--- libgeis/geis_backend_protected.h 2012-04-17 23:43:04 +0000
+++ libgeis/geis_backend_protected.h 2012-09-05 18:11:18 +0000
@@ -58,6 +58,7 @@
58 void (* compose)(GeisBackendToken, GeisBackendToken);58 void (* compose)(GeisBackendToken, GeisBackendToken);
59 GeisStatus (* activate)(GeisBackendToken, GeisSubscription);59 GeisStatus (* activate)(GeisBackendToken, GeisSubscription);
60 GeisStatus (* deactivate)(GeisBackendToken, GeisSubscription);60 GeisStatus (* deactivate)(GeisBackendToken, GeisSubscription);
61 void (* free_subscription_pdata)(GeisBackendToken, GeisSubscription);
61} *GeisBackendTokenVtable;62} *GeisBackendTokenVtable;
6263
6364
6465
=== modified file 'libgeis/geis_backend_token.c'
--- libgeis/geis_backend_token.c 2011-10-17 16:52:22 +0000
+++ libgeis/geis_backend_token.c 2012-09-05 18:11:18 +0000
@@ -77,4 +77,12 @@
77 return token->vtbl->deactivate(token, subscription);77 return token->vtbl->deactivate(token, subscription);
78}78}
7979
8080/**
81 * Frees the private data that the backend allocated for a given subscription
82 */
83void
84geis_backend_token_free_subscription_pdata(GeisBackendToken token,
85 GeisSubscription subscription)
86{
87 token->vtbl->free_subscription_pdata(token, subscription);
88}
8189
=== modified file 'libgeis/geis_backend_token.h'
--- libgeis/geis_backend_token.h 2011-10-17 16:52:22 +0000
+++ libgeis/geis_backend_token.h 2012-09-05 18:11:18 +0000
@@ -101,4 +101,15 @@
101geis_backend_token_deactivate(GeisBackendToken token,101geis_backend_token_deactivate(GeisBackendToken token,
102 GeisSubscription subscription);102 GeisSubscription subscription);
103103
104/**
105 * Frees the private data that the backend allocated for a given subscription
106 *
107 * @param[in] token The backend token.
108 * @param[in] subscription The subscription that will have its backend private data
109 * freed
110 */
111void
112geis_backend_token_free_subscription_pdata(GeisBackendToken token,
113 GeisSubscription subscription);
114
104#endif /* GEIS_BACKEND_TOKEN_H_ */115#endif /* GEIS_BACKEND_TOKEN_H_ */
105116
=== modified file 'libgeis/geis_subscription.c'
--- libgeis/geis_subscription.c 2012-06-21 21:17:25 +0000
+++ libgeis/geis_subscription.c 2012-09-05 18:11:18 +0000
@@ -337,8 +337,6 @@
337 if (sub->sub_backend_token)337 if (sub->sub_backend_token)
338 {338 {
339 status = geis_backend_token_deactivate(sub->sub_backend_token, sub);339 status = geis_backend_token_deactivate(sub->sub_backend_token, sub);
340 geis_backend_token_delete(sub->sub_backend_token);
341 sub->sub_backend_token = NULL;
342 }340 }
343 return status;341 return status;
344}342}
@@ -426,6 +424,14 @@
426{424{
427 geis_debug("destroying subscription \"%s\" id %d", sub->sub_name, sub->sub_id);425 geis_debug("destroying subscription \"%s\" id %d", sub->sub_name, sub->sub_id);
428 geis_subscription_deactivate(sub);426 geis_subscription_deactivate(sub);
427
428 if (sub->sub_backend_token)
429 {
430 geis_backend_token_free_subscription_pdata(sub->sub_backend_token, sub);
431 geis_backend_token_delete(sub->sub_backend_token);
432 sub->sub_backend_token = NULL;
433 }
434
429 if (sub->sub_geis != NULL)435 if (sub->sub_geis != NULL)
430 {436 {
431 geis_unref(sub->sub_geis);437 geis_unref(sub->sub_geis);
@@ -507,6 +513,13 @@
507 geis_error("error adding filter to subscription");513 geis_error("error adding filter to subscription");
508 goto error_exit;514 goto error_exit;
509 }515 }
516 else
517 {
518 /* since we're taking ownership of the filter, we're removing the initial
519 reference that belonged to the API user, created in geis_filter_new().
520 Now the only remaining reference is the one held by our geis_filter_bag */
521 geis_filter_unref(filter);
522 }
510523
511error_exit:524error_exit:
512 return status;525 return status;
513526
=== modified file 'testsuite/geis2/Makefile.am'
--- testsuite/geis2/Makefile.am 2012-07-24 22:18:36 +0000
+++ testsuite/geis2/Makefile.am 2012-09-05 18:11:18 +0000
@@ -48,6 +48,7 @@
48gtest_geis2_grail_backend_SOURCES = \48gtest_geis2_grail_backend_SOURCES = \
49 gtest_grail_backend.h gtest_grail_backend.cpp \49 gtest_grail_backend.h gtest_grail_backend.cpp \
50 gtest_gbe_accept_ended_grail_gesture.cpp \50 gtest_gbe_accept_ended_grail_gesture.cpp \
51 gtest_gbe_configure_new_devices.cpp \
51 gtest_gbe_deactivate_sub.cpp \52 gtest_gbe_deactivate_sub.cpp \
52 gtest_gbe_direct_touch_coords.cpp \53 gtest_gbe_direct_touch_coords.cpp \
53 gtest_gbe_construction_finished.cpp \54 gtest_gbe_construction_finished.cpp \
5455
=== added file 'testsuite/geis2/gtest_gbe_configure_new_devices.cpp'
--- testsuite/geis2/gtest_gbe_configure_new_devices.cpp 1970-01-01 00:00:00 +0000
+++ testsuite/geis2/gtest_gbe_configure_new_devices.cpp 2012-09-05 18:11:18 +0000
@@ -0,0 +1,201 @@
1#include "gtest_grail_backend.h"
2#include "x11_mocks.h"
3
4/*
5 Regression test for bug LP#1045785
6 https://bugs.launchpad.net/geis/+bug/1045785
7
8 Steps to reproduce the issue:
9 1 - create a subscription, set some configuration options
10 (geis_subscription_set_configuration) and activate it.
11 2 - connect a new multitouch device to your computer (e.g. pair an Apple
12 Magic Trackpad)
13
14 Expected outcome:
15 Gestures from that new multitouch device follow the configurations set by
16 the subscription.
17 */
18
19class ConfigureNewDevice : public Geis2GrailBackendBase
20{
21 protected:
22 ConfigureNewDevice();
23
24 virtual void OnEventInitComplete(GeisEvent event);
25 virtual void OnEventClassAvailable(GeisEvent event);
26 virtual void OnEventGestureBegin(GeisEvent event);
27
28 void CreateSubscription();
29 void SendXInput2Events();
30
31 /* signals that a new device has been added */
32 void SendXIDeviceAddedEvent();
33
34 GeisSubscription _subscription;
35 GeisGestureClass _drag_class;
36};
37
38ConfigureNewDevice::ConfigureNewDevice()
39 : _subscription(nullptr),
40 _drag_class(nullptr)
41{
42}
43
44void ConfigureNewDevice::OnEventInitComplete(GeisEvent event)
45{
46 CreateSubscription();
47
48 /* The new device comes only after the subscription has been created and
49 configured */
50 CreateXMockTouchScreenDevice();
51 SendXIDeviceAddedEvent();
52
53 SendXInput2Events();
54}
55
56void ConfigureNewDevice::OnEventClassAvailable(GeisEvent event)
57{
58 GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_CLASS);
59 GeisGestureClass gesture_class =
60 reinterpret_cast<GeisGestureClass>(geis_attr_value_to_pointer(attr));
61
62 if (strcmp(geis_gesture_class_name(gesture_class), GEIS_GESTURE_DRAG) == 0)
63 {
64 _drag_class = gesture_class;
65 geis_gesture_class_ref(gesture_class);
66 }
67}
68
69void ConfigureNewDevice::OnEventGestureBegin(GeisEvent event)
70{
71 /* There should be no drag gesture since we set a huge drag threshold. */
72
73 GeisAttr attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
74 GeisGroupSet group_set =
75 reinterpret_cast<GeisGroupSet>(geis_attr_value_to_pointer(attr));
76 GeisGroup group = geis_groupset_group(group_set, 0);
77 GeisFrame frame = geis_group_frame(group, 0);
78
79 ASSERT_NE(nullptr, _drag_class);
80 GeisBoolean is_drag = geis_frame_is_class(frame, _drag_class);
81 ASSERT_FALSE(is_drag);
82}
83
84void ConfigureNewDevice::CreateSubscription()
85{
86 GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
87 GeisFilter filter = nullptr;
88
89 _subscription = geis_subscription_new(_geis, "2-fingers drag",
90 GEIS_SUBSCRIPTION_NONE);
91
92 filter = geis_filter_new(_geis, "filter");
93 ASSERT_NE(nullptr, filter);
94
95 status = geis_filter_add_term(filter,
96 GEIS_FILTER_CLASS,
97 GEIS_CLASS_ATTRIBUTE_NAME, GEIS_FILTER_OP_EQ, GEIS_GESTURE_DRAG,
98 GEIS_GESTURE_ATTRIBUTE_TOUCHES, GEIS_FILTER_OP_EQ, 2,
99 nullptr);
100 ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
101
102 status = geis_filter_add_term(filter,
103 GEIS_FILTER_REGION,
104 GEIS_REGION_ATTRIBUTE_WINDOWID, GEIS_FILTER_OP_EQ,
105 DefaultRootWindow(xmock_display),
106 nullptr);
107 ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
108
109 status = geis_subscription_add_filter(_subscription, filter);
110 ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
111
112 /* Set a huge threshold (in meters) so that no drag can be recognized */
113 GeisFloat drag_threshold = 1000.0f;
114 status = geis_subscription_set_configuration(_subscription,
115 GEIS_CONFIG_DRAG_THRESHOLD, &drag_threshold);
116 ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
117
118 status = geis_subscription_activate(_subscription);
119 ASSERT_EQ(GEIS_STATUS_SUCCESS, status);
120}
121
122void ConfigureNewDevice::SendXInput2Events()
123{
124 /* Emulate a simple 2 fingers drag */
125
126 /* event type, touch id, X and Y */
127 SendTouchEvent(XI_TouchBegin, 1, 10.0f, 10.0f);
128 SendTouchEvent(XI_TouchBegin, 2, 20.0f, 10.0f);
129
130 xmock_server_time += 2;
131
132 /* touch id */
133 SendTouchOwnershipEvent(1);
134 SendTouchOwnershipEvent(2);
135
136 xmock_server_time += 20;
137
138 SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 25.0f);
139 SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 25.0f);
140
141 xmock_server_time += 20;
142
143 SendTouchEvent(XI_TouchUpdate, 1, 10.0f, 35.0f);
144 SendTouchEvent(XI_TouchUpdate, 2, 20.0f, 35.0f);
145
146 xmock_server_time += 20;
147
148 SendTouchEvent(XI_TouchEnd, 1, 10.0f, 50.0f);
149 SendTouchEvent(XI_TouchEnd, 2, 20.0f, 50.0f);
150}
151
152void ConfigureNewDevice::SendXIDeviceAddedEvent()
153{
154 XEvent event;
155 XGenericEventCookie *xcookie = 0;
156 XIHierarchyEvent *hierarchy_event;
157 XIHierarchyInfo *info;
158
159 info = (XIHierarchyInfo*)calloc(1, sizeof(XIHierarchyInfo));
160 info->deviceid = xmock_devices[0].deviceid;
161 info->enabled = True;
162 info->flags = XISlaveAdded;
163
164 hierarchy_event = (XIHierarchyEvent*)calloc(1, sizeof(XIHierarchyEvent));
165 hierarchy_event->type = GenericEvent;
166 hierarchy_event->serial = _xevent_serial_number++;
167 hierarchy_event->display = xmock_display;
168 hierarchy_event->extension = xmock_xi2_opcode;
169 hierarchy_event->evtype = XI_HierarchyChanged;
170 hierarchy_event->time = xmock_server_time;
171 hierarchy_event->flags = XISlaveAdded;
172 hierarchy_event->num_info = 1;
173 hierarchy_event->info = info;
174
175 event.type = GenericEvent;
176 xcookie = &event.xcookie;
177 xcookie->extension = xmock_xi2_opcode;
178 xcookie->evtype = XI_HierarchyChanged;
179 xcookie->data = hierarchy_event;
180 xmock_add_to_event_queue(&event);
181}
182
183TEST_F(ConfigureNewDevice, Test)
184{
185 _geis = geis_new(GEIS_INIT_GRAIL_BACKEND,
186 GEIS_INIT_NO_ATOMIC_GESTURES,
187 nullptr);
188 ASSERT_NE(nullptr, _geis);
189
190 Run();
191
192 if (_subscription)
193 geis_subscription_delete(_subscription);
194
195 if (_drag_class)
196 geis_gesture_class_unref(_drag_class);
197
198 geis_delete(_geis);
199
200 DestroyXMockDevices();
201}
0202
=== modified file 'testsuite/geis2/gtest_grail_backend.cpp'
--- testsuite/geis2/gtest_grail_backend.cpp 2012-07-05 17:13:06 +0000
+++ testsuite/geis2/gtest_grail_backend.cpp 2012-09-05 18:11:18 +0000
@@ -168,6 +168,9 @@
168 case GEIS_EVENT_INIT_COMPLETE:168 case GEIS_EVENT_INIT_COMPLETE:
169 OnEventInitComplete(event);169 OnEventInitComplete(event);
170 break;170 break;
171 case GEIS_EVENT_CLASS_AVAILABLE:
172 OnEventClassAvailable(event);
173 break;
171 case GEIS_EVENT_GESTURE_BEGIN:174 case GEIS_EVENT_GESTURE_BEGIN:
172 OnEventGestureBegin(event);175 OnEventGestureBegin(event);
173 break;176 break;
174177
=== modified file 'testsuite/geis2/gtest_grail_backend.h'
--- testsuite/geis2/gtest_grail_backend.h 2012-07-05 17:13:06 +0000
+++ testsuite/geis2/gtest_grail_backend.h 2012-09-05 18:11:18 +0000
@@ -47,6 +47,7 @@
47 void DestroyXMockDevices();47 void DestroyXMockDevices();
4848
49 virtual void OnEventInitComplete(GeisEvent event) {}49 virtual void OnEventInitComplete(GeisEvent event) {}
50 virtual void OnEventClassAvailable(GeisEvent event) {}
50 virtual void OnEventGestureBegin(GeisEvent event) {}51 virtual void OnEventGestureBegin(GeisEvent event) {}
51 virtual void OnEventGestureUpdate(GeisEvent event) {}52 virtual void OnEventGestureUpdate(GeisEvent event) {}
52 virtual void OnEventGestureEnd(GeisEvent event) {}53 virtual void OnEventGestureEnd(GeisEvent event) {}
@@ -59,11 +60,12 @@
59 void GetGestureTimestampInEvent(GeisInteger *timestamp, GeisEvent event);60 void GetGestureTimestampInEvent(GeisInteger *timestamp, GeisEvent event);
6061
61 Geis _geis;62 Geis _geis;
62 private:
6363
64 /* holds the serial number to be used on the next synthetic XEvent */64 /* holds the serial number to be used on the next synthetic XEvent */
65 int _xevent_serial_number;65 int _xevent_serial_number;
6666
67 private:
68
67 bool DispatchAndProcessEvents();69 bool DispatchAndProcessEvents();
6870
69 void AcceptRejectGestureInEvent(GeisEvent event, bool accept);71 void AcceptRejectGestureInEvent(GeisEvent event, bool accept);
7072
=== modified file 'testsuite/x11_mocks/x11_mocks.c'
--- testsuite/x11_mocks/x11_mocks.c 2012-04-25 17:23:11 +0000
+++ testsuite/x11_mocks/x11_mocks.c 2012-09-05 18:11:18 +0000
@@ -194,6 +194,14 @@
194 free(device_event->valuators.mask);194 free(device_event->valuators.mask);
195 free(device_event->valuators.values);195 free(device_event->valuators.values);
196 }196 }
197 else if (cookie->evtype == XI_HierarchyChanged)
198 {
199 XIHierarchyEvent *hierarchy_event = (XIHierarchyEvent*) cookie->data;
200 for (int i = 0; i < hierarchy_event->num_info; ++i)
201 {
202 free(&(hierarchy_event->info[i]));
203 }
204 }
197 free(cookie->data);205 free(cookie->data);
198 }206 }
199}207}

Subscribers

People subscribed via source and target branches