src/video/x11/SDL_x11mouse.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. X11_FreeWMCursor
  2. X11_CreateWMCursor
  3. X11_ShowWMCursor
  4. X11_WarpWMCursor
  5. SetMouseAccel
  6. X11_CheckMouseModeNoLock
  7. X11_CheckMouseMode

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_x11mouse.c,v 1.4.2.13 2001/02/10 07:20:15 hercules Exp $";
  26 #endif
  27 
  28 #include <stdlib.h>
  29 #include <stdio.h>
  30 #include <string.h>
  31 
  32 #include <X11/Xlib.h>
  33 #include <X11/Xutil.h>
  34 
  35 #include "SDL_error.h"
  36 #include "SDL_mouse.h"
  37 #include "SDL_events_c.h"
  38 #include "SDL_cursor_c.h"
  39 #include "SDL_x11dga_c.h"
  40 #include "SDL_x11mouse_c.h"
  41 
  42 
  43 /* The implementation dependent data for the window manager cursor */
  44 struct WMcursor {
  45         Cursor x_cursor;
  46 };
  47 
  48 
  49 void X11_FreeWMCursor(_THIS, WMcursor *cursor)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         if ( SDL_Display != NULL ) {
  52                 SDL_Lock_EventThread();
  53                 XFreeCursor(SDL_Display, cursor->x_cursor);
  54                 XSync(SDL_Display, False);
  55                 SDL_Unlock_EventThread();
  56         }
  57         free(cursor);
  58 }
  59 
  60 WMcursor *X11_CreateWMCursor(_THIS,
     /* [<][>][^][v][top][bottom][index][help] */
  61                 Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  62 {
  63         WMcursor *cursor;
  64         XGCValues GCvalues;
  65         GC        GCcursor;
  66         XImage *data_image, *mask_image;
  67         Pixmap  data_pixmap, mask_pixmap;
  68         int       clen, i;
  69         char     *x_data, *x_mask;
  70         static XColor black = {  0,  0,  0,  0 };
  71         static XColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
  72 
  73         /* Allocate the cursor memory */
  74         cursor = (WMcursor *)malloc(sizeof(WMcursor));
  75         if ( cursor == NULL ) {
  76                 SDL_OutOfMemory();
  77                 return(NULL);
  78         }
  79 
  80         /* Mix the mask and the data */
  81         clen = (w/8)*h;
  82         x_data = (char *)malloc(clen);
  83         if ( x_data == NULL ) {
  84                 free(cursor);
  85                 SDL_OutOfMemory();
  86                 return(NULL);
  87         }
  88         x_mask = (char *)malloc(clen);
  89         if ( x_mask == NULL ) {
  90                 free(cursor);
  91                 free(x_data);
  92                 SDL_OutOfMemory();
  93                 return(NULL);
  94         }
  95         for ( i=0; i<clen; ++i ) {
  96                 /* The mask is OR'd with the data to turn inverted color
  97                    pixels black since inverted color cursors aren't supported
  98                    under X11.
  99                  */
 100                 x_mask[i] = data[i] | mask[i];
 101                 x_data[i] = data[i];
 102         }
 103 
 104         /* Prevent the event thread from running while we use the X server */
 105         SDL_Lock_EventThread();
 106 
 107         /* Create the data image */
 108         data_image = XCreateImage(SDL_Display, 
 109                         DefaultVisual(SDL_Display, SDL_Screen),
 110                                         1, XYBitmap, 0, x_data, w, h, 8, w/8);
 111         data_image->byte_order = MSBFirst;
 112         data_image->bitmap_bit_order = MSBFirst;
 113         data_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1);
 114 
 115         /* Create the data mask */
 116         mask_image = XCreateImage(SDL_Display, 
 117                         DefaultVisual(SDL_Display, SDL_Screen),
 118                                         1, XYBitmap, 0, x_mask, w, h, 8, w/8);
 119         mask_image->byte_order = MSBFirst;
 120         mask_image->bitmap_bit_order = MSBFirst;
 121         mask_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1);
 122 
 123         /* Create the graphics context */
 124         GCvalues.function = GXcopy;
 125         GCvalues.foreground = ~0;
 126         GCvalues.background =  0;
 127         GCvalues.plane_mask = AllPlanes;
 128         GCcursor = XCreateGC(SDL_Display, data_pixmap,
 129                         (GCFunction|GCForeground|GCBackground|GCPlaneMask),
 130                                                                 &GCvalues);
 131 
 132         /* Blit the images to the pixmaps */
 133         XPutImage(SDL_Display, data_pixmap, GCcursor, data_image,
 134                                                         0, 0, 0, 0, w, h);
 135         XPutImage(SDL_Display, mask_pixmap, GCcursor, mask_image,
 136                                                         0, 0, 0, 0, w, h);
 137         XFreeGC(SDL_Display, GCcursor);
 138         /* These free the x_data and x_mask memory pointers */
 139         XDestroyImage(data_image);
 140         XDestroyImage(mask_image);
 141 
 142         /* Create the cursor */
 143         cursor->x_cursor = XCreatePixmapCursor(SDL_Display, data_pixmap,
 144                                 mask_pixmap, &black, &white, hot_x, hot_y);
 145 
 146         /* Release the event thread */
 147         XSync(SDL_Display, False);
 148         SDL_Unlock_EventThread();
 149 
 150         return(cursor);
 151 }
 152 
 153 int X11_ShowWMCursor(_THIS, WMcursor *cursor)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         /* Don't do anything if the display is gone */
 156         if ( SDL_Display == NULL ) {
 157                 return(0);
 158         }
 159 
 160         /* Set the X11 cursor cursor, or blank if cursor is NULL */
 161         if ( SDL_Window ) {
 162                 SDL_Lock_EventThread();
 163                 if ( cursor == NULL ) {
 164                         if ( SDL_BlankCursor != NULL ) {
 165                                 XDefineCursor(SDL_Display, SDL_Window,
 166                                         SDL_BlankCursor->x_cursor);
 167                         }
 168                 } else {
 169                         XDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor);
 170                 }
 171                 XSync(SDL_Display, False);
 172                 SDL_Unlock_EventThread();
 173         }
 174         return(1);
 175 }
 176 
 177 void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
     /* [<][>][^][v][top][bottom][index][help] */
 178 {
 179         if ( using_dga & DGA_MOUSE ) {
 180                 x += (this->screen->offset % this->screen->pitch) /
 181                       this->screen->format->BytesPerPixel;
 182                 y += (this->screen->offset / this->screen->pitch);
 183                 SDL_PrivateMouseMotion(0, 0, x, y);
 184         } else {
 185                 SDL_Lock_EventThread();
 186                 XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y);
 187                 XSync(SDL_Display, False);
 188                 SDL_Unlock_EventThread();
 189         }
 190 }
 191 
 192 /* Sets the mouse acceleration from a string of the form:
 193         2/1/0
 194    The first number is the numerator, followed by the acceleration
 195    denumenator and threshold.
 196 */
 197 static void SetMouseAccel(_THIS, const char *accel_param)
     /* [<][>][^][v][top][bottom][index][help] */
 198 {
 199         int i;
 200         int accel_value[3];
 201         char *mouse_param, *mouse_param_buf, *pin;
 202 
 203         mouse_param_buf = (char *)malloc(strlen(accel_param)+1);
 204         if ( ! mouse_param_buf ) {
 205                 return;
 206         }
 207         strcpy(mouse_param_buf, accel_param);
 208         mouse_param = mouse_param_buf;
 209 
 210         for ( i=0; (i < 3) && mouse_param; ++i ) {
 211                 pin = strchr(mouse_param, '/');
 212                 if ( pin ) {
 213                         *pin = '\0';
 214                 }
 215                 accel_value[i] = atoi(mouse_param);
 216                 if ( pin ) {
 217                         mouse_param = pin+1;
 218                 } else {
 219                         mouse_param = NULL;
 220                 }
 221         }
 222         if ( mouse_param_buf ) {
 223                 XChangePointerControl(SDL_Display, True, True,
 224                         accel_value[0], accel_value[1], accel_value[2]);
 225                 free(mouse_param_buf);
 226         }
 227 }
 228 
 229 /* Check to see if we need to enter or leave mouse relative mode */
 230 void X11_CheckMouseModeNoLock(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 231 {
 232         /* If the mouse is hidden and input is grabbed, we use relative mode */
 233         if ( !(SDL_cursorstate & CURSOR_VISIBLE) &&
 234              (this->input_grab != SDL_GRAB_OFF) &&
 235              (SDL_GetAppState() & SDL_APPACTIVE) ) {
 236                 if ( ! mouse_relative ) {
 237                         X11_EnableDGAMouse(this);
 238                         if ( ! (using_dga & DGA_MOUSE) ) {
 239                                 char *xmouse_accel;
 240 
 241                                 SDL_GetMouseState(&mouse_last.x, &mouse_last.y);
 242                                 /* Use as raw mouse mickeys as possible */
 243                                 XGetPointerControl(SDL_Display,
 244                                                 &mouse_accel.numerator, 
 245                                                 &mouse_accel.denominator,
 246                                                 &mouse_accel.threshold);
 247                                 xmouse_accel=getenv("SDL_VIDEO_X11_MOUSEACCEL");
 248                                 if ( xmouse_accel ) {
 249                                         SetMouseAccel(this, xmouse_accel);
 250                                 }
 251                         }
 252                         mouse_relative = 1;
 253                 }
 254         } else {
 255                 if ( mouse_relative ) {
 256                         if ( using_dga & DGA_MOUSE ) {
 257                                 X11_DisableDGAMouse(this);
 258                         } else {
 259                                 XChangePointerControl(SDL_Display, True, True,
 260                                                 mouse_accel.numerator, 
 261                                                 mouse_accel.denominator,
 262                                                 mouse_accel.threshold);
 263                         }
 264                         mouse_relative = 0;
 265                 }
 266         }
 267 }
 268 void X11_CheckMouseMode(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 269 {
 270         SDL_Lock_EventThread();
 271         X11_CheckMouseModeNoLock(this);
 272         SDL_Unlock_EventThread();
 273 }

/* [<][>][^][v][top][bottom][index][help] */