src/video/photon/SDL_ph_wm.c
author Sam Lantinga <slouken@lokigames.com>
Thu, 26 Apr 2001 16:45:43 +0000
changeset 0 74212992fb08
child 19 8cc4dbfab9ab
permissions -rw-r--r--
Initial revision
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@0
     3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@0
     6
    modify it under the terms of the GNU Library General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@0
     8
    version 2 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@0
    13
    Library General Public License for more details.
slouken@0
    14
slouken@0
    15
    You should have received a copy of the GNU Library General Public
slouken@0
    16
    License along with this library; if not, write to the Free
slouken@0
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@0
    20
    slouken@devolution.com
slouken@0
    21
*/
slouken@0
    22
slouken@0
    23
#ifdef SAVE_RCSID
slouken@0
    24
static char rcsid =
slouken@0
    25
 "@(#) $Id$";
slouken@0
    26
#endif
slouken@0
    27
slouken@0
    28
#include <stdlib.h>
slouken@0
    29
#include <string.h>
slouken@0
    30
#include <Ph.h>
slouken@0
    31
#include "SDL_version.h"
slouken@0
    32
#include "SDL_error.h"
slouken@0
    33
#include "SDL_timer.h"
slouken@0
    34
#include "SDL_video.h"
slouken@0
    35
#include "SDL_syswm.h"
slouken@0
    36
#include "SDL_events_c.h"
slouken@0
    37
#include "SDL_pixels_c.h"
slouken@0
    38
#include "SDL_ph_modes_c.h"
slouken@0
    39
#include "SDL_ph_wm_c.h"
slouken@0
    40
slouken@0
    41
/* This is necessary for working properly with Enlightenment, etc. */
slouken@0
    42
#define USE_ICON_WINDOW
slouken@0
    43
slouken@0
    44
void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
slouken@0
    45
{
slouken@0
    46
slouken@0
    47
#if 0 /*big*/
slouken@0
    48
	int ncolors;
slouken@0
    49
	PhImage_t *image;
slouken@0
    50
	PgColor_t* palette;
slouken@0
    51
slouken@0
    52
	image = PhCreateImage( image,
slouken@0
    53
                          	icon->w,
slouken@0
    54
                          	icon->h,
slouken@0
    55
                          	Pg_IMAGE_DIRECT_888,
slouken@0
    56
                          	NULL, 0, 0 );
slouken@0
    57
slouken@0
    58
/* ---------------------------------------- */
slouken@0
    59
	SDL_Surface *sicon;
slouken@0
    60
//	XWMHints *wmhints;
slouken@0
    61
//	XImage *icon_image;
slouken@0
    62
//	Pixmap icon_pixmap;
slouken@0
    63
//	Pixmap mask_pixmap;
slouken@0
    64
//	GC GC;
slouken@0
    65
//	XGCValues GCvalues;
slouken@0
    66
	int i, b, dbpp;
slouken@0
    67
	SDL_Rect bounds;
slouken@0
    68
	Uint8 *LSBmask, *color_tried;
slouken@0
    69
	Visual *dvis;
slouken@0
    70
slouken@0
    71
	/* Lock the event thread, in multi-threading environments */
slouken@0
    72
	SDL_Lock_EventThread();
slouken@0
    73
slouken@0
    74
	/* The icon must use the default visual, depth and colormap of the
slouken@0
    75
	   screen, so it might need a conversion */
slouken@0
    76
// ?	dbpp = DefaultDepth(SDL_Display, SDL_Screen);
slouken@0
    77
	switch(dbpp) {
slouken@0
    78
	case 15:
slouken@0
    79
	    dbpp = 16; break;
slouken@0
    80
	case 24:
slouken@0
    81
	    dbpp = 32; break;
slouken@0
    82
	}
slouken@0
    83
	dvis = DefaultVisual(SDL_Display, SDL_Screen);
slouken@0
    84
slouken@0
    85
	/* The Visual struct is supposed to be opaque but we cheat a little */
slouken@0
    86
	sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
slouken@0
    87
				     dbpp,
slouken@0
    88
				     dvis->red_mask, dvis->green_mask,
slouken@0
    89
				     dvis->blue_mask, 0);
slouken@0
    90
slouken@0
    91
	if ( sicon == NULL ) {
slouken@0
    92
		goto done;
slouken@0
    93
	}
slouken@0
    94
	/* If we already have allocated colours from the default colormap,
slouken@0
    95
	   copy them */
slouken@0
    96
	if(SDL_Visual == dvis && SDL_XColorMap == SDL_DisplayColormap
slouken@0
    97
	   && this->screen->format->palette && sicon->format->palette) {
slouken@0
    98
	    memcpy(sicon->format->palette->colors,
slouken@0
    99
		   this->screen->format->palette->colors,
slouken@0
   100
		   this->screen->format->palette->ncolors * sizeof(SDL_Color));
slouken@0
   101
	}
slouken@0
   102
slouken@0
   103
	bounds.x = 0;
slouken@0
   104
	bounds.y = 0;
slouken@0
   105
	bounds.w = icon->w;
slouken@0
   106
	bounds.h = icon->h;
slouken@0
   107
	if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 )
slouken@0
   108
		goto done;
slouken@0
   109
slouken@0
   110
	/* Lock down the colors used in the colormap */
slouken@0
   111
	color_tried = NULL;
slouken@0
   112
	if ( sicon->format->BitsPerPixel == 8 ) {
slouken@0
   113
		SDL_Palette *palette;
slouken@0
   114
		Uint8 *p;
slouken@0
   115
		XColor wanted;
slouken@0
   116
slouken@0
   117
		palette = sicon->format->palette;
slouken@0
   118
		color_tried = malloc(palette->ncolors);
slouken@0
   119
		if ( color_tried == NULL ) {
slouken@0
   120
			goto done;
slouken@0
   121
		}
slouken@0
   122
		if ( SDL_iconcolors != NULL ) {
slouken@0
   123
			free(SDL_iconcolors);
slouken@0
   124
		}
slouken@0
   125
		SDL_iconcolors = malloc(palette->ncolors
slouken@0
   126
					* sizeof(*SDL_iconcolors));
slouken@0
   127
		if ( SDL_iconcolors == NULL ) {
slouken@0
   128
			free(color_tried);
slouken@0
   129
			goto done;
slouken@0
   130
		}
slouken@0
   131
		memset(color_tried, 0, palette->ncolors);
slouken@0
   132
		memset(SDL_iconcolors, 0,
slouken@0
   133
		       palette->ncolors * sizeof(*SDL_iconcolors));
slouken@0
   134
slouken@0
   135
		p = (Uint8 *)sicon->pixels; 
slouken@0
   136
		for ( i = sicon->w*sicon->h; i > 0; --i, ++p ) {
slouken@0
   137
			if ( ! color_tried[*p] ) {
slouken@0
   138
				wanted.pixel = *p;
slouken@0
   139
				wanted.red   = (palette->colors[*p].r<<8);
slouken@0
   140
				wanted.green = (palette->colors[*p].g<<8);
slouken@0
   141
				wanted.blue  = (palette->colors[*p].b<<8);
slouken@0
   142
				wanted.flags = (DoRed|DoGreen|DoBlue);
slouken@0
   143
				if (XAllocColor(SDL_Display,
slouken@0
   144
						SDL_DisplayColormap, &wanted)) {
slouken@0
   145
					++SDL_iconcolors[wanted.pixel];
slouken@0
   146
				}
slouken@0
   147
				color_tried[*p] = 1;
slouken@0
   148
			}
slouken@0
   149
		}
slouken@0
   150
	}
slouken@0
   151
	if ( color_tried != NULL ) {
slouken@0
   152
		free(color_tried);
slouken@0
   153
	}
slouken@0
   154
slouken@0
   155
	/* Translate mask data to LSB order and set the icon mask */
slouken@0
   156
	i = (sicon->w/8)*sicon->h;
slouken@0
   157
	LSBmask = (Uint8 *)malloc(i);
slouken@0
   158
	if ( LSBmask == NULL ) {
slouken@0
   159
		goto done;
slouken@0
   160
	}
slouken@0
   161
	memset(LSBmask, 0, i);
slouken@0
   162
	while ( --i >= 0 ) {
slouken@0
   163
		for ( b=0; b<8; ++b )
slouken@0
   164
			LSBmask[i] |= (((mask[i]>>b)&0x01)<<(7-b));
slouken@0
   165
	}
slouken@0
   166
	mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow,
slouken@0
   167
					LSBmask, sicon->w, sicon->h, 1L, 0L, 1);
slouken@0
   168
slouken@0
   169
	/* Transfer the image to an X11 pixmap */
slouken@0
   170
	icon_image = XCreateImage(SDL_Display,
slouken@0
   171
			DefaultVisual(SDL_Display, SDL_Screen),
slouken@0
   172
			DefaultDepth(SDL_Display, SDL_Screen),
slouken@0
   173
			ZPixmap, 0, (char *)sicon->pixels, sicon->w, sicon->h,
slouken@0
   174
			((sicon->format)->BytesPerPixel == 3) ? 32 :
slouken@0
   175
				(sicon->format)->BytesPerPixel*8, 0);
slouken@0
   176
	icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h,
slouken@0
   177
			DefaultDepth(SDL_Display, SDL_Screen));
slouken@0
   178
	GC = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues);
slouken@0
   179
	XPutImage(SDL_Display, icon_pixmap, GC, icon_image,
slouken@0
   180
					0, 0, 0, 0, sicon->w, sicon->h);
slouken@0
   181
	XFreeGC(SDL_Display, GC);
slouken@0
   182
	XDestroyImage(icon_image);
slouken@0
   183
	free(LSBmask);
slouken@0
   184
	sicon->pixels = NULL;
slouken@0
   185
slouken@0
   186
#ifdef USE_ICON_WINDOW
slouken@0
   187
	/* Create an icon window and set the pixmap as its background */
slouken@0
   188
	icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root,
slouken@0
   189
					0, 0, sicon->w, sicon->h, 0,
slouken@0
   190
					CopyFromParent, CopyFromParent);
slouken@0
   191
	XSetWindowBackgroundPixmap(SDL_Display, icon_window, icon_pixmap);
slouken@0
   192
	XClearWindow(SDL_Display, icon_window);
slouken@0
   193
#endif
slouken@0
   194
slouken@0
   195
	/* Set the window icon to the icon pixmap (and icon window) */
slouken@0
   196
	wmhints = XAllocWMHints();
slouken@0
   197
	wmhints->flags = (IconPixmapHint | IconMaskHint);
slouken@0
   198
	wmhints->icon_pixmap = icon_pixmap;
slouken@0
   199
	wmhints->icon_mask = mask_pixmap;
slouken@0
   200
#ifdef USE_ICON_WINDOW
slouken@0
   201
	wmhints->flags |= IconWindowHint;
slouken@0
   202
	wmhints->icon_window = icon_window;
slouken@0
   203
#endif
slouken@0
   204
	XSetWMHints(SDL_Display, WMwindow, wmhints);
slouken@0
   205
	XFree(wmhints);
slouken@0
   206
	XSync(SDL_Display, False);
slouken@0
   207
slouken@0
   208
  done:
slouken@0
   209
	SDL_Unlock_EventThread();
slouken@0
   210
	if ( sicon != NULL ) {
slouken@0
   211
		SDL_FreeSurface(sicon);
slouken@0
   212
	}
slouken@0
   213
	
slouken@0
   214
#endif /*big*/
slouken@0
   215
	return;
slouken@0
   216
}
slouken@0
   217
slouken@0
   218
void ph_SetCaption(_THIS, const char *title, const char *icon)
slouken@0
   219
{
slouken@0
   220
slouken@0
   221
#if 0
slouken@0
   222
	XTextProperty titleprop, iconprop;
slouken@0
   223
slouken@0
   224
	/* Lock the event thread, in multi-threading environments */
slouken@0
   225
	SDL_Lock_EventThread();
slouken@0
   226
slouken@0
   227
	if ( title != NULL ) {
slouken@0
   228
		XStringListToTextProperty((char **)&title, 1, &titleprop);
slouken@0
   229
		XSetWMName(SDL_Display, WMwindow, &titleprop);
slouken@0
   230
		XFree(titleprop.value);
slouken@0
   231
	}
slouken@0
   232
	if ( icon != NULL ) {
slouken@0
   233
		XStringListToTextProperty((char **)&icon, 1, &iconprop);
slouken@0
   234
		XSetWMIconName(SDL_Display, WMwindow, &iconprop);
slouken@0
   235
		XFree(iconprop.value);
slouken@0
   236
	}
slouken@0
   237
	XSync(SDL_Display, False);
slouken@0
   238
slouken@0
   239
	SDL_Unlock_EventThread();
slouken@0
   240
#endif
slouken@0
   241
}
slouken@0
   242
slouken@0
   243
/* Iconify the window */
slouken@0
   244
int ph_IconifyWindow(_THIS)
slouken@0
   245
{
slouken@0
   246
	int result;
slouken@0
   247
	
slouken@0
   248
#if 0
slouken@0
   249
	SDL_Lock_EventThread();
slouken@0
   250
	result = XIconifyWindow(SDL_Display, WMwindow, SDL_Screen);
slouken@0
   251
	XSync(SDL_Display, False);
slouken@0
   252
	SDL_Unlock_EventThread();
slouken@0
   253
#endif
slouken@0
   254
	return(result);
slouken@0
   255
}
slouken@0
   256
slouken@0
   257
SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode)
slouken@0
   258
{
slouken@0
   259
#if 0 /*big*/
slouken@0
   260
	int numtries, result;
slouken@0
   261
slouken@0
   262
	if ( this->screen == NULL ) {
slouken@0
   263
		return(SDL_GRAB_OFF);
slouken@0
   264
	}
slouken@0
   265
	if ( ! SDL_Window ) {
slouken@0
   266
		return(mode);	/* Will be set later on mode switch */
slouken@0
   267
	}
slouken@0
   268
	if ( mode == SDL_GRAB_OFF ) {
slouken@0
   269
		XUngrabPointer(SDL_Display, CurrentTime);
slouken@0
   270
		if ( this->screen->flags & SDL_FULLSCREEN ) {
slouken@0
   271
			/* Rebind the mouse to the fullscreen window */
slouken@0
   272
			for ( numtries = 0; numtries < 10; ++numtries ) {
slouken@0
   273
				result = XGrabPointer(SDL_Display, FSwindow,
slouken@0
   274
						True, 0,
slouken@0
   275
						GrabModeAsync, GrabModeAsync,
slouken@0
   276
						FSwindow, None, CurrentTime);
slouken@0
   277
				if ( result == AlreadyGrabbed ) {
slouken@0
   278
					break;
slouken@0
   279
				}
slouken@0
   280
				SDL_Delay(100);
slouken@0
   281
			}
slouken@0
   282
		}
slouken@0
   283
#ifdef GRAB_FULLSCREEN
slouken@0
   284
		if ( !(this->screen->flags & SDL_FULLSCREEN) )
slouken@0
   285
#endif
slouken@0
   286
		XUngrabKeyboard(SDL_Display, CurrentTime);
slouken@0
   287
	} else {
slouken@0
   288
		if ( this->screen->flags & SDL_FULLSCREEN ) {
slouken@0
   289
			/* Unbind the mouse from the fullscreen window */
slouken@0
   290
			XUngrabPointer(SDL_Display, CurrentTime);
slouken@0
   291
		}
slouken@0
   292
		/* Try to grab the mouse */
slouken@0
   293
		for ( numtries = 0; numtries < 10; ++numtries ) {
slouken@0
   294
			result = XGrabPointer(SDL_Display, SDL_Window, True, 0,
slouken@0
   295
						GrabModeAsync, GrabModeAsync,
slouken@0
   296
						SDL_Window, None, CurrentTime);
slouken@0
   297
			if ( result != AlreadyGrabbed ) {
slouken@0
   298
				break;
slouken@0
   299
			}
slouken@0
   300
			SDL_Delay(100);
slouken@0
   301
		}
slouken@0
   302
#ifdef GRAB_FULLSCREEN
slouken@0
   303
		if ( !(this->screen->flags & SDL_FULLSCREEN) )
slouken@0
   304
#endif
slouken@0
   305
		XGrabKeyboard(SDL_Display, WMwindow, True,
slouken@0
   306
			GrabModeAsync, GrabModeAsync, CurrentTime);
slouken@0
   307
	}
slouken@0
   308
	XSync(SDL_Display, False);
slouken@0
   309
slouken@0
   310
slouken@0
   311
#endif /*big*/
slouken@0
   312
	return(mode);
slouken@0
   313
}
slouken@0
   314
slouken@0
   315
SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode)
slouken@0
   316
{
slouken@0
   317
#if 0
slouken@0
   318
	SDL_Lock_EventThread();
slouken@0
   319
	mode = X11_GrabInputNoLock(this, mode);
slouken@0
   320
	SDL_Unlock_EventThread();
slouken@0
   321
#endif
slouken@0
   322
	return(mode);
slouken@0
   323
}
slouken@0
   324
slouken@0
   325
/* If 'info' is the right version, this function fills it and returns 1.
slouken@0
   326
   Otherwise, in case of a version mismatch, it returns -1.
slouken@0
   327
*/
slouken@0
   328
static void lock_display(void)
slouken@0
   329
{
slouken@0
   330
	SDL_Lock_EventThread();
slouken@0
   331
}
slouken@0
   332
static void unlock_display(void)
slouken@0
   333
{
slouken@0
   334
#if 0
slouken@0
   335
	/* Make sure any X11 transactions are completed */
slouken@0
   336
	SDL_VideoDevice *this = current_video;
slouken@0
   337
	XSync(SDL_Display, False);
slouken@0
   338
	SDL_Unlock_EventThread();
slouken@0
   339
#endif
slouken@0
   340
}
slouken@0
   341
int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info)
slouken@0
   342
{
slouken@0
   343
#if 0
slouken@0
   344
	if ( info->version.major <= SDL_MAJOR_VERSION ) {
slouken@0
   345
		info->subsystem = SDL_SYSWM_X11;
slouken@0
   346
		info->info.x11.display = SDL_Display;
slouken@0
   347
		info->info.x11.window = SDL_Window;
slouken@0
   348
		if ( SDL_VERSIONNUM(info->version.major,
slouken@0
   349
		                    info->version.minor,
slouken@0
   350
		                    info->version.patch) >= 1002 ) {
slouken@0
   351
			info->info.x11.fswindow = FSwindow;
slouken@0
   352
			info->info.x11.wmwindow = WMwindow;
slouken@0
   353
		}
slouken@0
   354
		info->info.x11.lock_func = lock_display;
slouken@0
   355
		info->info.x11.unlock_func = unlock_display;
slouken@0
   356
		return(1);
slouken@0
   357
	} else {
slouken@0
   358
		SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@0
   359
					SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@0
   360
		return(-1);
slouken@0
   361
	}
slouken@0
   362
#endif
slouken@0
   363
}