|
|
1.1.1.3 ! root 1: /* $Id: mouse.c,v 1.3 2010/02/07 14:29:53 fredette Exp $ */ 1.1 root 2: 3: /* generic/mouse.c - generic mouse implementation support: */ 4: 5: /* 6: * Copyright (c) 2003 Matt Fredette 7: * All rights reserved. 8: * 9: * Redistribution and use in source and binary forms, with or without 10: * modification, are permitted provided that the following conditions 11: * are met: 12: * 1. Redistributions of source code must retain the above copyright 13: * notice, this list of conditions and the following disclaimer. 14: * 2. Redistributions in binary form must reproduce the above copyright 15: * notice, this list of conditions and the following disclaimer in the 16: * documentation and/or other materials provided with the distribution. 17: * 3. All advertising materials mentioning features or use of this software 18: * must display the following acknowledgement: 19: * This product includes software developed by Matt Fredette. 20: * 4. The name of the author may not be used to endorse or promote products 21: * derived from this software without specific prior written permission. 22: * 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33: * POSSIBILITY OF SUCH DAMAGE. 34: */ 35: 36: #include <tme/common.h> 1.1.1.3 ! root 37: _TME_RCSID("$Id: mouse.c,v 1.3 2010/02/07 14:29:53 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include <tme/generic/mouse.h> 1.1.1.2 root 41: #include <errno.h> 1.1 root 42: 43: /* macros: */ 44: 45: /* types: */ 46: 47: /* this creates a new mouse buffer: */ 48: struct tme_mouse_buffer * 49: tme_mouse_buffer_new(unsigned int size) 50: { 51: struct tme_mouse_buffer *buffer; 52: 53: /* round the buffer size up to a power of two: */ 54: if (size & (size - 1)) { 55: do { 56: size &= (size - 1); 57: } while (size & (size - 1)); 58: size <<= 1; 59: } 60: 61: /* allocate the buffer: */ 62: buffer = tme_new0(struct tme_mouse_buffer, 1); 63: 64: /* set the buffer size: */ 65: buffer->tme_mouse_buffer_size = size; 66: 67: /* set the head and tail pointers: */ 68: buffer->tme_mouse_buffer_head = 0; 69: buffer->tme_mouse_buffer_tail = 0; 70: 71: /* allocate the buffer events: */ 72: buffer->tme_mouse_buffer_events 73: = tme_new(struct tme_mouse_event, size); 74: 75: /* done: */ 76: return (buffer); 77: } 78: 79: /* this destroys a mouse buffer: */ 80: void 81: tme_mouse_buffer_destroy(struct tme_mouse_buffer *buffer) 82: { 83: 84: /* free the events: */ 85: tme_free(buffer->tme_mouse_buffer_events); 86: 87: /* destroy the buffer itself: */ 88: tme_free(buffer); 89: } 90: 1.1.1.3 ! root 91: /* this returns nonzero if both deltas are nonzero and have ! 92: different signs: */ ! 93: static inline int ! 94: _tme_mouse_deltas_opposite(int delta, int delta_last) ! 95: { ! 96: int opposite; ! 97: ! 98: opposite = (delta_last ^ delta) < 0; ! 99: opposite -= (delta == 0); ! 100: opposite -= (delta_last == 0); ! 101: return (opposite > 0); ! 102: } ! 103: 1.1 root 104: /* this copies an event into a mouse buffer: */ 105: int 106: tme_mouse_buffer_copyin(struct tme_mouse_buffer *buffer, 107: _tme_const struct tme_mouse_event *event) 108: { 109: unsigned int buffer_head, buffer_size_mask; 1.1.1.3 ! root 110: struct tme_mouse_event *event_last; ! 111: unsigned int unmergeable_mash; 1.1 root 112: 113: buffer_head = buffer->tme_mouse_buffer_head; 114: buffer_size_mask = buffer->tme_mouse_buffer_size - 1; 115: 1.1.1.3 ! root 116: /* if the buffer is not empty: */ ! 117: if (buffer_head != buffer->tme_mouse_buffer_tail) { ! 118: ! 119: /* get the last event in the buffer: */ ! 120: event_last = &buffer->tme_mouse_buffer_events[(buffer_head - 1) & buffer_size_mask]; ! 121: ! 122: /* the new event can't be merged if both delta Xs are nonzero and ! 123: have different signs: */ ! 124: unmergeable_mash ! 125: = _tme_mouse_deltas_opposite(event->tme_mouse_event_delta_x, ! 126: event_last->tme_mouse_event_delta_x); ! 127: ! 128: /* the new event can't be merged if both delta Ys are nonzero and ! 129: have different signs: */ ! 130: unmergeable_mash ! 131: |= _tme_mouse_deltas_opposite(event->tme_mouse_event_delta_y, ! 132: event_last->tme_mouse_event_delta_y); ! 133: ! 134: /* the new event can't be merged if its button mask is ! 135: different: */ ! 136: unmergeable_mash ! 137: |= (event->tme_mouse_event_buttons ! 138: ^ event_last->tme_mouse_event_buttons); ! 139: ! 140: /* the new event can't be merged if its delta units are ! 141: different: */ ! 142: unmergeable_mash ! 143: |= (event->tme_mouse_event_delta_units ! 144: ^ event_last->tme_mouse_event_delta_units); ! 145: ! 146: /* if the new event can't be merged: */ ! 147: if (__tme_predict_false(unmergeable_mash)) { ! 148: ! 149: /* nothing to do */ ! 150: } ! 151: ! 152: /* otherwise, the new event can be merged: */ ! 153: else { ! 154: ! 155: /* merge the event: */ ! 156: /* XXX FIXME - we should check for integer overflow here: */ ! 157: event_last->tme_mouse_event_delta_x += event->tme_mouse_event_delta_x; ! 158: event_last->tme_mouse_event_delta_y += event->tme_mouse_event_delta_y; ! 159: event_last->tme_mouse_event_time = event->tme_mouse_event_time; ! 160: return (TME_OK); ! 161: } ! 162: } ! 163: 1.1 root 164: /* if the buffer is full: */ 165: if (((buffer_head + 1) & buffer_size_mask) 166: == buffer->tme_mouse_buffer_tail) { 167: return (EAGAIN); 168: } 169: 170: /* put this event into the buffer: */ 171: buffer->tme_mouse_buffer_events[buffer_head] 172: = *event; 173: 174: /* advance the head: */ 175: buffer->tme_mouse_buffer_head 176: = (buffer_head + 1) & buffer_size_mask; 177: 178: return (TME_OK); 179: } 180: 181: /* this copies an event out of a mouse buffer: */ 182: int 183: tme_mouse_buffer_copyout(struct tme_mouse_buffer *buffer, 184: struct tme_mouse_event *events, 185: unsigned int count) 186: { 187: unsigned int buffer_head, buffer_tail; 188: unsigned int buffer_size, buffer_size_mask; 189: unsigned int resid; 190: 191: /* get the head, tail, and size mask: */ 192: buffer_head = buffer->tme_mouse_buffer_head; 193: buffer_tail = buffer->tme_mouse_buffer_tail; 194: buffer_size_mask = buffer->tme_mouse_buffer_size - 1; 195: 196: for (resid = count; resid > 0; ) { 197: 198: /* if the buffer is empty: */ 199: if (buffer_tail == buffer->tme_mouse_buffer_head) { 200: 201: /* we're done copying out: */ 202: break; 203: } 204: 205: /* otherwise, the buffer is not empty, meaning there is always some 206: data starting at the buffer tail. if the buffer tail > the 207: buffer head, there is space from the buffer tail up to the end 208: of the buffer, otherwise there is space from the buffer tail up 209: to the buffer head: */ 210: buffer_size = ((buffer_tail > buffer_head) 211: ? (buffer_size_mask - buffer_tail) + 1 212: : (buffer_head - buffer_tail)); 213: 214: /* don't copy out more data than there is space available: */ 215: buffer_size = TME_MIN(buffer_size, resid); 216: assert(buffer_size > 0); 217: 218: /* copy out the data: */ 219: memcpy(events, 220: buffer->tme_mouse_buffer_events + buffer_tail, 221: sizeof(struct tme_mouse_event) * buffer_size); 222: events += buffer_size; 223: 224: /* update and loop: */ 225: buffer_tail = (buffer_tail + buffer_size) & buffer_size_mask; 226: resid -= buffer_size; 227: } 228: 229: buffer->tme_mouse_buffer_tail = buffer_tail; 230: return (count - resid); 231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.