diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 6 | ||||
-rw-r--r-- | src/ios.h | 1 | ||||
-rw-r--r-- | src/ios.m | 12 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 9 | ||||
-rw-r--r-- | src/ui/indicatorwidget.c | 1 | ||||
-rw-r--r-- | src/ui/sidebarwidget.c | 2 | ||||
-rw-r--r-- | src/ui/text.c | 2 | ||||
-rw-r--r-- | src/ui/touch.c | 278 | ||||
-rw-r--r-- | src/ui/touch.h | 29 | ||||
-rw-r--r-- | src/ui/widget.c | 3 | ||||
-rw-r--r-- | src/ui/widget.h | 1 | ||||
-rw-r--r-- | src/ui/window.c | 4 |
12 files changed, 343 insertions, 5 deletions
@@ -64,6 +64,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
64 | #if defined (iPlatformAppleDesktop) | 64 | #if defined (iPlatformAppleDesktop) |
65 | # include "macos.h" | 65 | # include "macos.h" |
66 | #endif | 66 | #endif |
67 | #if defined (iPlatformAppleMobile) | ||
68 | # include "ios.h" | ||
69 | #endif | ||
67 | #if defined (iPlatformMsys) | 70 | #if defined (iPlatformMsys) |
68 | # include "win32.h" | 71 | # include "win32.h" |
69 | #endif | 72 | #endif |
@@ -465,6 +468,9 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
465 | #if defined (iPlatformAppleDesktop) | 468 | #if defined (iPlatformAppleDesktop) |
466 | setupApplication_MacOS(); | 469 | setupApplication_MacOS(); |
467 | #endif | 470 | #endif |
471 | #if defined (iPlatformAppleMobile) | ||
472 | setupApplication_iOS(); | ||
473 | #endif | ||
468 | init_Keys(); | 474 | init_Keys(); |
469 | loadPrefs_App_(d); | 475 | loadPrefs_App_(d); |
470 | load_Keys(dataDir_App_()); | 476 | load_Keys(dataDir_App_()); |
@@ -24,4 +24,5 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
24 | 24 | ||
25 | #include "ui/util.h" | 25 | #include "ui/util.h" |
26 | 26 | ||
27 | void setupApplication_iOS (void); | ||
27 | 28 | ||
@@ -21,3 +21,15 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
22 | 22 | ||
23 | #include "ios.h" | 23 | #include "ios.h" |
24 | |||
25 | #include <SDL_events.h> | ||
26 | |||
27 | static void enableMouse_(iBool yes) { | ||
28 | SDL_EventState(SDL_MOUSEBUTTONDOWN, yes); | ||
29 | SDL_EventState(SDL_MOUSEMOTION, yes); | ||
30 | SDL_EventState(SDL_MOUSEBUTTONUP, yes); | ||
31 | } | ||
32 | |||
33 | void setupApplication_iOS(void) { | ||
34 | enableMouse_(iFalse); | ||
35 | } | ||
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 232b4140..0a282f1b 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -2351,7 +2351,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2351 | which device is sending the event. */ | 2351 | which device is sending the event. */ |
2352 | if (ev->wheel.which == 0) { /* Trackpad with precise scrolling w/inertia. */ | 2352 | if (ev->wheel.which == 0) { /* Trackpad with precise scrolling w/inertia. */ |
2353 | stop_Anim(&d->scrollY); | 2353 | stop_Anim(&d->scrollY); |
2354 | iInt2 wheel = init_I2(ev->wheel.x, ev->wheel.y); | 2354 | iInt2 wheel = mulf_I2(init_I2(ev->wheel.x, ev->wheel.y), get_Window()->pixelRatio); |
2355 | /* Only scroll on one axis at a time. */ | 2355 | /* Only scroll on one axis at a time. */ |
2356 | if (iAbs(wheel.x) > iAbs(wheel.y)) { | 2356 | if (iAbs(wheel.x) > iAbs(wheel.y)) { |
2357 | wheel.y = 0; | 2357 | wheel.y = 0; |
@@ -2359,8 +2359,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
2359 | else { | 2359 | else { |
2360 | wheel.x = 0; | 2360 | wheel.x = 0; |
2361 | } | 2361 | } |
2362 | scroll_DocumentWidget_(d, -wheel.y * get_Window()->pixelRatio); | 2362 | scroll_DocumentWidget_(d, -wheel.y); |
2363 | scrollWideBlock_DocumentWidget_(d, mouseCoord, wheel.x * get_Window()->pixelRatio, 0); | 2363 | #if defined (iPlatformAppleMobile) |
2364 | wheel.x = -wheel.x; | ||
2365 | #endif | ||
2366 | scrollWideBlock_DocumentWidget_(d, mouseCoord, wheel.x, 0); | ||
2364 | } | 2367 | } |
2365 | else | 2368 | else |
2366 | #endif | 2369 | #endif |
diff --git a/src/ui/indicatorwidget.c b/src/ui/indicatorwidget.c index 96556912..4a829ae3 100644 --- a/src/ui/indicatorwidget.c +++ b/src/ui/indicatorwidget.c | |||
@@ -72,6 +72,7 @@ void init_IndicatorWidget(iIndicatorWidget *d) { | |||
72 | iWidget *w = &d->widget; | 72 | iWidget *w = &d->widget; |
73 | init_Widget(w); | 73 | init_Widget(w); |
74 | init_Anim(&d->pos, 0); | 74 | init_Anim(&d->pos, 0); |
75 | setFlags_Widget(w, unhittable_WidgetFlag, iTrue); | ||
75 | } | 76 | } |
76 | 77 | ||
77 | static void startTimer_IndicatorWidget_(iIndicatorWidget *d) { | 78 | static void startTimer_IndicatorWidget_(iIndicatorWidget *d) { |
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c index 679d8e6f..32727703 100644 --- a/src/ui/sidebarwidget.c +++ b/src/ui/sidebarwidget.c | |||
@@ -322,7 +322,7 @@ static void updateItems_SidebarWidget_(iSidebarWidget *d) { | |||
322 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { | 322 | iConstForEach(PtrArray, i, identities_GmCerts(certs_App())) { |
323 | const iGmIdentity *ident = i.ptr; | 323 | const iGmIdentity *ident = i.ptr; |
324 | iSidebarItem *item = new_SidebarItem(); | 324 | iSidebarItem *item = new_SidebarItem(); |
325 | item->id = index_PtrArrayConstIterator(&i); | 325 | item->id = (uint32_t) index_PtrArrayConstIterator(&i); |
326 | item->icon = ident->icon; | 326 | item->icon = ident->icon; |
327 | set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); | 327 | set_String(&item->label, collect_String(subject_TlsCertificate(ident->cert))); |
328 | iDate until; | 328 | iDate until; |
diff --git a/src/ui/text.c b/src/ui/text.c index 65c7a256..7bb65bdc 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -668,7 +668,7 @@ static iChar nextChar_(const char **chPos, const char *end) { | |||
668 | } | 668 | } |
669 | 669 | ||
670 | static enum iFontId fontId_Text_(const iFont *font) { | 670 | static enum iFontId fontId_Text_(const iFont *font) { |
671 | return font - text_.fonts; | 671 | return (enum iFontId) (font - text_.fonts); |
672 | } | 672 | } |
673 | 673 | ||
674 | iLocalDef iBool isWrapBoundary_(iChar prevC, iChar c) { | 674 | iLocalDef iBool isWrapBoundary_(iChar prevC, iChar c) { |
diff --git a/src/ui/touch.c b/src/ui/touch.c new file mode 100644 index 00000000..12cd1745 --- /dev/null +++ b/src/ui/touch.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* Copyright 2021 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are met: | ||
5 | |||
6 | 1. Redistributions of source code must retain the above copyright notice, this | ||
7 | list of conditions and the following disclaimer. | ||
8 | 2. Redistributions in binary form must reproduce the above copyright notice, | ||
9 | this list of conditions and the following disclaimer in the documentation | ||
10 | and/or other materials provided with the distribution. | ||
11 | |||
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | ||
22 | |||
23 | #include "touch.h" | ||
24 | #include "window.h" | ||
25 | #include "app.h" | ||
26 | |||
27 | #include <the_Foundation/array.h> | ||
28 | #include <the_Foundation/math.h> | ||
29 | #include <SDL_timer.h> | ||
30 | |||
31 | iDeclareType(Touch) | ||
32 | iDeclareType(TouchState) | ||
33 | iDeclareType(Momentum) | ||
34 | |||
35 | struct Impl_Touch { | ||
36 | SDL_FingerID id; | ||
37 | iWidget *affinity; /* widget on which the touch started */ | ||
38 | iBool hasMoved; | ||
39 | uint32_t startTime; | ||
40 | iFloat3 startPos; | ||
41 | uint32_t posTime[2]; | ||
42 | iFloat3 pos[2]; | ||
43 | iFloat3 remainder; | ||
44 | }; | ||
45 | |||
46 | iLocalDef void pushPos_Touch_(iTouch *d, const iFloat3 pos, uint32_t time) { | ||
47 | d->posTime[1] = d->posTime[0]; | ||
48 | d->posTime[0] = time; | ||
49 | d->pos[1] = d->pos[0]; | ||
50 | d->pos[0] = pos; | ||
51 | } | ||
52 | |||
53 | struct Impl_Momentum { | ||
54 | iWidget *affinity; | ||
55 | uint32_t releaseTime; | ||
56 | iFloat3 velocity; | ||
57 | iFloat3 accum; | ||
58 | }; | ||
59 | |||
60 | struct Impl_TouchState { | ||
61 | iArray *touches; | ||
62 | iArray *moms; | ||
63 | double lastMomTime; | ||
64 | }; | ||
65 | |||
66 | static iTouchState *touchState_(void) { | ||
67 | static iTouchState state_; | ||
68 | iTouchState *d = &state_; | ||
69 | if (!d->touches) { | ||
70 | d->touches = new_Array(sizeof(iTouch)); | ||
71 | d->moms = new_Array(sizeof(iMomentum)); | ||
72 | d->lastMomTime = SDL_GetTicks(); | ||
73 | } | ||
74 | return d; | ||
75 | } | ||
76 | |||
77 | static iTouch *find_TouchState_(iTouchState *d, SDL_FingerID id) { | ||
78 | iConstForEach(Array, i, d->touches) { | ||
79 | iTouch *touch = (iTouch *) i.value; | ||
80 | if (touch->id == id) { | ||
81 | return touch; | ||
82 | } | ||
83 | } | ||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | static uint32_t longPressSpanMs_ = 500; | ||
88 | static int tapRadiusPt_ = 15; | ||
89 | |||
90 | static iBool isStationary_Touch_(const iTouch *d) { | ||
91 | return !d->hasMoved && | ||
92 | length_F3(sub_F3(d->pos[0], d->startPos)) < tapRadiusPt_ * get_Window()->pixelRatio; | ||
93 | } | ||
94 | |||
95 | static void dispatchClick_Touch_(const iTouch *d, int button) { | ||
96 | const iFloat3 tapPos = divf_F3(add_F3(d->pos[0], d->startPos), 2); | ||
97 | SDL_MouseButtonEvent btn = { | ||
98 | .type = SDL_MOUSEBUTTONDOWN, | ||
99 | .button = button, | ||
100 | .clicks = 1, | ||
101 | .state = SDL_PRESSED, | ||
102 | .timestamp = SDL_GetTicks(), | ||
103 | .which = SDL_TOUCH_MOUSEID, | ||
104 | .x = x_F3(tapPos), | ||
105 | .y = y_F3(tapPos) | ||
106 | }; | ||
107 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &btn); | ||
108 | /* Immediately released, too. */ | ||
109 | btn.type = SDL_MOUSEBUTTONUP; | ||
110 | btn.state = SDL_RELEASED; | ||
111 | btn.timestamp = SDL_GetTicks(); | ||
112 | dispatchEvent_Widget(get_Window()->root, (SDL_Event *) &btn); | ||
113 | } | ||
114 | |||
115 | static void clearWidgetMomentum_TouchState_(iTouchState *d, iWidget *widget) { | ||
116 | if (!widget) return; | ||
117 | iForEach(Array, m, d->moms) { | ||
118 | iMomentum *mom = m.value; | ||
119 | if (mom->affinity == widget) { | ||
120 | remove_ArrayIterator(&m); | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | static void update_TouchState_(void *ptr) { | ||
126 | iTouchState *d = ptr; | ||
127 | const uint32_t nowTime = SDL_GetTicks(); | ||
128 | /* Check for long presses to simulate right clicks. */ | ||
129 | iForEach(Array, i, d->touches) { | ||
130 | iTouch *touch = i.value; | ||
131 | /* Holding a touch will reset previous momentum for this widget. */ | ||
132 | if (isStationary_Touch_(touch)) { | ||
133 | if (nowTime - touch->startTime > 25) { | ||
134 | clearWidgetMomentum_TouchState_(d, touch->affinity); | ||
135 | } | ||
136 | if (nowTime - touch->startTime >= longPressSpanMs_ && touch->affinity) { | ||
137 | dispatchClick_Touch_(touch, SDL_BUTTON_RIGHT); | ||
138 | remove_ArrayIterator(&i); | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | /* Update/cancel momentum scrolling. */ { | ||
143 | const float minSpeed = 10.0f; | ||
144 | const float momFriction = 0.975f; | ||
145 | const float stepDurationMs = 1000.0f / 120.0f; | ||
146 | double momAvailMs = nowTime - d->lastMomTime; | ||
147 | int numSteps = iMin((int) (momAvailMs / stepDurationMs), 10); | ||
148 | d->lastMomTime += numSteps * stepDurationMs; | ||
149 | // printf("mom steps:%d\n", numSteps); | ||
150 | iForEach(Array, m, d->moms) { | ||
151 | if (numSteps == 0) break; | ||
152 | iMomentum *mom = m.value; | ||
153 | for (int step = 0; step < numSteps; step++) { | ||
154 | mulvf_F3(&mom->velocity, momFriction); | ||
155 | addv_F3(&mom->accum, mulf_F3(mom->velocity, stepDurationMs / 1000.0f)); | ||
156 | } | ||
157 | const iInt2 pixels = initF3_I2(mom->accum); | ||
158 | if (pixels.x || pixels.y) { | ||
159 | subv_F3(&mom->accum, initI2_F3(pixels)); | ||
160 | dispatchEvent_Widget(mom->affinity, (SDL_Event *) &(SDL_MouseWheelEvent){ | ||
161 | .type = SDL_MOUSEWHEEL, | ||
162 | .timestamp = SDL_GetTicks(), | ||
163 | .which = 0, /* means "precise scrolling" in DocumentWidget */ | ||
164 | .x = pixels.x, | ||
165 | .y = pixels.y | ||
166 | }); | ||
167 | } | ||
168 | //printf("mom vel:%f\n", length_F3(mom->velocity)); | ||
169 | if (length_F3(mom->velocity) < minSpeed) { | ||
170 | remove_ArrayIterator(&m); | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | /* Keep updating if interaction is still ongoing. */ | ||
175 | if (!isEmpty_Array(d->touches) || !isEmpty_Array(d->moms)) { | ||
176 | addTicker_App(update_TouchState_, ptr); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | iBool processEvent_Touch(const SDL_Event *ev) { | ||
181 | /* We only handle finger events here. */ | ||
182 | if (ev->type != SDL_FINGERDOWN && ev->type != SDL_FINGERMOTION && ev->type != SDL_FINGERUP) { | ||
183 | return iFalse; | ||
184 | } | ||
185 | iTouchState *d = touchState_(); | ||
186 | const SDL_TouchFingerEvent *fing = &ev->tfinger; | ||
187 | iWindow *window = get_Window(); | ||
188 | const iInt2 rootSize = rootSize_Window(window); | ||
189 | const iFloat3 pos = init_F3(fing->x * rootSize.x, fing->y * rootSize.y, 0); | ||
190 | //printf("%2d: %f: touch %f, %f\n", ev->type, z_F3(pos), x_F3(pos), y_F3(pos)); | ||
191 | //fflush(stdout); | ||
192 | const uint32_t nowTime = SDL_GetTicks(); | ||
193 | if (ev->type == SDL_FINGERDOWN) { | ||
194 | /* Register the new touch. */ | ||
195 | iWidget *aff = hitChild_Widget(window->root, init_I2(iRound(x_F3(pos)), iRound(y_F3(pos)))); | ||
196 | pushBack_Array(d->touches, &(iTouch){ | ||
197 | .id = fing->fingerId, | ||
198 | .affinity = aff, | ||
199 | .startTime = nowTime, | ||
200 | .startPos = pos, | ||
201 | .pos = pos | ||
202 | }); | ||
203 | /* Some widgets rely on hover state. */ | ||
204 | dispatchEvent_Widget(window->root, (SDL_Event *) &(SDL_MouseMotionEvent){ | ||
205 | .type = SDL_MOUSEMOTION, | ||
206 | .timestamp = SDL_GetTicks(), | ||
207 | .which = SDL_TOUCH_MOUSEID, | ||
208 | .x = x_F3(pos), | ||
209 | .y = y_F3(pos) | ||
210 | }); | ||
211 | addTicker_App(update_TouchState_, d); | ||
212 | } | ||
213 | else if (ev->type == SDL_FINGERMOTION) { | ||
214 | iTouch *touch = find_TouchState_(d, fing->fingerId); | ||
215 | if (touch && touch->affinity) { | ||
216 | /* TODO: Update touch position. */ | ||
217 | const iFloat3 amount = add_F3(touch->remainder, | ||
218 | divf_F3(mul_F3(init_F3(fing->dx, fing->dy, 0), | ||
219 | init_F3(rootSize.x, rootSize.y, 0)), | ||
220 | window->pixelRatio)); | ||
221 | const iInt2 pixels = init_I2(iRound(x_F3(amount)), iRound(y_F3(amount))); | ||
222 | iFloat3 remainder = sub_F3(amount, initI2_F3(pixels)); | ||
223 | touch->remainder = remainder; | ||
224 | pushPos_Touch_(touch, pos, nowTime); | ||
225 | if (!touch->hasMoved && !isStationary_Touch_(touch)) { | ||
226 | touch->hasMoved = iTrue; | ||
227 | } | ||
228 | if (pixels.x || pixels.y) { | ||
229 | // printf("%p (%s) wy: %f\n", touch->affinity, class_Widget(touch->affinity)->name, | ||
230 | // fing->dy * rootSize.y / window->pixelRatio); | ||
231 | dispatchEvent_Widget(touch->affinity, (SDL_Event *) &(SDL_MouseWheelEvent){ | ||
232 | .type = SDL_MOUSEWHEEL, | ||
233 | .timestamp = SDL_GetTicks(), | ||
234 | .which = 0, /* means "precise scrolling" in DocumentWidget */ | ||
235 | .x = pixels.x, | ||
236 | .y = pixels.y | ||
237 | }); | ||
238 | /* TODO: Keep increasing movement if the direction is the same. */ | ||
239 | clearWidgetMomentum_TouchState_(d, touch->affinity); | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | else if (ev->type == SDL_FINGERUP) { | ||
244 | iTouch *touch = find_TouchState_(d, fing->fingerId); | ||
245 | iForEach(Array, i, d->touches) { | ||
246 | iTouch *touch = i.value; | ||
247 | if (touch->id != fing->fingerId) { | ||
248 | continue; | ||
249 | } | ||
250 | const uint32_t elapsed = nowTime - touch->posTime[1]; | ||
251 | iFloat3 velocity = zero_F3(); | ||
252 | if (elapsed < 50) { | ||
253 | velocity = divf_F3(sub_F3(pos, touch->pos[1]), (float) elapsed / 1000.0f); | ||
254 | } | ||
255 | pushPos_Touch_(touch, pos, nowTime); | ||
256 | iBool wasUsed = iFalse; | ||
257 | const uint32_t duration = nowTime - touch->startTime; | ||
258 | /* If short and didn't move far, do a tap (left click). */ | ||
259 | if (duration < longPressSpanMs_ && isStationary_Touch_(touch)) { | ||
260 | dispatchClick_Touch_(touch, SDL_BUTTON_LEFT); | ||
261 | } | ||
262 | else if (length_F3(velocity) > 10.0f) { | ||
263 | clearWidgetMomentum_TouchState_(d, touch->affinity); | ||
264 | iMomentum mom = { | ||
265 | .affinity = touch->affinity, | ||
266 | .releaseTime = nowTime, | ||
267 | .velocity = velocity | ||
268 | }; | ||
269 | if (isEmpty_Array(d->moms)) { | ||
270 | d->lastMomTime = nowTime; | ||
271 | } | ||
272 | pushBack_Array(d->moms, &mom); | ||
273 | } | ||
274 | remove_ArrayIterator(&i); | ||
275 | } | ||
276 | } | ||
277 | return iTrue; | ||
278 | } | ||
diff --git a/src/ui/touch.h b/src/ui/touch.h new file mode 100644 index 00000000..fb8ff555 --- /dev/null +++ b/src/ui/touch.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* Copyright 2021 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are met: | ||
5 | |||
6 | 1. Redistributions of source code must retain the above copyright notice, this | ||
7 | list of conditions and the following disclaimer. | ||
8 | 2. Redistributions in binary form must reproduce the above copyright notice, | ||
9 | this list of conditions and the following disclaimer in the documentation | ||
10 | and/or other materials provided with the distribution. | ||
11 | |||
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | ||
22 | |||
23 | #pragma once | ||
24 | |||
25 | #include <the_Foundation/defs.h> | ||
26 | #include <SDL_events.h> | ||
27 | |||
28 | iBool processEvent_Touch (const SDL_Event *); | ||
29 | void update_Touch (void); | ||
diff --git a/src/ui/widget.c b/src/ui/widget.c index b60c67e3..5afb004f 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -731,6 +731,9 @@ size_t childIndex_Widget(const iWidget *d, const iAnyObject *child) { | |||
731 | } | 731 | } |
732 | 732 | ||
733 | iAny *hitChild_Widget(const iWidget *d, iInt2 coord) { | 733 | iAny *hitChild_Widget(const iWidget *d, iInt2 coord) { |
734 | if (d->flags & unhittable_WidgetFlag) { | ||
735 | return NULL; | ||
736 | } | ||
734 | iConstForEach(ObjectList, i, d->children) { | 737 | iConstForEach(ObjectList, i, d->children) { |
735 | iAny *found = hitChild_Widget(constAs_Widget(i.object), coord); | 738 | iAny *found = hitChild_Widget(constAs_Widget(i.object), coord); |
736 | if (found) return found; | 739 | if (found) return found; |
diff --git a/src/ui/widget.h b/src/ui/widget.h index 79f68b3c..a9756793 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -91,6 +91,7 @@ enum iWidgetFlag { | |||
91 | #define borderTop_WidgetFlag iBit64(37) | 91 | #define borderTop_WidgetFlag iBit64(37) |
92 | #define overflowScrollable_WidgetFlag iBit64(38) | 92 | #define overflowScrollable_WidgetFlag iBit64(38) |
93 | #define focusRoot_WidgetFlag iBit64(39) | 93 | #define focusRoot_WidgetFlag iBit64(39) |
94 | #define unhittable_WidgetFlag iBit64(40) | ||
94 | 95 | ||
95 | enum iWidgetAddPos { | 96 | enum iWidgetAddPos { |
96 | back_WidgetAddPos, | 97 | back_WidgetAddPos, |
diff --git a/src/ui/window.c b/src/ui/window.c index 563d57ae..d64e7ebf 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
33 | #include "paint.h" | 33 | #include "paint.h" |
34 | #include "util.h" | 34 | #include "util.h" |
35 | #include "keys.h" | 35 | #include "keys.h" |
36 | #include "touch.h" | ||
36 | #include "../app.h" | 37 | #include "../app.h" |
37 | #include "../visited.h" | 38 | #include "../visited.h" |
38 | #include "../gmcerts.h" | 39 | #include "../gmcerts.h" |
@@ -1246,6 +1247,9 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
1246 | postRefresh_App(); | 1247 | postRefresh_App(); |
1247 | return iTrue; | 1248 | return iTrue; |
1248 | } | 1249 | } |
1250 | if (processEvent_Touch(&event)) { | ||
1251 | return iTrue; | ||
1252 | } | ||
1249 | if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->focusGainedAt < 10) { | 1253 | if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->focusGainedAt < 10) { |
1250 | /* Suspiciously close to when input focus was received. For example under openbox, | 1254 | /* Suspiciously close to when input focus was received. For example under openbox, |
1251 | closing xterm with Ctrl+D will cause the keydown event to "spill" over to us. | 1255 | closing xterm with Ctrl+D will cause the keydown event to "spill" over to us. |