Mercurial > sdl-ios-xcode
view src/video/x11/SDL_x11wm.c @ 914:bbf8dcc8aed6
Date: Wed, 23 Jun 2004 17:05:33 -0400
From: Chris Nelson
Subject: [SDL] [Patch] WiseGroup MP-8800 / MP-8866 (PS2 Joystick)
In the current cvs version, SDL doesn't handle these Playstation2
controller => USB adapters correctly, in linux.
It will always assume that the maximum number of joysticks (2 in the
case of the MP-8866, 4 in the case of the 8800) are plugged in. This is
bad not only because it allows SDL to exaggerate the number of logical
joysticks, but primarily because the joystick axes are mapped
incorrectly, all over the place, such that the devices are effectively
unusable unless you have the maximum number of joysticks plugged in.
My changes to src/joystick/linux/SDL_sysjoystick.c build on another's
previous work (which was a special case for this very joystick,
actually), and fix both of these problems, as well as making the current
code a little more general, to allow for others to more easily drop in
code for quirky joysticks such as these.
I've tested this code under 2.6.7 as well as 2.4.24... Both work as
advertised (provided you load the JOYDEV linux code as a module,
otherwise they won't work at all, new code or old, but that's another
issue entirely).
Though this sounds horribly formal, you have my permission to distribute
all of my work on this issue under the LGPL. So there.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 25 Jul 2004 18:31:50 +0000 |
parents | a7a8c282d62e |
children | 3acd16ea0180 |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2004 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org */ #ifdef SAVE_RCSID static char rcsid = "@(#) $Id$"; #endif #include <stdlib.h> #include <string.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include "SDL_version.h" #include "SDL_error.h" #include "SDL_timer.h" #include "SDL_video.h" #include "SDL_syswm.h" #include "SDL_events_c.h" #include "SDL_pixels_c.h" #include "SDL_x11modes_c.h" #include "SDL_x11wm_c.h" static Uint8 reverse_byte(Uint8 x) { x = (x & 0xaa) >> 1 | (x & 0x55) << 1; x = (x & 0xcc) >> 2 | (x & 0x33) << 2; x = (x & 0xf0) >> 4 | (x & 0x0f) << 4; return x; } void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) { SDL_Surface *sicon; XWMHints *wmhints; XImage *icon_image; Pixmap icon_pixmap; Pixmap mask_pixmap; Window icon_window = None; GC gc; XGCValues GCvalues; int i, dbpp; SDL_Rect bounds; Uint8 *LSBmask; Visual *dvis; char *p; int masksize; SDL_Lock_EventThread(); /* The icon must use the default visual, depth and colormap of the screen, so it might need a conversion */ dvis = DefaultVisual(SDL_Display, SDL_Screen); dbpp = DefaultDepth(SDL_Display, SDL_Screen); for(i = 0; i < this->hidden->nvisuals; i++) { if(this->hidden->visuals[i].visual == dvis) { dbpp = this->hidden->visuals[i].bpp; break; } } /* The Visual struct is supposed to be opaque but we cheat a little */ sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, dbpp, dvis->red_mask, dvis->green_mask, dvis->blue_mask, 0); if ( sicon == NULL ) goto done; if(dbpp == 8) { /* Default visual is 8bit; we need to allocate colours from the default colormap */ SDL_Color want[256], got[256]; int nwant; Colormap dcmap; int missing; dcmap = DefaultColormap(SDL_Display, SDL_Screen); if(icon->format->palette) { /* The icon has a palette as well - we just have to find those colours */ nwant = icon->format->palette->ncolors; memcpy(want, icon->format->palette->colors, nwant * sizeof want[0]); } else { /* try the standard 6x6x6 cube for lack of better ideas */ int r, g, b, i; for(r = i = 0; r < 256; r += 0x33) for(g = 0; g < 256; g += 0x33) for(b = 0; b < 256; b += 0x33, i++) { want[i].r = r; want[i].g = g; want[i].b = b; } nwant = 216; } if(SDL_iconcolors) { /* free already allocated colours first */ unsigned long freelist[512]; int nfree = 0; for(i = 0; i < 256; i++) { while(SDL_iconcolors[i]) { freelist[nfree++] = i; SDL_iconcolors[i]--; } } XFreeColors(GFX_Display, dcmap, freelist, nfree, 0); } if(!SDL_iconcolors) SDL_iconcolors = malloc(256 * sizeof *SDL_iconcolors); memset(SDL_iconcolors, 0, 256 * sizeof *SDL_iconcolors); /* try to allocate the colours */ memset(got, 0, sizeof got); missing = 0; for(i = 0; i < nwant; i++) { XColor c; c.red = want[i].r << 8; c.green = want[i].g << 8; c.blue = want[i].b << 8; c.flags = DoRed | DoGreen | DoBlue; if(XAllocColor(GFX_Display, dcmap, &c)) { /* got the colour */ SDL_iconcolors[c.pixel]++; got[c.pixel] = want[i]; } else { missing = 1; } } if(missing) { /* Some colours were apparently missing, so we just allocate all the rest as well */ XColor cols[256]; for(i = 0; i < 256; i++) cols[i].pixel = i; XQueryColors(GFX_Display, dcmap, cols, 256); for(i = 0; i < 256; i++) { got[i].r = cols[i].red >> 8; got[i].g = cols[i].green >> 8; got[i].b = cols[i].blue >> 8; if(!SDL_iconcolors[i]) { if(XAllocColor(GFX_Display, dcmap, cols + i)) { SDL_iconcolors[i] = 1; } else { /* index not available */ got[i].r = 0; got[i].g = 0; got[i].b = 0; } } } } SDL_SetColors(sicon, got, 0, 256); } bounds.x = 0; bounds.y = 0; bounds.w = icon->w; bounds.h = icon->h; if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) goto done; /* We need the mask as given, except in LSBfirst format instead of MSBfirst. Reverse the bits in each byte. */ masksize = ((sicon->w + 7) >> 3) * sicon->h; LSBmask = malloc(masksize); if ( LSBmask == NULL ) { goto done; } memset(LSBmask, 0, masksize); for(i = 0; i < masksize; i++) LSBmask[i] = reverse_byte(mask[i]); mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow, (char *)LSBmask, sicon->w, sicon->h, 1L, 0L, 1); /* Transfer the image to an X11 pixmap */ icon_image = XCreateImage(SDL_Display, DefaultVisual(SDL_Display, SDL_Screen), DefaultDepth(SDL_Display, SDL_Screen), ZPixmap, 0, sicon->pixels, sicon->w, sicon->h, 32, 0); icon_image->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? MSBFirst : LSBFirst; icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h, DefaultDepth(SDL_Display, SDL_Screen)); gc = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues); XPutImage(SDL_Display, icon_pixmap, gc, icon_image, 0, 0, 0, 0, sicon->w, sicon->h); XFreeGC(SDL_Display, gc); XDestroyImage(icon_image); free(LSBmask); sicon->pixels = NULL; /* Some buggy window managers (some versions of Enlightenment, it seems) need an icon window *and* icon pixmap to work properly, while it screws up others. The default is only to use a pixmap. */ p = getenv("SDL_VIDEO_X11_ICONWIN"); if(p && *p) { icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root, 0, 0, sicon->w, sicon->h, 0, CopyFromParent, CopyFromParent); XSetWindowBackgroundPixmap(SDL_Display, icon_window, icon_pixmap); XClearWindow(SDL_Display, icon_window); } /* Set the window icon to the icon pixmap (and icon window) */ wmhints = XAllocWMHints(); wmhints->flags = (IconPixmapHint | IconMaskHint); wmhints->icon_pixmap = icon_pixmap; wmhints->icon_mask = mask_pixmap; if(icon_window != None) { wmhints->flags |= IconWindowHint; wmhints->icon_window = icon_window; } XSetWMHints(SDL_Display, WMwindow, wmhints); XFree(wmhints); XSync(SDL_Display, False); done: SDL_Unlock_EventThread(); SDL_FreeSurface(sicon); } void X11_SetCaption(_THIS, const char *title, const char *icon) { XTextProperty titleprop, iconprop; /* Lock the event thread, in multi-threading environments */ SDL_Lock_EventThread(); if ( title != NULL ) { #ifdef X_HAVE_UTF8_STRING Xutf8TextListToTextProperty(SDL_Display, (char **)&title, 1, XUTF8StringStyle, &titleprop); #else XStringListToTextProperty((char **)&title, 1, &titleprop); #endif XSetWMName(SDL_Display, WMwindow, &titleprop); XFree(titleprop.value); } if ( icon != NULL ) { #ifdef X_HAVE_UTF8_STRING Xutf8TextListToTextProperty(SDL_Display, (char **)&icon, 1, XUTF8StringStyle, &iconprop); #else XStringListToTextProperty((char **)&icon, 1, &iconprop); #endif XSetWMIconName(SDL_Display, WMwindow, &iconprop); XFree(iconprop.value); } XSync(SDL_Display, False); SDL_Unlock_EventThread(); } /* Iconify the window */ int X11_IconifyWindow(_THIS) { int result; SDL_Lock_EventThread(); result = XIconifyWindow(SDL_Display, WMwindow, SDL_Screen); XSync(SDL_Display, False); SDL_Unlock_EventThread(); return(result); } SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode) { int result; if ( this->screen == NULL ) { return(SDL_GRAB_OFF); } if ( ! SDL_Window ) { return(mode); /* Will be set later on mode switch */ } if ( mode == SDL_GRAB_OFF ) { XUngrabPointer(SDL_Display, CurrentTime); XUngrabKeyboard(SDL_Display, CurrentTime); } else { if ( this->screen->flags & SDL_FULLSCREEN ) { /* Unbind the mouse from the fullscreen window */ XUngrabPointer(SDL_Display, CurrentTime); } /* Try to grab the mouse */ #if 0 /* We'll wait here until we actually grab, otherwise behavior undefined */ for ( numtries = 0; numtries < 10; ++numtries ) { #else while ( 1 ) { #endif result = XGrabPointer(SDL_Display, SDL_Window, True, 0, GrabModeAsync, GrabModeAsync, SDL_Window, None, CurrentTime); if ( result == GrabSuccess ) { break; } SDL_Delay(100); } if ( result != GrabSuccess ) { /* Uh, oh, what do we do here? */ ; } /* Now grab the keyboard */ XGrabKeyboard(SDL_Display, WMwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime); /* Raise the window if we grab the mouse */ if ( !(this->screen->flags & SDL_FULLSCREEN) ) XRaiseWindow(SDL_Display, WMwindow); /* Make sure we register input focus */ SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); } XSync(SDL_Display, False); return(mode); } SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode) { SDL_Lock_EventThread(); mode = X11_GrabInputNoLock(this, mode); SDL_Unlock_EventThread(); return(mode); } /* If 'info' is the right version, this function fills it and returns 1. Otherwise, in case of a version mismatch, it returns -1. */ static void lock_display(void) { SDL_Lock_EventThread(); } static void unlock_display(void) { /* Make sure any X11 transactions are completed */ SDL_VideoDevice *this = current_video; XSync(SDL_Display, False); SDL_Unlock_EventThread(); } int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info) { if ( info->version.major <= SDL_MAJOR_VERSION ) { info->subsystem = SDL_SYSWM_X11; info->info.x11.display = SDL_Display; info->info.x11.window = SDL_Window; if ( SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch) >= 1002 ) { info->info.x11.fswindow = FSwindow; info->info.x11.wmwindow = WMwindow; } info->info.x11.lock_func = lock_display; info->info.x11.unlock_func = unlock_display; return(1); } else { SDL_SetError("Application not compiled with SDL %d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION); return(-1); } }