src/video/x11/SDL_x11wm.c

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

FUNCTIONS

This source file includes following functions.
  1. X11_SetIcon
  2. X11_SetCaption
  3. X11_IconifyWindow
  4. X11_GrabInputNoLock
  5. X11_GrabInput
  6. lock_display
  7. unlock_display
  8. X11_GetWMInfo

   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_x11wm.c,v 1.2.2.14 2001/03/21 18:39:51 hercules Exp $";
  26 #endif
  27 
  28 #include <stdlib.h>
  29 #include <string.h>
  30 #include <X11/Xlib.h>
  31 #include <X11/Xutil.h>
  32 
  33 #include "SDL_version.h"
  34 #include "SDL_error.h"
  35 #include "SDL_timer.h"
  36 #include "SDL_video.h"
  37 #include "SDL_syswm.h"
  38 #include "SDL_events_c.h"
  39 #include "SDL_pixels_c.h"
  40 #include "SDL_x11modes_c.h"
  41 #include "SDL_x11wm_c.h"
  42 
  43 /* This is necessary for working properly with Enlightenment, etc. */
  44 #define USE_ICON_WINDOW
  45 
  46 void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         SDL_Surface *sicon;
  49         XWMHints *wmhints;
  50         XImage *icon_image;
  51         Pixmap icon_pixmap;
  52         Pixmap mask_pixmap;
  53 #ifdef USE_ICON_WINDOW
  54         Window icon_window;
  55 #endif
  56         GC GC;
  57         XGCValues GCvalues;
  58         int i, b, dbpp;
  59         SDL_Rect bounds;
  60         Uint8 *LSBmask, *color_tried;
  61         Visual *dvis;
  62 
  63         /* Lock the event thread, in multi-threading environments */
  64         SDL_Lock_EventThread();
  65 
  66         /* The icon must use the default visual, depth and colormap of the
  67            screen, so it might need a conversion */
  68         dbpp = DefaultDepth(SDL_Display, SDL_Screen);
  69         switch(dbpp) {
  70         case 15:
  71             dbpp = 16; break;
  72         case 24:
  73             dbpp = 32; break;
  74         }
  75         dvis = DefaultVisual(SDL_Display, SDL_Screen);
  76 
  77         /* The Visual struct is supposed to be opaque but we cheat a little */
  78         sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
  79                                      dbpp,
  80                                      dvis->red_mask, dvis->green_mask,
  81                                      dvis->blue_mask, 0);
  82 
  83         if ( sicon == NULL ) {
  84                 goto done;
  85         }
  86         /* If we already have allocated colours from the default colormap,
  87            copy them */
  88         if(SDL_Visual == dvis && SDL_XColorMap == SDL_DisplayColormap
  89            && this->screen->format->palette && sicon->format->palette) {
  90             memcpy(sicon->format->palette->colors,
  91                    this->screen->format->palette->colors,
  92                    this->screen->format->palette->ncolors * sizeof(SDL_Color));
  93         }
  94 
  95         bounds.x = 0;
  96         bounds.y = 0;
  97         bounds.w = icon->w;
  98         bounds.h = icon->h;
  99         if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 )
 100                 goto done;
 101 
 102         /* Lock down the colors used in the colormap */
 103         color_tried = NULL;
 104         if ( sicon->format->BitsPerPixel == 8 ) {
 105                 SDL_Palette *palette;
 106                 Uint8 *p;
 107                 XColor wanted;
 108 
 109                 palette = sicon->format->palette;
 110                 color_tried = malloc(palette->ncolors);
 111                 if ( color_tried == NULL ) {
 112                         goto done;
 113                 }
 114                 if ( SDL_iconcolors != NULL ) {
 115                         free(SDL_iconcolors);
 116                 }
 117                 SDL_iconcolors = malloc(palette->ncolors
 118                                         * sizeof(*SDL_iconcolors));
 119                 if ( SDL_iconcolors == NULL ) {
 120                         free(color_tried);
 121                         goto done;
 122                 }
 123                 memset(color_tried, 0, palette->ncolors);
 124                 memset(SDL_iconcolors, 0,
 125                        palette->ncolors * sizeof(*SDL_iconcolors));
 126 
 127                 p = (Uint8 *)sicon->pixels; 
 128                 for ( i = sicon->w*sicon->h; i > 0; --i, ++p ) {
 129                         if ( ! color_tried[*p] ) {
 130                                 wanted.pixel = *p;
 131                                 wanted.red   = (palette->colors[*p].r<<8);
 132                                 wanted.green = (palette->colors[*p].g<<8);
 133                                 wanted.blue  = (palette->colors[*p].b<<8);
 134                                 wanted.flags = (DoRed|DoGreen|DoBlue);
 135                                 if (XAllocColor(SDL_Display,
 136                                                 SDL_DisplayColormap, &wanted)) {
 137                                         ++SDL_iconcolors[wanted.pixel];
 138                                 }
 139                                 color_tried[*p] = 1;
 140                         }
 141                 }
 142         }
 143         if ( color_tried != NULL ) {
 144                 free(color_tried);
 145         }
 146 
 147         /* Translate mask data to LSB order and set the icon mask */
 148         i = (sicon->w/8)*sicon->h;
 149         LSBmask = (Uint8 *)malloc(i);
 150         if ( LSBmask == NULL ) {
 151                 goto done;
 152         }
 153         memset(LSBmask, 0, i);
 154         while ( --i >= 0 ) {
 155                 for ( b=0; b<8; ++b )
 156                         LSBmask[i] |= (((mask[i]>>b)&0x01)<<(7-b));
 157         }
 158         mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow,
 159                           (char *)LSBmask, sicon->w, sicon->h, 1L, 0L, 1);
 160 
 161         /* Transfer the image to an X11 pixmap */
 162         icon_image = XCreateImage(SDL_Display,
 163                         DefaultVisual(SDL_Display, SDL_Screen),
 164                         DefaultDepth(SDL_Display, SDL_Screen),
 165                         ZPixmap, 0, (char *)sicon->pixels, sicon->w, sicon->h,
 166                         ((sicon->format)->BytesPerPixel == 3) ? 32 :
 167                                 (sicon->format)->BytesPerPixel*8, 0);
 168         icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h,
 169                         DefaultDepth(SDL_Display, SDL_Screen));
 170         GC = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues);
 171         XPutImage(SDL_Display, icon_pixmap, GC, icon_image,
 172                                         0, 0, 0, 0, sicon->w, sicon->h);
 173         XFreeGC(SDL_Display, GC);
 174         XDestroyImage(icon_image);
 175         free(LSBmask);
 176         sicon->pixels = NULL;
 177 
 178 #ifdef USE_ICON_WINDOW
 179         /* Create an icon window and set the pixmap as its background */
 180         icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root,
 181                                         0, 0, sicon->w, sicon->h, 0,
 182                                         CopyFromParent, CopyFromParent);
 183         XSetWindowBackgroundPixmap(SDL_Display, icon_window, icon_pixmap);
 184         XClearWindow(SDL_Display, icon_window);
 185 #endif
 186 
 187         /* Set the window icon to the icon pixmap (and icon window) */
 188         wmhints = XAllocWMHints();
 189         wmhints->flags = (IconPixmapHint | IconMaskHint);
 190         wmhints->icon_pixmap = icon_pixmap;
 191         wmhints->icon_mask = mask_pixmap;
 192 #ifdef USE_ICON_WINDOW
 193         wmhints->flags |= IconWindowHint;
 194         wmhints->icon_window = icon_window;
 195 #endif
 196         XSetWMHints(SDL_Display, WMwindow, wmhints);
 197         XFree(wmhints);
 198         XSync(SDL_Display, False);
 199 
 200   done:
 201         SDL_Unlock_EventThread();
 202         if ( sicon != NULL ) {
 203                 SDL_FreeSurface(sicon);
 204         }
 205         return;
 206 }
 207 
 208 void X11_SetCaption(_THIS, const char *title, const char *icon)
     /* [<][>][^][v][top][bottom][index][help] */
 209 {
 210         XTextProperty titleprop, iconprop;
 211 
 212         /* Lock the event thread, in multi-threading environments */
 213         SDL_Lock_EventThread();
 214 
 215         if ( title != NULL ) {
 216                 XStringListToTextProperty((char **)&title, 1, &titleprop);
 217                 XSetWMName(SDL_Display, WMwindow, &titleprop);
 218                 XFree(titleprop.value);
 219         }
 220         if ( icon != NULL ) {
 221                 XStringListToTextProperty((char **)&icon, 1, &iconprop);
 222                 XSetWMIconName(SDL_Display, WMwindow, &iconprop);
 223                 XFree(iconprop.value);
 224         }
 225         XSync(SDL_Display, False);
 226 
 227         SDL_Unlock_EventThread();
 228 }
 229 
 230 /* Iconify the window */
 231 int X11_IconifyWindow(_THIS)
     /* [<][>][^][v][top][bottom][index][help] */
 232 {
 233         int result;
 234 
 235         SDL_Lock_EventThread();
 236         result = XIconifyWindow(SDL_Display, WMwindow, SDL_Screen);
 237         XSync(SDL_Display, False);
 238         SDL_Unlock_EventThread();
 239         return(result);
 240 }
 241 
 242 SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode)
     /* [<][>][^][v][top][bottom][index][help] */
 243 {
 244         int numtries, result;
 245 
 246         if ( this->screen == NULL ) {
 247                 return(SDL_GRAB_OFF);
 248         }
 249         if ( ! SDL_Window ) {
 250                 return(mode);   /* Will be set later on mode switch */
 251         }
 252         if ( mode == SDL_GRAB_OFF ) {
 253                 XUngrabPointer(SDL_Display, CurrentTime);
 254                 if ( this->screen->flags & SDL_FULLSCREEN ) {
 255                         /* Rebind the mouse to the fullscreen window */
 256                         for ( numtries = 0; numtries < 10; ++numtries ) {
 257                                 result = XGrabPointer(SDL_Display, FSwindow,
 258                                                 True, 0,
 259                                                 GrabModeAsync, GrabModeAsync,
 260                                                 FSwindow, None, CurrentTime);
 261                                 if ( result == AlreadyGrabbed ) {
 262                                         break;
 263                                 }
 264                                 SDL_Delay(100);
 265                         }
 266                 }
 267 #ifdef GRAB_FULLSCREEN
 268                 if ( !(this->screen->flags & SDL_FULLSCREEN) )
 269 #endif
 270                 XUngrabKeyboard(SDL_Display, CurrentTime);
 271         } else {
 272                 if ( this->screen->flags & SDL_FULLSCREEN ) {
 273                         /* Unbind the mouse from the fullscreen window */
 274                         XUngrabPointer(SDL_Display, CurrentTime);
 275                 }
 276                 /* Try to grab the mouse */
 277                 for ( numtries = 0; numtries < 10; ++numtries ) {
 278                         result = XGrabPointer(SDL_Display, SDL_Window, True, 0,
 279                                                 GrabModeAsync, GrabModeAsync,
 280                                                 SDL_Window, None, CurrentTime);
 281                         if ( result != AlreadyGrabbed ) {
 282                                 break;
 283                         }
 284                         SDL_Delay(100);
 285                 }
 286 #ifdef GRAB_FULLSCREEN
 287                 if ( !(this->screen->flags & SDL_FULLSCREEN) )
 288 #endif
 289                 XGrabKeyboard(SDL_Display, WMwindow, True,
 290                         GrabModeAsync, GrabModeAsync, CurrentTime);
 291 
 292                 /* Raise the window if we grab the mouse */
 293                 if ( !(this->screen->flags & SDL_FULLSCREEN) )
 294                         XRaiseWindow(SDL_Display, WMwindow);
 295         }
 296         XSync(SDL_Display, False);
 297 
 298         return(mode);
 299 }
 300 
 301 SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode)
     /* [<][>][^][v][top][bottom][index][help] */
 302 {
 303         SDL_Lock_EventThread();
 304         mode = X11_GrabInputNoLock(this, mode);
 305         SDL_Unlock_EventThread();
 306 
 307         return(mode);
 308 }
 309 
 310 /* If 'info' is the right version, this function fills it and returns 1.
 311    Otherwise, in case of a version mismatch, it returns -1.
 312 */
 313 static void lock_display(void)
     /* [<][>][^][v][top][bottom][index][help] */
 314 {
 315         SDL_Lock_EventThread();
 316 }
 317 static void unlock_display(void)
     /* [<][>][^][v][top][bottom][index][help] */
 318 {
 319         /* Make sure any X11 transactions are completed */
 320         SDL_VideoDevice *this = current_video;
 321         XSync(SDL_Display, False);
 322         SDL_Unlock_EventThread();
 323 }
 324 int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info)
     /* [<][>][^][v][top][bottom][index][help] */
 325 {
 326         if ( info->version.major <= SDL_MAJOR_VERSION ) {
 327                 info->subsystem = SDL_SYSWM_X11;
 328                 info->info.x11.display = SDL_Display;
 329                 info->info.x11.window = SDL_Window;
 330                 if ( SDL_VERSIONNUM(info->version.major,
 331                                     info->version.minor,
 332                                     info->version.patch) >= 1002 ) {
 333                         info->info.x11.fswindow = FSwindow;
 334                         info->info.x11.wmwindow = WMwindow;
 335                 }
 336                 info->info.x11.lock_func = lock_display;
 337                 info->info.x11.unlock_func = unlock_display;
 338                 return(1);
 339         } else {
 340                 SDL_SetError("Application not compiled with SDL %d.%d\n",
 341                                         SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
 342                 return(-1);
 343         }
 344 }

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