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 <core/gfxcard.h>
38 #include <core/state.h>
39 #include <core/windows_internal.h>
40 
41 #include <misc/util.h>
42 
43 #include <unique/context.h>
44 #include <unique/device.h>
45 #include <unique/internal.h>
46 
47 
48 D_DEBUG_DOMAIN( UniQuE_Pointer, "UniQuE/Pointer", "UniQuE's Pointer Device Class" );
49 
50 
51 typedef struct {
52      int magic;
53 
54      int x;
55      int y;
56 } PointerData;
57 
58 /**************************************************************************************************/
59 
60 static DFBResult
pointer_initialize(UniqueDevice * device,void * data,void * ctx)61 pointer_initialize( UniqueDevice    *device,
62                     void            *data,
63                     void            *ctx )
64 {
65      PointerData *pointer = data;
66 
67      D_MAGIC_ASSERT( device, UniqueDevice );
68 
69      D_DEBUG_AT( UniQuE_Pointer, "pointer_initialize( %p, %p, %p )\n", device, data, ctx );
70 
71      D_MAGIC_SET( pointer, PointerData );
72 
73      return DFB_OK;
74 }
75 
76 static void
pointer_shutdown(UniqueDevice * device,void * data,void * ctx)77 pointer_shutdown( UniqueDevice    *device,
78                   void            *data,
79                   void            *ctx )
80 {
81      PointerData *pointer = data;
82 
83      D_MAGIC_ASSERT( device, UniqueDevice );
84      D_MAGIC_ASSERT( pointer, PointerData );
85 
86      D_DEBUG_AT( UniQuE_Pointer, "pointer_shutdown( %p, %p, %p )\n", device, data, ctx );
87 
88      D_MAGIC_CLEAR( pointer );
89 }
90 
91 static void
pointer_connected(UniqueDevice * device,void * data,void * ctx,CoreInputDevice * source)92 pointer_connected( UniqueDevice    *device,
93                    void            *data,
94                    void            *ctx,
95                    CoreInputDevice *source )
96 {
97      PointerData *pointer = data;
98 
99      (void) pointer;
100 
101      D_MAGIC_ASSERT( device, UniqueDevice );
102      D_MAGIC_ASSERT( pointer, PointerData );
103 
104      D_ASSERT( source != NULL );
105 
106      D_DEBUG_AT( UniQuE_Pointer, "pointer_connected( %p, %p, %p, %p )\n",
107                  device, data, ctx, source );
108 }
109 
110 static void
pointer_disconnected(UniqueDevice * device,void * data,void * ctx,CoreInputDevice * source)111 pointer_disconnected( UniqueDevice    *device,
112                       void            *data,
113                       void            *ctx,
114                       CoreInputDevice *source )
115 {
116      PointerData *pointer = data;
117 
118      (void) pointer;
119 
120      D_MAGIC_ASSERT( device, UniqueDevice );
121      D_MAGIC_ASSERT( pointer, PointerData );
122 
123      D_ASSERT( source != NULL );
124 
125      D_DEBUG_AT( UniQuE_Pointer, "pointer_disconnected( %p, %p, %p, %p )\n",
126                  device, data, ctx, source );
127 }
128 
129 static void
pointer_process_event(UniqueDevice * device,void * data,void * ctx,const DFBInputEvent * event)130 pointer_process_event( UniqueDevice        *device,
131                        void                *data,
132                        void                *ctx,
133                        const DFBInputEvent *event )
134 {
135      UniqueInputEvent  evt;
136      PointerData      *pointer = data;
137      UniqueContext    *context = ctx;
138      CoreWindowStack  *stack;
139 
140      D_MAGIC_ASSERT( device, UniqueDevice );
141      D_MAGIC_ASSERT( pointer, PointerData );
142      D_MAGIC_ASSERT( context, UniqueContext );
143 
144      D_ASSERT( event != NULL );
145 
146      D_DEBUG_AT( UniQuE_Pointer, "pointer_process_event( %p, %p, %p, %p ) <- type 0x%08x\n",
147                  device, data, ctx, event, event->type );
148 
149      stack = context->stack;
150 
151      D_ASSERT( stack != NULL );
152 
153      switch (event->type) {
154           case DIET_AXISMOTION: {
155                /*int x = pointer->x;
156                int y = pointer->y;*/
157                int x = stack->cursor.x;
158                int y = stack->cursor.y;
159 
160                if (event->flags & DIEF_AXISREL) {
161                     int rel = event->axisrel;
162 
163                     /* handle cursor acceleration */
164                     if (rel > stack->cursor.threshold)
165                          rel += (rel - stack->cursor.threshold)
166                                 * stack->cursor.numerator
167                                 / stack->cursor.denominator;
168                     else if (rel < -stack->cursor.threshold)
169                          rel += (rel + stack->cursor.threshold)
170                                 * stack->cursor.numerator
171                                 / stack->cursor.denominator;
172 
173                     switch (event->axis) {
174                          case DIAI_X:
175                               x += rel;
176                               break;
177 
178                          case DIAI_Y:
179                               y += rel;
180                               break;
181 
182                          default:
183                               return;
184                     }
185                }
186                else if (event->flags & DIEF_AXISABS) {
187                     switch (event->axis) {
188                          case DIAI_X:
189                               x = event->axisabs;
190                               break;
191 
192                          case DIAI_Y:
193                               y = event->axisabs;
194                               break;
195 
196                          default:
197                               return;
198                     }
199                }
200                else
201                     return;
202 
203                if (x < 0)
204                     x = 0;
205                else if (x >= context->width)
206                     x = context->width - 1;
207 
208                if (y < 0)
209                     y = 0;
210                else if (y >= context->height)
211                     y = context->height - 1;
212 
213                if (x == pointer->x && y == pointer->y)
214                     return;
215 
216                pointer->x = x;
217                pointer->y = y;
218 
219                evt.type = UIET_MOTION;
220 
221                evt.pointer.device_id = event->device_id;
222                evt.pointer.x         = x;
223                evt.pointer.y         = y;
224                evt.pointer.buttons   = event->buttons;
225 
226                unique_device_dispatch( device, &evt );
227                break;
228           }
229 
230           case DIET_BUTTONPRESS:
231           case DIET_BUTTONRELEASE:
232                evt.type = UIET_BUTTON;
233 
234                evt.pointer.device_id = event->device_id;
235                evt.pointer.press     = (event->type == DIET_BUTTONPRESS);
236                evt.pointer.x         = pointer->x;
237                evt.pointer.y         = pointer->y;
238                evt.pointer.button    = event->button;
239                evt.pointer.buttons   = event->buttons;
240 
241                unique_device_dispatch( device, &evt );
242                break;
243 
244           default:
245                break;
246      }
247 }
248 
249 
250 const UniqueDeviceClass unique_pointer_device_class = {
251      data_size:     sizeof(PointerData),
252 
253      Initialize:    pointer_initialize,
254      Shutdown:      pointer_shutdown,
255      Connected:     pointer_connected,
256      Disconnected:  pointer_disconnected,
257      ProcessEvent:  pointer_process_event
258 };
259 
260