1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <directfb.h>
32
33 #include <direct/debug.h>
34 #include <direct/messages.h>
35 #include <direct/util.h>
36
37 #include <fusion/shmalloc.h>
38 #include <fusion/vector.h>
39
40 #include <core/input.h>
41 #include <core/windowstack.h>
42
43 #include <misc/util.h>
44
45 #include <unique/device.h>
46 #include <unique/input_channel.h>
47 #include <unique/input_switch.h>
48 #include <unique/internal.h>
49
50
51
52 D_DEBUG_DOMAIN( UniQuE_InpSw, "UniQuE/InpSwitch", "UniQuE's Input Switch" );
53
54
55 typedef struct {
56 DirectLink link;
57
58 int magic;
59
60 UniqueDevice *device;
61
62 GlobalReaction reaction;
63 } SwitchConnection;
64
65 /**************************************************************************************************/
66
67 static void purge_connection( UniqueInputSwitch *input_switch,
68 SwitchConnection *connection );
69
70 static bool target_switch ( UniqueInputSwitch *input_switch,
71 UniqueDeviceClassIndex index,
72 UniqueInputChannel *channel );
73
74 static bool update_targets ( UniqueInputSwitch *input_switch );
75
76 /**************************************************************************************************/
77
78 DFBResult
unique_input_switch_create(UniqueContext * context,UniqueInputSwitch ** ret_switch)79 unique_input_switch_create( UniqueContext *context,
80 UniqueInputSwitch **ret_switch )
81 {
82 int i;
83 WMShared *shared;
84 UniqueInputSwitch *input_switch;
85
86 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_create( context %p )\n", context );
87
88 D_MAGIC_ASSERT( context, UniqueContext );
89
90 D_ASSERT( ret_switch != NULL );
91
92 shared = context->shared;
93
94 D_MAGIC_ASSERT( shared, WMShared );
95
96 /* Allocate switch data. */
97 input_switch = SHCALLOC( context->shmpool, 1, sizeof(UniqueInputSwitch) );
98 if (!input_switch) {
99 D_WARN( "out of (shared) memory" );
100 return D_OOSHM();
101 }
102
103 /* Initialize input_switch data. */
104 input_switch->context = context;
105
106 /* Set class ID of each target. */
107 for (i=0; i<_UDCI_NUM; i++)
108 input_switch->targets[i].clazz = shared->device_classes[i];
109
110 D_MAGIC_SET( input_switch, UniqueInputSwitch );
111
112 D_DEBUG_AT( UniQuE_InpSw, " -> input_switch created (%p)\n", input_switch );
113
114 *ret_switch = input_switch;
115
116 return DFB_OK;
117 }
118
119 DFBResult
unique_input_switch_destroy(UniqueInputSwitch * input_switch)120 unique_input_switch_destroy( UniqueInputSwitch *input_switch )
121 {
122 int i;
123 DirectLink *n;
124 SwitchConnection *connection;
125 UniqueContext *context;
126
127 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
128
129 context = input_switch->context;
130
131 D_MAGIC_ASSERT( context, UniqueContext );
132
133 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_destroy( %p )\n", input_switch );
134
135 direct_list_foreach_safe (connection, n, input_switch->connections) {
136 D_MAGIC_ASSERT( connection, SwitchConnection );
137
138 purge_connection( input_switch, connection );
139 }
140
141 D_ASSERT( input_switch->connections == NULL );
142
143 for (i=0; i<_UDCI_NUM; i++) {
144 UniqueInputFilter *filter;
145 UniqueInputTarget *target = &input_switch->targets[i];
146
147 direct_list_foreach_safe (filter, n, target->filters) {
148 D_MAGIC_ASSERT( filter, UniqueInputFilter );
149 D_MAGIC_ASSERT( filter->channel, UniqueInputChannel );
150
151 D_DEBUG_AT( UniQuE_InpSw, " -> filter %p, index %d, channel %p\n",
152 filter, filter->index, filter->channel );
153
154 direct_list_remove( &target->filters, &filter->link );
155
156 D_MAGIC_CLEAR( filter );
157
158 SHFREE( context->shmpool, filter );
159 }
160
161 D_ASSERT( target->filters == NULL );
162 }
163
164 D_MAGIC_CLEAR( input_switch );
165
166 SHFREE( context->shmpool, input_switch );
167
168 return DFB_OK;
169 }
170
171 DFBResult
unique_input_switch_add(UniqueInputSwitch * input_switch,UniqueDevice * device)172 unique_input_switch_add( UniqueInputSwitch *input_switch,
173 UniqueDevice *device )
174 {
175 DFBResult ret;
176 SwitchConnection *connection;
177 UniqueContext *context;
178
179 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
180 D_MAGIC_ASSERT( device, UniqueDevice );
181
182 context = input_switch->context;
183
184 D_MAGIC_ASSERT( context, UniqueContext );
185
186 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_add( %p, %p )\n", input_switch, device );
187
188 /* Allocate connection structure. */
189 connection = SHCALLOC( context->shmpool, 1, sizeof(SwitchConnection) );
190 if (!connection) {
191 D_WARN( "out of (shared) memory" );
192 return D_OOSHM();
193 }
194
195 /* Initialize connection structure. */
196 connection->device = device;
197
198 /* Attach global reaction for processing events. */
199 ret = unique_device_attach_global( device, UNIQUE_INPUT_SWITCH_DEVICE_LISTENER,
200 input_switch, &connection->reaction );
201 if (ret) {
202 D_DERROR( ret, "UniQuE/InpSwitch: Could not attach global device reaction!\n" );
203 SHFREE( context->shmpool, connection );
204 return ret;
205 }
206
207 /* Add the new connection to the list. */
208 direct_list_append( &input_switch->connections, &connection->link );
209
210 D_MAGIC_SET( connection, SwitchConnection );
211
212 return DFB_OK;
213 }
214
215 DFBResult
unique_input_switch_remove(UniqueInputSwitch * input_switch,UniqueDevice * device)216 unique_input_switch_remove( UniqueInputSwitch *input_switch,
217 UniqueDevice *device )
218 {
219 SwitchConnection *connection;
220
221 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
222 D_MAGIC_ASSERT( device, UniqueDevice );
223
224 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_remove( %p, %p )\n", input_switch, device );
225
226 direct_list_foreach (connection, input_switch->connections) {
227 D_MAGIC_ASSERT( connection, SwitchConnection );
228
229 if (connection->device == device)
230 break;
231 }
232
233 if (!connection) {
234 D_WARN( "device not found amoung connections" );
235 return DFB_ITEMNOTFOUND;
236 }
237
238 purge_connection( input_switch, connection );
239
240 return DFB_OK;
241 }
242
243 DFBResult
unique_input_switch_select(UniqueInputSwitch * input_switch,UniqueDeviceClassIndex index,UniqueInputChannel * channel)244 unique_input_switch_select( UniqueInputSwitch *input_switch,
245 UniqueDeviceClassIndex index,
246 UniqueInputChannel *channel )
247 {
248 UniqueInputTarget *target;
249
250 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
251 D_MAGIC_ASSERT( channel, UniqueInputChannel );
252
253 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_select( %p, %d, %p )\n",
254 input_switch, index, channel );
255
256 D_ASSERT( index >= 0 );
257 D_ASSERT( index < _UDCI_NUM );
258
259 target = &input_switch->targets[index];
260
261 target->normal = channel;
262
263 if (!target->fixed && !target->implicit)
264 target_switch( input_switch, index, channel );
265
266 return DFB_OK;
267 }
268
269 DFBResult
unique_input_switch_set(UniqueInputSwitch * input_switch,UniqueDeviceClassIndex index,UniqueInputChannel * channel)270 unique_input_switch_set( UniqueInputSwitch *input_switch,
271 UniqueDeviceClassIndex index,
272 UniqueInputChannel *channel )
273 {
274 UniqueInputTarget *target;
275
276 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
277 D_MAGIC_ASSERT( channel, UniqueInputChannel );
278
279 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_set( %p, %d, %p )\n",
280 input_switch, index, channel );
281
282 D_ASSERT( index >= 0 );
283 D_ASSERT( index < _UDCI_NUM );
284
285 target = &input_switch->targets[index];
286
287 if (target->fixed)
288 return DFB_BUSY;
289
290 target->fixed = channel;
291
292 target_switch( input_switch, index, channel );
293
294 return DFB_OK;
295 }
296
297 DFBResult
unique_input_switch_unset(UniqueInputSwitch * input_switch,UniqueDeviceClassIndex index,UniqueInputChannel * channel)298 unique_input_switch_unset( UniqueInputSwitch *input_switch,
299 UniqueDeviceClassIndex index,
300 UniqueInputChannel *channel )
301 {
302 UniqueInputTarget *target;
303
304 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_unset( %p, %d, %p )\n",
305 input_switch, index, channel );
306
307 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
308 D_MAGIC_ASSERT( channel, UniqueInputChannel );
309
310 D_ASSERT( index >= 0 );
311 D_ASSERT( index < _UDCI_NUM );
312
313 target = &input_switch->targets[index];
314
315 if (target->fixed != channel)
316 return DFB_ACCESSDENIED;
317
318 target->fixed = NULL;
319
320
321 update_targets( input_switch );
322 //target_switch( input_switch, index, target->normal );
323
324 return DFB_OK;
325 }
326
327 DFBResult
unique_input_switch_set_filter(UniqueInputSwitch * input_switch,UniqueDeviceClassIndex index,UniqueInputChannel * channel,const UniqueInputEvent * event,UniqueInputFilter ** ret_filter)328 unique_input_switch_set_filter( UniqueInputSwitch *input_switch,
329 UniqueDeviceClassIndex index,
330 UniqueInputChannel *channel,
331 const UniqueInputEvent *event,
332 UniqueInputFilter **ret_filter )
333 {
334 UniqueInputFilter *filter;
335 UniqueInputTarget *target;
336 UniqueContext *context;
337
338 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_set_filter( %p, %d, %p, %p )\n",
339 input_switch, index, channel, event );
340
341 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
342 D_MAGIC_ASSERT( channel, UniqueInputChannel );
343
344 D_ASSERT( index >= 0 );
345 D_ASSERT( index < _UDCI_NUM );
346
347 D_ASSERT( event != NULL );
348 D_ASSERT( ret_filter != NULL );
349
350 context = input_switch->context;
351
352 D_MAGIC_ASSERT( context, UniqueContext );
353
354 target = &input_switch->targets[index];
355
356 direct_list_foreach (filter, target->filters) {
357 D_MAGIC_ASSERT( filter, UniqueInputFilter );
358
359 if (unique_device_filter( target->clazz, event, &filter->filter ))
360 return DFB_BUSY;
361 }
362
363 /* Allocate new filter. */
364 filter = SHCALLOC( context->shmpool, 1, sizeof(UniqueInputFilter) );
365 if (!filter)
366 return D_OOSHM();
367
368 filter->index = index;
369 filter->channel = channel;
370 filter->filter = *event;
371
372 direct_list_append( &target->filters, &filter->link );
373
374 D_MAGIC_SET( filter, UniqueInputFilter );
375
376 *ret_filter = filter;
377
378 return DFB_OK;
379 }
380
381 DFBResult
unique_input_switch_unset_filter(UniqueInputSwitch * input_switch,UniqueInputFilter * filter)382 unique_input_switch_unset_filter( UniqueInputSwitch *input_switch,
383 UniqueInputFilter *filter )
384 {
385 UniqueInputTarget *target;
386 UniqueContext *context;
387
388 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_unset_filter( %p, %p )\n",
389 input_switch, filter );
390
391 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
392 D_MAGIC_ASSERT( filter, UniqueInputFilter );
393
394 context = input_switch->context;
395
396 D_MAGIC_ASSERT( context, UniqueContext );
397
398 D_ASSERT( filter->index >= 0 );
399 D_ASSERT( filter->index < _UDCI_NUM );
400
401 target = &input_switch->targets[filter->index];
402
403 direct_list_remove( &target->filters, &filter->link );
404
405 D_MAGIC_CLEAR( filter );
406
407 SHFREE( context->shmpool, filter );
408
409 return DFB_OK;
410 }
411
412 DFBResult
unique_input_switch_drop(UniqueInputSwitch * input_switch,UniqueInputChannel * channel)413 unique_input_switch_drop( UniqueInputSwitch *input_switch,
414 UniqueInputChannel *channel )
415 {
416 int i;
417 UniqueContext *context;
418
419 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_drop( %p, %p )\n", input_switch, channel );
420
421 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
422 D_MAGIC_ASSERT( channel, UniqueInputChannel );
423
424 context = input_switch->context;
425
426 D_MAGIC_ASSERT( context, UniqueContext );
427
428 for (i=0; i<_UDCI_NUM; i++) {
429 DirectLink *n;
430 UniqueInputFilter *filter;
431 UniqueInputTarget *target = &input_switch->targets[i];
432
433 if (target->normal == channel)
434 target->normal = NULL;
435
436 if (target->fixed == channel)
437 target->fixed = NULL;
438
439 if (target->implicit == channel)
440 target->implicit = NULL;
441
442 if (target->current == channel)
443 target->current = NULL;
444
445 D_DEBUG_AT( UniQuE_InpSw, " -> index %d, filters %p\n", i, target->filters );
446
447 direct_list_foreach_safe (filter, n, target->filters) {
448 D_MAGIC_ASSERT( filter, UniqueInputFilter );
449 D_MAGIC_ASSERT( filter->channel, UniqueInputChannel );
450
451 D_DEBUG_AT( UniQuE_InpSw,
452 " -> filter %p, channel %p\n", filter, filter->channel );
453
454 D_ASSUME( filter->channel != channel );
455
456 if (filter->channel == channel) {
457 direct_list_remove( &target->filters, &filter->link );
458
459 D_MAGIC_CLEAR( filter );
460
461 SHFREE( context->shmpool, filter );
462 }
463 }
464 }
465
466 if (!input_switch->targets[UDCI_POINTER].fixed)
467 update_targets( input_switch );
468
469 return DFB_OK;
470 }
471
472 DFBResult
unique_input_switch_update(UniqueInputSwitch * input_switch,UniqueInputChannel * channel)473 unique_input_switch_update( UniqueInputSwitch *input_switch,
474 UniqueInputChannel *channel )
475 {
476 int x, y, i;
477 StretRegion *region;
478 UniqueContext *context;
479
480 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
481
482 x = input_switch->x;
483 y = input_switch->y;
484
485 D_DEBUG_AT( UniQuE_InpSw, "unique_input_switch_update( %d, %d )\n", x, y );
486
487 context = input_switch->context;
488
489 D_MAGIC_ASSERT( context, UniqueContext );
490
491 region = stret_region_at( context->root, x, y, SRF_INPUT, SRCID_UNKNOWN );
492 if (region) {
493 for (i=0; i<_UDCI_NUM; i++) {
494 UniqueInputTarget *target = &input_switch->targets[i];
495
496 if (target->normal == channel)
497 stret_region_get_input( region, i, x, y, &target->normal );
498 }
499 }
500 else {
501 for (i=0; i<_UDCI_NUM; i++) {
502 UniqueInputTarget *target = &input_switch->targets[i];
503
504 if (target->normal == channel)
505 target->normal = NULL;
506 }
507 }
508
509 for (i=0; i<_UDCI_NUM; i++) {
510 UniqueInputTarget *target = &input_switch->targets[i];
511
512 target_switch( input_switch, i, target->fixed ? : target->implicit ? : target->normal );
513 }
514
515 return DFB_OK;
516 }
517
518 /**************************************************************************************************/
519
520 static bool
target_switch(UniqueInputSwitch * input_switch,UniqueDeviceClassIndex index,UniqueInputChannel * channel)521 target_switch( UniqueInputSwitch *input_switch,
522 UniqueDeviceClassIndex index,
523 UniqueInputChannel *channel )
524 {
525 UniqueInputEvent evt;
526 UniqueInputTarget *target;
527 UniqueInputChannel *current;
528
529 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
530 D_ASSERT( index >= 0 );
531 D_ASSERT( index < _UDCI_NUM );
532
533 target = &input_switch->targets[index];
534
535 current = target->current;
536
537 D_MAGIC_ASSERT_IF( channel, UniqueInputChannel );
538 D_MAGIC_ASSERT_IF( current, UniqueInputChannel );
539
540 if (channel == current)
541 return false;
542
543 D_DEBUG_AT( UniQuE_InpSw, "target_switch( index %d, x %d, y %d, channel %p )\n",
544 index, input_switch->x, input_switch->y, channel );
545
546 evt.type = UIET_CHANNEL;
547
548 evt.channel.index = index;
549 evt.channel.x = input_switch->x;
550 evt.channel.y = input_switch->y;
551
552 if (current) {
553 evt.channel.selected = false;
554
555 unique_input_channel_dispatch( current, &evt );
556 }
557
558 target->current = channel;
559
560 if (channel) {
561 evt.channel.selected = true;
562
563 unique_input_channel_dispatch( channel, &evt );
564 }
565
566 return true;
567 }
568
569 static void
target_dispatch(UniqueInputTarget * target,const UniqueInputEvent * event)570 target_dispatch( UniqueInputTarget *target,
571 const UniqueInputEvent *event )
572 {
573 UniqueInputFilter *filter;
574 UniqueInputChannel *channel;
575
576 D_ASSERT( target != NULL );
577 D_ASSERT( event != NULL );
578
579 channel = target->current;
580
581 D_MAGIC_ASSERT_IF( channel, UniqueInputChannel );
582
583
584 direct_list_foreach (filter, target->filters) {
585 D_MAGIC_ASSERT( filter, UniqueInputFilter );
586
587 if (unique_device_filter( target->clazz, event, &filter->filter )) {
588 channel = filter->channel;
589
590 D_MAGIC_ASSERT( channel, UniqueInputChannel );
591
592 break;
593 }
594 }
595
596 if (channel)
597 unique_input_channel_dispatch( channel, event );
598 else
599 D_DEBUG_AT( UniQuE_InpSw, "target_dispatch( class %d ) "
600 "<- no selected channel, dropping event.\n", target->clazz );
601 }
602
603 static bool
update_targets(UniqueInputSwitch * input_switch)604 update_targets( UniqueInputSwitch *input_switch )
605 {
606 int x, y, i;
607 StretRegion *region;
608 UniqueContext *context;
609 bool updated[_UDCI_NUM];
610
611 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
612
613 x = input_switch->x;
614 y = input_switch->y;
615
616 D_DEBUG_AT( UniQuE_InpSw, "update_targets( %d, %d )\n", x, y );
617
618 context = input_switch->context;
619
620 D_MAGIC_ASSERT( context, UniqueContext );
621
622 region = stret_region_at( context->root, x, y, SRF_INPUT, SRCID_UNKNOWN );
623 if (region) {
624 for (i=0; i<_UDCI_NUM; i++)
625 stret_region_get_input( region, i, x, y, &input_switch->targets[i].normal );
626 }
627 else {
628 for (i=0; i<_UDCI_NUM; i++)
629 input_switch->targets[i].normal = NULL;
630 }
631
632 for (i=0; i<_UDCI_NUM; i++) {
633 UniqueInputTarget *target = &input_switch->targets[i];
634
635 updated[i] = target_switch( input_switch, i,
636 target->fixed ? : target->implicit ? : target->normal );
637 }
638
639 return updated[UDCI_POINTER];
640 }
641
642 ReactionResult
_unique_input_switch_device_listener(const void * msg_data,void * ctx)643 _unique_input_switch_device_listener( const void *msg_data,
644 void *ctx )
645 {
646 const UniqueInputEvent *event = msg_data;
647 UniqueInputSwitch *inpsw = ctx;
648 UniqueInputTarget *target = NULL;
649 UniqueContext *context;
650
651 (void) event;
652 (void) inpsw;
653
654 D_ASSERT( event != NULL );
655
656 D_MAGIC_ASSERT( inpsw, UniqueInputSwitch );
657
658 context = inpsw->context;
659
660 D_MAGIC_ASSERT( context, UniqueContext );
661
662 if (dfb_windowstack_lock( context->stack ))
663 return RS_OK;
664
665 if (!context->active) {
666 dfb_windowstack_unlock( context->stack );
667 return RS_OK;
668 }
669
670 D_DEBUG_AT( UniQuE_InpSw, "_unique_input_switch_device_listener( %p, %p )\n",
671 event, inpsw );
672
673 switch (event->type) {
674 case UIET_MOTION:
675 target = &inpsw->targets[UDCI_POINTER];
676
677 inpsw->x = event->pointer.x;
678 inpsw->y = event->pointer.y;
679
680 if (!target->fixed && !target->implicit && update_targets( inpsw ))
681 break;
682
683 target_dispatch( target, event );
684 break;
685
686 case UIET_BUTTON:
687 target = &inpsw->targets[UDCI_POINTER];
688
689 if (event->pointer.press && !target->implicit) {
690 D_DEBUG_AT( UniQuE_InpSw, " -> implicit pointer grab, %p\n", target->current );
691
692 target->implicit = target->current;
693 }
694
695 target_dispatch( target, event );
696
697 if (!event->pointer.press && !event->pointer.buttons) {
698 D_ASSUME( target->implicit != NULL );
699
700 if (target->implicit) {
701 D_DEBUG_AT( UniQuE_InpSw, " -> implicit pointer ungrab, %p\n", target->implicit );
702
703 target->implicit = NULL;
704
705 if (!target->fixed)
706 update_targets( inpsw );
707 }
708 }
709 break;
710
711 case UIET_WHEEL:
712 target_dispatch( &inpsw->targets[UDCI_WHEEL], event );
713 break;
714
715 case UIET_KEY:
716 target = &inpsw->targets[UDCI_KEYBOARD];
717
718 if (event->keyboard.press && !target->implicit) {
719 D_DEBUG_AT( UniQuE_InpSw, " -> implicit keyboard grab, %p\n", target->current );
720
721 target->implicit = target->current;
722 }
723
724 target_dispatch( target, event );
725
726 if (!event->keyboard.press && !event->keyboard.modifiers) {
727 //D_ASSUME( target->implicit != NULL );
728
729 if (target->implicit) {
730 D_DEBUG_AT( UniQuE_InpSw, " -> implicit keyboard ungrab, %p\n", target->implicit );
731
732 if (!target->fixed)
733 target_switch( inpsw, UDCI_KEYBOARD, target->normal );
734
735 target->implicit = NULL;
736 }
737 }
738 break;
739
740 default:
741 D_ONCE( "unknown event type" );
742 break;
743 }
744
745 dfb_windowstack_unlock( context->stack );
746
747 return RS_OK;
748 }
749
750 /**************************************************************************************************/
751
752 static void
purge_connection(UniqueInputSwitch * input_switch,SwitchConnection * connection)753 purge_connection( UniqueInputSwitch *input_switch,
754 SwitchConnection *connection )
755 {
756 UniqueContext *context;
757
758 D_DEBUG_AT( UniQuE_InpSw, "purge_connection( %p, %p )\n", input_switch, connection );
759
760 D_MAGIC_ASSERT( input_switch, UniqueInputSwitch );
761 D_MAGIC_ASSERT( connection, SwitchConnection );
762
763 context = input_switch->context;
764
765 D_MAGIC_ASSERT( context, UniqueContext );
766
767 /* Detach global reaction for receiving events. */
768 unique_device_detach_global( connection->device, &connection->reaction );
769
770 direct_list_remove( &input_switch->connections, &connection->link );
771
772 D_MAGIC_CLEAR( connection );
773
774 SHFREE( context->shmpool, connection );
775 }
776
777