Update to MPlayer SVN rev 29473 and FFmpeg SVN rev 19572.
[vaapi:athaifas-mplayer.git] / gui / wm / .svn / text-base / ws.c.svn-base
1 /*
2  * AutoSpace Window System for Linux/Win32 v0.85
3  * written by pontscho/fresh!mindworkz
4  *
5  * This file is part of MPlayer.
6  *
7  * MPlayer is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * MPlayer is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <X11/Xlib.h>
23 #include <X11/Xproto.h>
24 #include <X11/Xutil.h>
25 #include <X11/keysym.h>
26 #include <X11/Xatom.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33
34 #include <inttypes.h>
35
36 #include "config.h"
37 #include "libvo/x11_common.h"
38 #include "libvo/video_out.h"
39 #include "cpudetect.h"
40 #include "libswscale/swscale.h"
41 #include "libswscale/rgb2rgb.h"
42 #include "libmpcodecs/vf_scale.h"
43 #include "mp_msg.h"
44 #include "help_mp.h"
45 #include "mplayer.h"
46 #include "mpbswap.h"
47 #include "ws.h"
48 #include "wsxdnd.h"
49
50 #include <X11/extensions/XShm.h>
51 #ifdef CONFIG_XSHAPE
52 #include <X11/extensions/shape.h>
53 #endif
54
55 #ifdef CONFIG_XINERAMA
56 #include <X11/extensions/Xinerama.h>
57 #endif
58
59 #ifdef CONFIG_XF86VM
60 #include <X11/extensions/xf86vmode.h>
61 #endif
62
63 #include <sys/ipc.h>
64 #include <sys/shm.h>
65
66 #undef ENABLE_DPMS
67
68 typedef struct
69 {
70  unsigned long flags;
71  unsigned long functions;
72  unsigned long decorations;
73  long input_mode;
74  unsigned long status;
75 } MotifWmHints;
76
77 Atom                 wsMotifHints;
78
79 int                  wsMaxX         = 0; // Screen width.
80 int                  wsMaxY         = 0; // Screen height.
81 int                  wsOrgX         = 0; // Screen origin x.
82 int                  wsOrgY         = 0; // Screen origin y.
83
84 Display            * wsDisplay;
85 int                  wsScreen;
86 Window               wsRootWin;
87 XEvent               wsEvent;
88 int                  wsWindowDepth;
89 GC                   wsHGC;
90 MotifWmHints         wsMotifWmHints;
91 Atom                 wsTextProperlyAtom = None;
92 int                  wsLayer = 0;
93
94 int                  wsDepthOnScreen = 0;
95 int                  wsRedMask = 0;
96 int                  wsGreenMask = 0;
97 int                  wsBlueMask = 0;
98 int                  wsOutMask = 0;
99 int                  wsNonNativeOrder = 0;
100
101 int                  wsTrue    = True;
102
103 #define wsWLCount 5
104 wsTWindow          * wsWindowList[wsWLCount] = { NULL,NULL,NULL,NULL,NULL };
105
106 unsigned long        wsKeyTable[512];
107
108 int                  wsUseXShm = 1;
109 int                  wsUseXShape = 1;
110
111 inline int wsSearch( Window win );
112
113 // ---
114
115 #define PACK_RGB16(r,g,b,pixel) pixel=(b>>3);\
116                                 pixel<<=6;\
117                                 pixel|=(g>>2);\
118                                 pixel<<=5;\
119                                 pixel|=(r>>3)
120
121 #define PACK_RGB15(r,g,b,pixel) pixel=(b>>3);\
122                                 pixel<<=5;\
123                                 pixel|=(g>>3);\
124                                 pixel<<=5;\
125                                 pixel|=(r>>3)
126
127 typedef void(*wsTConvFunc)( const unsigned char * in_pixels, unsigned char * out_pixels, unsigned num_pixels );
128 wsTConvFunc wsConvFunc = NULL;
129
130 void rgb32torgb32( const unsigned char * src, unsigned char * dst,unsigned int src_size )
131 { memcpy( dst,src,src_size ); }
132
133 // ---
134
135 #define MWM_HINTS_FUNCTIONS     (1L << 0)
136 #define MWM_HINTS_DECORATIONS   (1L << 1)
137 #define MWM_HINTS_INPUT_MODE    (1L << 2)
138 #define MWM_HINTS_STATUS        (1L << 3)
139
140 #define MWM_FUNC_ALL            (1L << 0)
141 #define MWM_FUNC_RESIZE         (1L << 1)
142 #define MWM_FUNC_MOVE           (1L << 2)
143 #define MWM_FUNC_MINIMIZE       (1L << 3)
144 #define MWM_FUNC_MAXIMIZE       (1L << 4)
145 #define MWM_FUNC_CLOSE          (1L << 5)
146
147 #define MWM_DECOR_ALL           (1L << 0)
148 #define MWM_DECOR_BORDER        (1L << 1)
149 #define MWM_DECOR_RESIZEH       (1L << 2)
150 #define MWM_DECOR_TITLE         (1L << 3)
151 #define MWM_DECOR_MENU          (1L << 4)
152 #define MWM_DECOR_MINIMIZE      (1L << 5)
153 #define MWM_DECOR_MAXIMIZE      (1L << 6)
154
155 #define MWM_INPUT_MODELESS 0
156 #define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
157 #define MWM_INPUT_SYSTEM_MODAL 2
158 #define MWM_INPUT_FULL_APPLICATION_MODAL 3
159 #define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
160
161 #define MWM_TEAROFF_WINDOW      (1L<<0)
162
163 void wsWindowDecoration( wsTWindow * win,long d )
164 {
165  wsMotifHints=XInternAtom( wsDisplay,"_MOTIF_WM_HINTS",0 );
166  if ( wsMotifHints == None ) return;
167
168  memset( &wsMotifWmHints,0,sizeof( MotifWmHints ) );
169  wsMotifWmHints.flags=MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
170  if ( d )
171   {
172    wsMotifWmHints.functions=MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE;
173    wsMotifWmHints.decorations=MWM_DECOR_ALL;
174   }
175  XChangeProperty( wsDisplay,win->WindowID,wsMotifHints,wsMotifHints,32,
176                   PropModeReplace,(unsigned char *)&wsMotifWmHints,5 );
177 }
178
179 // ----------------------------------------------------------------------------------------------
180 //   Init X Window System.
181 // ----------------------------------------------------------------------------------------------
182
183 int wsIOErrorHandler( Display * dpy )
184 {
185  fprintf( stderr,"[ws] IO error in display.\n" );
186  exit( 0 );
187 }
188
189 int wsErrorHandler( Display * dpy,XErrorEvent * Event )
190 {
191  char type[128];
192  XGetErrorText( wsDisplay,Event->error_code,type,128 );
193  fprintf(stderr,"[ws] Error in display.\n");
194  fprintf(stderr,"[ws]  Error code: %d ( %s )\n",Event->error_code,type );
195  fprintf(stderr,"[ws]  Request code: %d\n",Event->request_code );
196  fprintf(stderr,"[ws]  Minor code: %d\n",Event->minor_code );
197  fprintf(stderr,"[ws]  Modules: %s\n",current_module?current_module:"(NULL)" );
198  exit( 0 );
199 }
200
201 void wsXInit( void* mDisplay )
202 {
203  int    eventbase;
204  int    errorbase;
205
206 if(mDisplay){
207  wsDisplay=mDisplay;
208 } else {
209  char * DisplayName = ":0.0";
210  if ( getenv( "DISPLAY" ) ) DisplayName=getenv( "DISPLAY" );
211  wsDisplay=XOpenDisplay( DisplayName );
212  if ( !wsDisplay )
213   {
214    mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_CouldNotOpenDisplay );
215    exit( 0 );
216   }
217 }
218
219 /* enable DND atoms */
220 wsXDNDInitialize();
221
222 { /* on remote display XShm will be disabled - LGB */
223  char *dispname=DisplayString(wsDisplay);
224  int localdisp=1;
225  if (dispname&&*dispname!=':') {
226     localdisp=0;
227     wsUseXShm=0;
228  }
229  mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] display name: %s => %s display.\n",dispname,localdisp?"local":"REMOTE");
230  if (!localdisp) mp_msg( MSGT_GPLAYER,MSGL_V,MSGTR_WS_RemoteDisplay );
231 }
232
233  if ( !XShmQueryExtension( wsDisplay ) )
234   {
235    mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_NoXshm );
236    wsUseXShm=0;
237   }
238 #ifdef CONFIG_XSHAPE
239   if ( !XShapeQueryExtension( wsDisplay,&eventbase,&errorbase ) )
240    {
241     mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_NoXshape );
242     wsUseXShape=0;
243    }
244 #else
245   wsUseXShape=0;
246 #endif
247
248  XSynchronize( wsDisplay,True );
249
250  wsScreen=DefaultScreen( wsDisplay );
251  wsRootWin=RootWindow( wsDisplay,wsScreen );
252 #ifdef CONFIG_XF86VM
253     {
254       int clock;
255       XF86VidModeModeLine modeline;
256
257       XF86VidModeGetModeLine( wsDisplay,wsScreen,&clock ,&modeline );
258       wsMaxX=modeline.hdisplay;
259       wsMaxY=modeline.vdisplay;
260     }
261 #endif
262  {
263  wsOrgX = wsOrgY = 0;
264  if ( !wsMaxX )
265  wsMaxX=DisplayWidth( wsDisplay,wsScreen );
266  if ( !wsMaxY )
267  wsMaxY=DisplayHeight( wsDisplay,wsScreen );
268  }
269   vo_screenwidth = wsMaxX; vo_screenheight = wsMaxY;
270   xinerama_x = wsOrgX; xinerama_y = wsOrgY;
271   update_xinerama_info();
272   wsMaxX = vo_screenwidth; wsMaxY = vo_screenheight;
273   wsOrgX = xinerama_x; wsOrgY = xinerama_y;
274
275  wsGetDepthOnScreen();
276 #ifdef DEBUG
277   {
278    int minor,major,shp;
279    mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] Screen depth: %d\n",wsDepthOnScreen );
280    mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws]  size: %dx%d\n",wsMaxX,wsMaxY );
281 #ifdef CONFIG_XINERAMA
282    mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws]  origin: +%d+%d\n",wsOrgX,wsOrgY );
283 #endif
284    mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws]  red mask: 0x%x\n",wsRedMask );
285    mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws]  green mask: 0x%x\n",wsGreenMask );
286    mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws]  blue mask: 0x%x\n",wsBlueMask );
287    if ( wsUseXShm )
288     {
289      XShmQueryVersion( wsDisplay,&major,&minor,&shp );
290      mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] XShm version is %d.%d\n",major,minor );
291     }
292    #ifdef CONFIG_XSHAPE
293     if ( wsUseXShape )
294      {
295       XShapeQueryVersion( wsDisplay,&major,&minor );
296       mp_msg( MSGT_GPLAYER,MSGL_DBG2,"[ws] XShape version is %d.%d\n",major,minor );
297      }
298    #endif
299   }
300 #endif
301  wsOutMask=wsGetOutMask();
302  mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] Initialized converter: " );
303  sws_rgb2rgb_init(get_sws_cpuflags());
304  switch ( wsOutMask )
305   {
306    case wsRGB32:
307      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb32\n" );
308      wsConvFunc=rgb32torgb32;
309      break;
310    case wsBGR32:
311      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr32\n" );
312      wsConvFunc=rgb32tobgr32;
313      break;
314    case wsRGB24:
315      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb24\n" );
316      wsConvFunc=rgb32to24;
317      break;
318    case wsBGR24:
319      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr24\n" );
320      wsConvFunc=rgb32tobgr24;
321      break;
322    case wsRGB16:
323      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb16\n" );
324      wsConvFunc=rgb32to16;
325      break;
326    case wsBGR16:
327      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr16\n" );
328      wsConvFunc=rgb32tobgr16;
329      break;
330    case wsRGB15:
331      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to rgb15\n" );
332      wsConvFunc=rgb32to15;
333      break;
334    case wsBGR15:
335      mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"rgb32 to bgr15\n" );
336      wsConvFunc=rgb32tobgr15;
337      break;
338   }
339  XSetErrorHandler( wsErrorHandler );
340 }
341
342 // ----------------------------------------------------------------------------------------------
343 //   Create window.
344 //     X,Y   : window position
345 //     wX,wY : size of window
346 //     bW    : border width
347 //     cV    : visible mouse cursor on window
348 //     D     : visible frame, title, etc.
349 //     sR    : screen ratio
350 // ----------------------------------------------------------------------------------------------
351
352 XClassHint           wsClassHint;
353 XTextProperty        wsTextProperty;
354 Window               LeaderWindow;
355
356 void wsCreateWindow( wsTWindow * win,int X,int Y,int wX,int hY,int bW,int cV,unsigned char D,char * label )
357 {
358  int depth;
359
360  win->Property=D;
361  if ( D & wsShowFrame ) win->Decorations=1;
362  wsHGC=DefaultGC( wsDisplay,wsScreen );
363 // The window position and size.
364  switch ( X )
365   {
366    case -1: win->X=( wsMaxX / 2 ) - ( wX / 2 ) + wsOrgX; break;
367    case -2: win->X=wsMaxX - wX - 1 + wsOrgX; break;
368    default: win->X=X; break;
369   }
370  switch ( Y )
371   {
372    case -1: win->Y=( wsMaxY / 2 ) - ( hY / 2 ) + wsOrgY; break;
373    case -2: win->Y=wsMaxY - hY - 1 + wsOrgY; break;
374    default: win->Y=Y; break;
375   }
376  win->Width=wX;
377  win->Height=hY;
378  win->OldX=win->X;
379  win->OldY=win->Y;
380  win->OldWidth=win->Width;
381  win->OldHeight=win->Height;
382
383 // Border size for window.
384  win->BorderWidth=bW;
385 // Hide Mouse Cursor
386  win->wsCursor=None;
387  win->wsMouseEventType=cV;
388  win->wsCursorData[0]=0;
389  win->wsCursorPixmap=XCreateBitmapFromData( wsDisplay,wsRootWin,win->wsCursorData,1,1 );
390  if ( !(cV & wsShowMouseCursor) ) win->wsCursor=XCreatePixmapCursor( wsDisplay,win->wsCursorPixmap,win->wsCursorPixmap,&win->wsColor,&win->wsColor,0,0 );
391
392  depth = vo_find_depth_from_visuals( wsDisplay,wsScreen,NULL );
393  if ( depth < 15 )
394   {
395    mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ColorDepthTooLow );
396    exit( 0 );
397   }
398  XMatchVisualInfo( wsDisplay,wsScreen,depth,TrueColor,&win->VisualInfo );
399
400 // ---
401  win->AtomLeaderClient=XInternAtom( wsDisplay,"WM_CLIENT_LEADER",False );
402  win->AtomDeleteWindow=XInternAtom( wsDisplay,"WM_DELETE_WINDOW",False );
403  win->AtomTakeFocus=XInternAtom( wsDisplay,"WM_TAKE_FOCUS",False );
404  win->AtomRolle=XInternAtom( wsDisplay,"WM_WINDOW_ROLE",False );
405  win->AtomWMSizeHint=XInternAtom( wsDisplay,"WM_SIZE_HINT",False );
406  win->AtomWMNormalHint=XInternAtom( wsDisplay,"WM_NORMAL_HINT",False );
407  win->AtomProtocols=XInternAtom( wsDisplay,"WM_PROTOCOLS",False );
408  win->AtomsProtocols[0]=win->AtomDeleteWindow;
409  win->AtomsProtocols[1]=win->AtomTakeFocus;
410  win->AtomsProtocols[2]=win->AtomRolle;
411 // ---
412
413  win->WindowAttrib.background_pixel=BlackPixel( wsDisplay,wsScreen );
414  win->WindowAttrib.border_pixel=WhitePixel( wsDisplay,wsScreen );
415  win->WindowAttrib.colormap=XCreateColormap( wsDisplay,wsRootWin,win->VisualInfo.visual,AllocNone );
416  win->WindowAttrib.event_mask=StructureNotifyMask | FocusChangeMask |
417                               ExposureMask | PropertyChangeMask |
418                               EnterWindowMask | LeaveWindowMask |
419                               VisibilityChangeMask |
420                               KeyPressMask | KeyReleaseMask;
421  if ( ( cV & wsHandleMouseButton ) ) win->WindowAttrib.event_mask|=ButtonPressMask | ButtonReleaseMask;
422  if ( ( cV & wsHandleMouseMove ) ) win->WindowAttrib.event_mask|=PointerMotionMask;
423  win->WindowAttrib.cursor=win->wsCursor;
424  win->WindowAttrib.override_redirect=False;
425  if ( D & wsOverredirect ) win->WindowAttrib.override_redirect=True;
426
427  win->WindowMask=CWBackPixel | CWBorderPixel |
428                  CWColormap | CWEventMask | CWCursor |
429                  CWOverrideRedirect;
430
431  win->WindowID=XCreateWindow( wsDisplay,
432   (win->Parent != 0?win->Parent:wsRootWin),
433   win->X,win->Y,win->Width,win->Height,win->BorderWidth,
434   win->VisualInfo.depth,
435   InputOutput,
436   win->VisualInfo.visual,
437   win->WindowMask,&win->WindowAttrib );
438
439  wsClassHint.res_name="MPlayer";
440
441  wsClassHint.res_class="MPlayer";
442  XSetClassHint( wsDisplay,win->WindowID,&wsClassHint );
443
444  win->SizeHint.flags=PPosition | PSize | PResizeInc | PWinGravity;// | PBaseSize;
445  win->SizeHint.x=win->X;
446  win->SizeHint.y=win->Y;
447  win->SizeHint.width=win->Width;
448  win->SizeHint.height=win->Height;
449
450  if ( D & wsMinSize )
451   {
452    win->SizeHint.flags|=PMinSize;
453    win->SizeHint.min_width=win->Width;
454    win->SizeHint.min_height=win->Height;
455   }
456  if ( D & wsMaxSize )
457   {
458    win->SizeHint.flags|=PMaxSize;
459    win->SizeHint.max_width=win->Width;
460    win->SizeHint.max_height=win->Height;
461   }
462
463  win->SizeHint.height_inc=1;
464  win->SizeHint.width_inc=1;
465  win->SizeHint.base_width=win->Width;
466  win->SizeHint.base_height=win->Height;
467  win->SizeHint.win_gravity=StaticGravity;
468  XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint );
469
470  win->WMHints.flags=InputHint | StateHint;
471  win->WMHints.input=True;
472  win->WMHints.initial_state=NormalState;
473  XSetWMHints( wsDisplay,win->WindowID,&win->WMHints );
474
475  wsWindowDecoration( win,win->Decorations );
476  XStoreName( wsDisplay,win->WindowID,label );
477  XmbSetWMProperties( wsDisplay,win->WindowID,label,label,NULL,0,NULL,NULL,NULL );
478
479  XSetWMProtocols( wsDisplay,win->WindowID,win->AtomsProtocols,3 );
480  XChangeProperty( wsDisplay,win->WindowID,
481                   win->AtomLeaderClient,
482                   XA_WINDOW,32,PropModeReplace,
483                   (unsigned char *)&LeaderWindow,1 );
484
485  wsTextProperty.value=label;
486  wsTextProperty.encoding=XA_STRING;
487  wsTextProperty.format=8;
488  wsTextProperty.nitems=strlen( label );
489  XSetWMIconName( wsDisplay,win->WindowID,&wsTextProperty );
490
491  win->wGC=XCreateGC( wsDisplay,win->WindowID,
492   GCForeground | GCBackground,
493   &win->wGCV );
494
495  win->Visible=0;
496  win->Focused=0;
497  win->Mapped=0;
498  win->Rolled=0;
499  if ( D & wsShowWindow ) XMapWindow( wsDisplay,win->WindowID );
500
501  wsCreateImage( win,win->Width,win->Height );
502 // --- End of creating --------------------------------------------------------------------------
503
504  {
505   int i;
506   for ( i=0;i < wsWLCount;i++ )
507    if ( wsWindowList[i] == NULL ) break;
508   if ( i == wsWLCount )
509    {  mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_TooManyOpenWindows ); exit( 0 ); }
510   wsWindowList[i]=win;
511  }
512
513  XFlush( wsDisplay );
514  XSync( wsDisplay,False );
515
516  win->ReDraw=NULL;
517  win->ReSize=NULL;
518  win->Idle=NULL;
519  win->MouseHandler=NULL;
520  win->KeyHandler=NULL;
521  mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"[ws] window is created. ( %s ).\n",label );
522 }
523
524 void wsDestroyWindow( wsTWindow * win )
525 {
526  int l;
527  l=wsSearch( win->WindowID );
528  wsWindowList[l]=NULL;
529  if ( win->wsCursor != None )
530    {
531     XFreeCursor( wsDisplay,win->wsCursor );
532     win->wsCursor=None;
533    }
534  XFreeGC( wsDisplay,win->wGC );
535  XUnmapWindow( wsDisplay,win->WindowID );
536  wsDestroyImage( win );
537  XDestroyWindow( wsDisplay,win->WindowID );
538 #if 0
539  win->ReDraw=NULL;
540  win->ReSize=NULL;
541  win->Idle=NULL;
542  win->MouseHandler=NULL;
543  win->KeyHandler=NULL;
544  win->Visible=0;
545  win->Focused=0;
546  win->Mapped=0;
547  win->Rolled=0;
548 #endif
549 }
550
551 // ----------------------------------------------------------------------------------------------
552 //   Handle events.
553 // ----------------------------------------------------------------------------------------------
554
555 inline int wsSearch( Window win )
556 {
557  int i;
558  for ( i=0;i<wsWLCount;i++ ) if ( wsWindowList[i] && wsWindowList[i]->WindowID == win ) return i;
559  return -1;
560 }
561
562 Bool wsEvents( Display * display,XEvent * Event,XPointer arg )
563 {
564  unsigned long i = 0;
565  int           l;
566  int           x,y;
567  Window        child_window = 0;
568
569  l=wsSearch( Event->xany.window );
570  if ( l == -1 ) return !wsTrue;
571  wsWindowList[l]->State=0;
572  switch( Event->type )
573   {
574    case ClientMessage:
575         if ( Event->xclient.message_type == wsWindowList[l]->AtomProtocols )
576          {
577           if ( (Atom)Event->xclient.data.l[0] == wsWindowList[l]->AtomDeleteWindow )
578            { i=wsWindowClosed; goto expose; }
579           if ( (Atom)Event->xclient.data.l[0] == wsWindowList[l]->AtomTakeFocus )
580            { i=wsWindowFocusIn;  wsWindowList[l]->Focused=wsFocused; goto expose; }
581           if ( (Atom)Event->xclient.data.l[0] == wsWindowList[l]->AtomRolle )
582            { mp_msg( MSGT_GPLAYER,MSGL_V,"[ws] role set.\n" ); }
583          } else {
584            /* try to process DND events */
585            wsXDNDProcessClientMessage(wsWindowList[l],&Event->xclient);
586          }
587         break;
588
589    case MapNotify:   i=wsWindowMapped;   wsWindowList[l]->Mapped=wsMapped;   goto expose;
590    case UnmapNotify: i=wsWindowUnmapped; wsWindowList[l]->Mapped=wsNone;     goto expose;
591    case FocusIn:
592         if ( wsWindowList[l]->Focused == wsFocused ) break;
593         i=wsWindowFocusIn;
594         wsWindowList[l]->Focused=wsFocused;
595         goto expose;
596    case FocusOut:
597         if ( wsWindowList[l]->Focused == wsNone ) break;
598         i=wsWindowFocusOut;
599         wsWindowList[l]->Focused=wsNone;
600         goto expose;
601    case VisibilityNotify:
602         switch( Event->xvisibility.state )
603          {
604           case VisibilityUnobscured:        i=wsWindowVisible;        wsWindowList[l]->Visible=wsVisible;    goto expose;
605           case VisibilityFullyObscured:     i=wsWindowNotVisible;     wsWindowList[l]->Visible=wsNotVisible; goto expose;
606           case VisibilityPartiallyObscured: i=wsWindowPartialVisible; wsWindowList[l]->Visible=wsPVisible;   goto expose;
607          }
608 expose:
609         wsWindowList[l]->State=i;
610         if ( wsWindowList[l]->ReDraw ) wsWindowList[l]->ReDraw();
611         break;
612
613    case Expose:
614         wsWindowList[l]->State=wsWindowExpose;
615         if ( ( wsWindowList[l]->ReDraw )&&( !Event->xexpose.count ) ) wsWindowList[l]->ReDraw();
616         break;
617
618    case ConfigureNotify:
619         XTranslateCoordinates( wsDisplay,wsWindowList[l]->WindowID,wsRootWin,0,0,&x,&y,&child_window );
620         if ( ( wsWindowList[l]->X != x )||( wsWindowList[l]->Y != y )||( wsWindowList[l]->Width != Event->xconfigure.width )||( wsWindowList[l]->Height != Event->xconfigure.height ) )
621           {
622            wsWindowList[l]->X=x; wsWindowList[l]->Y=y;
623            wsWindowList[l]->Width=Event->xconfigure.width; wsWindowList[l]->Height=Event->xconfigure.height;
624            if ( wsWindowList[l]->ReSize ) wsWindowList[l]->ReSize( wsWindowList[l]->X,wsWindowList[l]->Y,wsWindowList[l]->Width,wsWindowList[l]->Height );
625           }
626
627         wsWindowList[l]->Rolled=wsNone;
628         if ( Event->xconfigure.y < 0 )
629           { i=wsWindowRolled; wsWindowList[l]->Rolled=wsRolled; goto expose; }
630
631         break;
632
633    case KeyPress:   i=wsKeyPressed;  goto keypressed;
634    case KeyRelease: i=wsKeyReleased;
635 keypressed:
636         wsWindowList[l]->Alt=0;
637         wsWindowList[l]->Shift=0;
638         wsWindowList[l]->NumLock=0;
639         wsWindowList[l]->Control=0;
640         wsWindowList[l]->CapsLock=0;
641         if ( Event->xkey.state & Mod1Mask ) wsWindowList[l]->Alt=1;
642         if ( Event->xkey.state & Mod2Mask ) wsWindowList[l]->NumLock=1;
643         if ( Event->xkey.state & ControlMask ) wsWindowList[l]->Control=1;
644         if ( Event->xkey.state & ShiftMask ) wsWindowList[l]->Shift=1;
645         if ( Event->xkey.state & LockMask ) wsWindowList[l]->CapsLock=1;
646 #if 0
647         {
648          KeySym        keySym;
649          keySym=XKeycodeToKeysym( wsDisplay,Event->xkey.keycode,0 );
650          if ( keySym != NoSymbol )
651           {
652            keySym=( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) );
653            wsKeyTable[ keySym ]=i;
654            if ( wsWindowList[l]->KeyHandler )
655              wsWindowList[l]->KeyHandler( Event->xkey.state,i,keySym );
656           }
657         }
658 #else
659         {
660                 int             key;
661                 char            buf[100];
662                 KeySym          keySym;
663          static XComposeStatus  stat;
664
665          XLookupString( &Event->xkey,buf,sizeof(buf),&keySym,&stat );
666          key=( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) );
667          wsKeyTable[ key ]=i;
668          if ( wsWindowList[l]->KeyHandler ) wsWindowList[l]->KeyHandler( Event->xkey.keycode,i,key );
669         }
670 #endif
671         break;
672
673    case MotionNotify:
674      i=wsMoveMouse;
675      {
676        /* pump all motion events from the display queue:
677           this way it works faster when moving the window */
678       static XEvent e;
679       if ( Event->xmotion.state )
680        {
681         while(XCheckTypedWindowEvent(display,Event->xany.window,MotionNotify,&e)){
682          /* FIXME: need to make sure we didn't release/press the button in between...*/
683          /* FIXME: do we need some timeout here to make sure we don't spend too much time
684             removing events from the queue? */
685          Event = &e;
686         }
687        }
688      }
689      goto buttonreleased;
690    case ButtonRelease: i=Event->xbutton.button + 128; goto buttonreleased;
691    case ButtonPress:   i=Event->xbutton.button;       goto buttonreleased;
692    case EnterNotify:   i=wsEnterWindow;               goto buttonreleased;
693    case LeaveNotify:   i=wsLeaveWindow;
694 buttonreleased:
695         if ( wsWindowList[l]->MouseHandler )
696           wsWindowList[l]->MouseHandler( i,Event->xbutton.x,Event->xbutton.y,Event->xmotion.x_root,Event->xmotion.y_root );
697         break;
698
699    case SelectionNotify:
700      /* Handle DandD */
701      wsXDNDProcessSelection(wsWindowList[l],Event);
702      break;
703   }
704  XFlush( wsDisplay );
705  XSync( wsDisplay,False );
706  return !wsTrue;
707 }
708
709 Bool wsDummyEvents( Display * display,XEvent * Event,XPointer arg )
710 { return True; }
711
712 void wsHandleEvents( void ){
713  // handle pending events
714  while ( XPending(wsDisplay) ){
715    XNextEvent( wsDisplay,&wsEvent );
716 //   printf("### X event: %d  [%d]\n",wsEvent.type,delay);
717    wsEvents( wsDisplay,&wsEvent,NULL );
718  }
719 }
720
721 void wsMainLoop( void )
722 {
723  int delay=20;
724  mp_msg( MSGT_GPLAYER,MSGL_V,"[ws] init threads: %d\n",XInitThreads() );
725  XSynchronize( wsDisplay,False );
726  XLockDisplay( wsDisplay );
727 // XIfEvent( wsDisplay,&wsEvent,wsEvents,NULL );
728
729 #if 1
730
731 while(wsTrue){
732  // handle pending events
733  while ( XPending(wsDisplay) ){
734    XNextEvent( wsDisplay,&wsEvent );
735    wsEvents( wsDisplay,&wsEvent,NULL );
736    delay=0;
737  }
738  usleep(delay*1000); // FIXME!
739  if(delay<10*20) delay+=20; // pump up delay up to 0.2 sec (low activity)
740 }
741
742 #else
743
744  while( wsTrue )
745   {
746    XIfEvent( wsDisplay,&wsEvent,wsDummyEvents,NULL );
747    wsEvents( wsDisplay,&wsEvent,NULL );
748   }
749 #endif
750
751  XUnlockDisplay( wsDisplay );
752 }
753
754 // ----------------------------------------------------------------------------------------------
755 //    Move window to selected layer
756 // ----------------------------------------------------------------------------------------------
757
758 #define WIN_LAYER_ONBOTTOM               2
759 #define WIN_LAYER_NORMAL                 4
760 #define WIN_LAYER_ONTOP                 10
761
762 void wsSetLayer( Display * wsDisplay, Window win, int layer )
763 { vo_x11_setlayer( wsDisplay,win,layer ); }
764
765 // ----------------------------------------------------------------------------------------------
766 //    Switch to fullscreen.
767 // ----------------------------------------------------------------------------------------------
768 void wsFullScreen( wsTWindow * win )
769 {
770  int decoration = 0;
771
772  if ( win->isFullScreen )
773   {
774    vo_x11_ewmh_fullscreen( _NET_WM_STATE_REMOVE ); // removes fullscreen state if wm supports EWMH
775    if ( ! (vo_fs_type & vo_wm_FULLSCREEN) ) // shouldn't be needed with EWMH fs
776     {
777      win->X=win->OldX;
778      win->Y=win->OldY;
779      win->Width=win->OldWidth;
780      win->Height=win->OldHeight;
781      decoration=win->Decorations;
782     }
783
784 #ifdef ENABLE_DPMS
785    wsScreenSaverOn( wsDisplay );
786 #endif
787
788    win->isFullScreen=False;
789   }
790   else
791    {
792     if ( ! (vo_fs_type & vo_wm_FULLSCREEN) ) // shouldn't be needed with EWMH fs
793      {
794       win->OldX=win->X; win->OldY=win->Y;
795       win->OldWidth=win->Width; win->OldHeight=win->Height;
796       vo_dx = win->X; vo_dy = win->Y;
797       vo_dwidth = win->Width; vo_dheight = win->Height;
798       vo_screenwidth = wsMaxX; vo_screenheight = wsMaxY;
799       xinerama_x = wsOrgX; xinerama_y = wsOrgY;
800       update_xinerama_info();
801       wsMaxX = vo_screenwidth; wsMaxY = vo_screenheight;
802       wsOrgX = xinerama_x; wsOrgY = xinerama_y;
803       win->X=wsOrgX; win->Y=wsOrgY;
804       win->Width=wsMaxX; win->Height=wsMaxY;
805      }
806
807     win->isFullScreen=True;
808 #ifdef ENABLE_DPMS
809     wsScreenSaverOff( wsDisplay );
810 #endif
811
812      vo_x11_ewmh_fullscreen( _NET_WM_STATE_ADD ); // adds fullscreen state if wm supports EWMH
813    }
814
815   if ( ! (vo_fs_type & vo_wm_FULLSCREEN) ) // shouldn't be needed with EWMH fs
816    {
817     vo_x11_decoration( wsDisplay,win->WindowID,decoration );
818     vo_x11_sizehint( win->X,win->Y,win->Width,win->Height,0 );
819     vo_x11_setlayer( wsDisplay,win->WindowID,win->isFullScreen );
820
821     if ((!(win->isFullScreen)) & vo_ontop) vo_x11_setlayer(wsDisplay, win->WindowID,1);
822
823     XMoveResizeWindow( wsDisplay,win->WindowID,win->X,win->Y,win->Width,win->Height );
824    }
825
826  if ( vo_wm_type == 0 && !(vo_fsmode&16) )
827   {
828    XWithdrawWindow( wsDisplay,win->WindowID,wsScreen );
829   }
830
831
832  XMapRaised( wsDisplay,win->WindowID );
833  XRaiseWindow( wsDisplay,win->WindowID );
834  XFlush( wsDisplay );
835 }
836
837 // ----------------------------------------------------------------------------------------------
838 //    Redraw screen.
839 // ----------------------------------------------------------------------------------------------
840 void wsPostRedisplay( wsTWindow * win )
841 {
842  if ( win->ReDraw )
843   {
844    win->State=wsWindowExpose;
845    win->ReDraw();
846    XFlush( wsDisplay );
847   }
848 }
849
850 // ----------------------------------------------------------------------------------------------
851 //    Do Exit.
852 // ----------------------------------------------------------------------------------------------
853 void wsDoExit( void )
854 { wsTrue=False; wsResizeWindow( wsWindowList[0],32,32 ); }
855
856 // ----------------------------------------------------------------------------------------------
857 //    Put 'Image' to window.
858 // ----------------------------------------------------------------------------------------------
859 void wsConvert( wsTWindow * win,unsigned char * Image,unsigned int Size )
860 {
861   int i;
862   if ( wsConvFunc )
863     wsConvFunc( Image,win->ImageData,win->xImage->width * win->xImage->height * 4 );
864   if (!wsNonNativeOrder) return;
865   switch (win->xImage->bits_per_pixel) {
866     case 32:
867     {
868       uint32_t *d = win->ImageData;
869       for (i = 0; i < win->xImage->width * win->xImage->height; i++)
870         d[i] = bswap_32(d[i]);
871       break;
872     }
873     case 16:
874     case 15:
875     {
876       uint16_t *d = win->ImageData;
877       for (i = 0; i < win->xImage->width * win->xImage->height; i++)
878         d[i] = bswap_16(d[i]);
879       break;
880     }
881   }
882 }
883
884 void wsPutImage( wsTWindow * win )
885 {
886  if ( wsUseXShm )
887   {
888    XShmPutImage( wsDisplay,win->WindowID,win->wGC,win->xImage,
889     0,0,
890     ( win->Width - win->xImage->width ) / 2,( win->Height - win->xImage->height ) / 2,
891     win->xImage->width,win->xImage->height,0 );
892   }
893   else
894    {
895     XPutImage( wsDisplay,win->WindowID,win->wGC,win->xImage,
896     0,0,
897     ( win->Width - win->xImage->width ) / 2,( win->Height - win->xImage->height ) / 2,
898     win->xImage->width,win->xImage->height );
899    }
900 }
901
902 // ----------------------------------------------------------------------------------------------
903 //    Move window to x, y.
904 // ----------------------------------------------------------------------------------------------
905 void wsMoveWindow( wsTWindow * win,int b,int x, int y )
906 {
907  if ( b )
908   {
909    switch ( x )
910     {
911      case -1: win->X=( wsMaxX / 2 ) - ( win->Width / 2 ) + wsOrgX; break;
912      case -2: win->X=wsMaxX - win->Width + wsOrgX; break;
913      default: win->X=x; break;
914     }
915    switch ( y )
916     {
917      case -1: win->Y=( wsMaxY / 2 ) - ( win->Height / 2 ) + wsOrgY; break;
918      case -2: win->Y=wsMaxY - win->Height + wsOrgY; break;
919      default: win->Y=y; break;
920     }
921   }
922   else { win->X=x; win->Y=y; }
923
924  win->SizeHint.flags=PPosition | PWinGravity;
925  win->SizeHint.x=win->X;
926  win->SizeHint.y=win->Y;
927  win->SizeHint.win_gravity=StaticGravity;
928  XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint );
929
930  XMoveWindow( wsDisplay,win->WindowID,win->X,win->Y );
931  if ( win->ReSize ) win->ReSize( win->X,win->Y,win->Width,win->Height );
932 }
933
934 // ----------------------------------------------------------------------------------------------
935 //    Resize window to sx, sy.
936 // ----------------------------------------------------------------------------------------------
937 void wsResizeWindow( wsTWindow * win,int sx, int sy )
938 {
939  win->Width=sx;
940  win->Height=sy;
941
942  win->SizeHint.flags=PPosition | PSize | PWinGravity;// | PBaseSize;
943  win->SizeHint.x=win->X;
944  win->SizeHint.y=win->Y;
945  win->SizeHint.width=win->Width;
946  win->SizeHint.height=win->Height;
947
948  if ( win->Property & wsMinSize )
949   {
950    win->SizeHint.flags|=PMinSize;
951    win->SizeHint.min_width=win->Width;
952    win->SizeHint.min_height=win->Height;
953   }
954  if ( win->Property & wsMaxSize )
955   {
956    win->SizeHint.flags|=PMaxSize;
957    win->SizeHint.max_width=win->Width;
958    win->SizeHint.max_height=win->Height;
959   }
960
961  win->SizeHint.win_gravity=StaticGravity;
962  win->SizeHint.base_width=sx; win->SizeHint.base_height=sy;
963
964  if ( vo_wm_type == 0 ) XUnmapWindow( wsDisplay,win->WindowID );
965
966  XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint );
967  XResizeWindow( wsDisplay,win->WindowID,sx,sy );
968  XMapRaised( wsDisplay,win->WindowID );
969  if ( win->ReSize ) win->ReSize( win->X,win->Y,win->Width,win->Height );
970 }
971
972 // ----------------------------------------------------------------------------------------------
973 //    Iconify window.
974 // ----------------------------------------------------------------------------------------------
975 void wsIconify( wsTWindow win )
976 { XIconifyWindow( wsDisplay,win.WindowID,0 ); }
977
978 // ----------------------------------------------------------------------------------------------
979 //    Move top the window.
980 // ----------------------------------------------------------------------------------------------
981 void wsMoveTopWindow( Display * wsDisplay,Window win )
982 {
983 // XUnmapWindow( wsDisplay,win );
984 // XMapWindow( wsDisplay,win );
985  XMapRaised( wsDisplay,win );
986  XRaiseWindow( wsDisplay,win );
987 }
988
989 // ----------------------------------------------------------------------------------------------
990 //    Set window background to 'color'.
991 // ----------------------------------------------------------------------------------------------
992 void wsSetBackground( wsTWindow * win,int color )
993 { XSetWindowBackground( wsDisplay,win->WindowID,color ); }
994
995 void wsSetBackgroundRGB( wsTWindow * win,int r,int g,int b )
996 {
997  int color = 0;
998  switch ( wsOutMask )
999   {
1000    case wsRGB32:
1001    case wsRGB24: color=( r << 16 ) + ( g << 8 ) + b;  break;
1002    case wsBGR32:
1003    case wsBGR24: color=( b << 16 ) + ( g << 8 ) + r;  break;
1004    case wsRGB16: PACK_RGB16( b,g,r,color ); break;
1005    case wsBGR16: PACK_RGB16( r,g,b,color ); break;
1006    case wsRGB15: PACK_RGB15( b,g,r,color ); break;
1007    case wsBGR15: PACK_RGB15( r,g,b,color ); break;
1008   }
1009  XSetWindowBackground( wsDisplay,win->WindowID,color );
1010 }
1011
1012 void wsSetForegroundRGB( wsTWindow * win,int r,int g,int b )
1013 {
1014  int color = 0;
1015  switch ( wsOutMask )
1016   {
1017    case wsRGB32:
1018    case wsRGB24: color=( r << 16 ) + ( g << 8 ) + b;  break;
1019    case wsBGR32:
1020    case wsBGR24: color=( b << 16 ) + ( g << 8 ) + r;  break;
1021    case wsRGB16: PACK_RGB16( b,g,r,color ); break;
1022    case wsBGR16: PACK_RGB16( r,g,b,color ); break;
1023    case wsRGB15: PACK_RGB15( b,g,r,color ); break;
1024    case wsBGR15: PACK_RGB15( r,g,b,color ); break;
1025   }
1026  XSetForeground( wsDisplay,win->wGC,color );
1027 }
1028
1029 // ----------------------------------------------------------------------------------------------
1030 //    Draw string at x,y with fc ( foreground color ) and bc ( background color ).
1031 // ----------------------------------------------------------------------------------------------
1032 void wsDrawString( wsTWindow win,int x,int y,char * str,int fc,int bc )
1033 {
1034  XSetForeground( wsDisplay,win.wGC,bc );
1035  XFillRectangle( wsDisplay,win.WindowID,win.wGC,x,y,
1036    XTextWidth( win.Font,str,strlen( str ) ) + 20,
1037    win.FontHeight + 2 );
1038  XSetForeground( wsDisplay,win.wGC,fc );
1039  XDrawString( wsDisplay,win.WindowID,win.wGC,x + 10,y + 13,str,strlen( str ) );
1040 }
1041
1042 // ----------------------------------------------------------------------------------------------
1043 //    Calculation string width.
1044 // ----------------------------------------------------------------------------------------------
1045 int wsTextWidth( wsTWindow win,char * str )
1046 { return XTextWidth( win.Font,str,strlen( str ) ) + 20; }
1047
1048 // ----------------------------------------------------------------------------------------------
1049 //    Show / hide mouse cursor.
1050 // ----------------------------------------------------------------------------------------------
1051 void wsVisibleMouse( wsTWindow * win,int m )
1052 {
1053  switch ( m )
1054   {
1055    case wsShowMouseCursor:
1056     if ( win->wsCursor != None )
1057      {
1058       XFreeCursor( wsDisplay,win->wsCursor );
1059       win->wsCursor=None;
1060      }
1061     XDefineCursor( wsDisplay,win->WindowID,0 );
1062     break;
1063    case wsHideMouseCursor:
1064     win->wsCursor=XCreatePixmapCursor( wsDisplay,win->wsCursorPixmap,win->wsCursorPixmap,&win->wsColor,&win->wsColor,0,0 );
1065     XDefineCursor( wsDisplay,win->WindowID,win->wsCursor );
1066     break;
1067   }
1068  XFlush( wsDisplay );
1069 }
1070
1071 int wsGetDepthOnScreen( void )
1072 {
1073  int depth;
1074  XImage * mXImage;
1075  Visual * visual;
1076
1077  if( (depth = vo_find_depth_from_visuals( wsDisplay,wsScreen,&visual )) > 0 )
1078   {
1079    mXImage = XCreateImage( wsDisplay,visual,depth,ZPixmap,0,NULL,
1080                            1,1,32,0 );
1081    wsDepthOnScreen = mXImage->bits_per_pixel;
1082    wsRedMask=mXImage->red_mask;
1083    wsGreenMask=mXImage->green_mask;
1084    wsBlueMask=mXImage->blue_mask;
1085 #if HAVE_BIGENDIAN
1086    wsNonNativeOrder = mXImage->byte_order == LSBFirst;
1087 #else
1088    wsNonNativeOrder = mXImage->byte_order == MSBFirst;
1089 #endif
1090    XDestroyImage( mXImage );
1091   }
1092  else
1093   {
1094    int                 bpp,ibpp;
1095    XWindowAttributes   attribs;
1096
1097    mXImage=XGetImage( wsDisplay,wsRootWin,0,0,1,1,AllPlanes,ZPixmap );
1098    bpp=mXImage->bits_per_pixel;
1099
1100    XGetWindowAttributes( wsDisplay,wsRootWin,&attribs );
1101    ibpp=attribs.depth;
1102    mXImage=XGetImage( wsDisplay,wsRootWin,0,0,1,1,AllPlanes,ZPixmap );
1103    bpp=mXImage->bits_per_pixel;
1104    if ( ( ibpp + 7 ) / 8 != ( bpp + 7 ) / 8 ) ibpp=bpp;
1105    wsDepthOnScreen=ibpp;
1106    wsRedMask=mXImage->red_mask;
1107    wsGreenMask=mXImage->green_mask;
1108    wsBlueMask=mXImage->blue_mask;
1109    XDestroyImage( mXImage );
1110   }
1111  return wsDepthOnScreen;
1112 }
1113
1114 void wsXDone( void )
1115 {
1116  XCloseDisplay( wsDisplay );
1117 }
1118
1119 void wsVisibleWindow( wsTWindow * win,int show )
1120 {
1121  switch( show )
1122   {
1123    case wsShowWindow: XMapRaised( wsDisplay,win->WindowID ); break;
1124    case wsHideWindow: XUnmapWindow( wsDisplay,win->WindowID ); break;
1125   }
1126  XFlush( wsDisplay );
1127 }
1128
1129 void wsDestroyImage( wsTWindow * win )
1130 {
1131  if ( win->xImage )
1132   {
1133    XDestroyImage( win->xImage );
1134    if ( wsUseXShm )
1135     {
1136      XShmDetach( wsDisplay,&win->Shminfo );
1137      shmdt( win->Shminfo.shmaddr );
1138     }
1139   }
1140  win->xImage=NULL;
1141 }
1142
1143 void wsCreateImage( wsTWindow * win,int Width,int Height )
1144 {
1145  int CompletionType = -1;
1146  if ( wsUseXShm )
1147   {
1148    CompletionType=XShmGetEventBase( wsDisplay ) + ShmCompletion;
1149    win->xImage=XShmCreateImage( wsDisplay,win->VisualInfo.visual,
1150                    win->VisualInfo.depth,ZPixmap,NULL,&win->Shminfo,Width,Height );
1151    if ( win->xImage == NULL )
1152     {
1153      mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ShmError );
1154      exit( 0 );
1155     }
1156    win->Shminfo.shmid=shmget( IPC_PRIVATE,win->xImage->bytes_per_line * win->xImage->height,IPC_CREAT|0777 );
1157    if ( win->Shminfo.shmid < 0 )
1158     {
1159      XDestroyImage( win->xImage );
1160      mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ShmError );
1161      exit( 0 );
1162     }
1163    win->Shminfo.shmaddr=(char *)shmat( win->Shminfo.shmid,0,0 );
1164
1165    if ( win->Shminfo.shmaddr == ((char *) -1) )
1166     {
1167      XDestroyImage( win->xImage );
1168      if ( win->Shminfo.shmaddr != ((char *) -1) ) shmdt( win->Shminfo.shmaddr );
1169      mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_ShmError );
1170      exit( 0 );
1171     }
1172    win->xImage->data=win->Shminfo.shmaddr;
1173    win->Shminfo.readOnly=0;
1174    XShmAttach( wsDisplay,&win->Shminfo );
1175    shmctl( win->Shminfo.shmid,IPC_RMID,0 );
1176   }
1177   else
1178    {
1179     win->xImage=XCreateImage( wsDisplay,win->VisualInfo.visual,win->VisualInfo.depth,
1180                               ZPixmap,0,0,Width,Height,
1181                               (wsDepthOnScreen == 3) ? 32 : wsDepthOnScreen,
1182                               0 );
1183     if ( ( win->xImage->data=malloc( win->xImage->bytes_per_line * win->xImage->height ) ) == NULL )
1184      {
1185       mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_WS_NotEnoughMemoryDrawBuffer );
1186       exit( 0 );
1187      }
1188    }
1189  win->ImageData=(unsigned char *)win->xImage->data;
1190  win->ImageDataw=(unsigned short int *)win->xImage->data;
1191  win->ImageDatadw=(unsigned int *)win->xImage->data;
1192 }
1193
1194 void wsResizeImage( wsTWindow * win,int Width,int Height )
1195 { wsDestroyImage( win ); wsCreateImage( win,Width,Height ); }
1196
1197 int wsGetOutMask( void )
1198 {
1199  if ( ( wsDepthOnScreen == 32 )&&( wsRedMask == 0xff0000 )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0x0000ff ) ) return wsRGB32;
1200  if ( ( wsDepthOnScreen == 32 )&&( wsRedMask == 0x0000ff )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0xff0000 ) ) return wsBGR32;
1201  if ( ( wsDepthOnScreen == 24 )&&( wsRedMask == 0xff0000 )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0x0000ff ) ) return wsRGB24;
1202  if ( ( wsDepthOnScreen == 24 )&&( wsRedMask == 0x0000ff )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0xff0000 ) ) return wsBGR24;
1203  if ( ( wsDepthOnScreen == 16 )&&( wsRedMask == 0xf800 )&&( wsGreenMask == 0x7e0 )&&( wsBlueMask ==   0x1f ) ) return wsRGB16;
1204  if ( ( wsDepthOnScreen == 16 )&&( wsRedMask ==   0x1f )&&( wsGreenMask == 0x7e0 )&&( wsBlueMask == 0xf800 ) ) return wsBGR16;
1205  if ( ( wsDepthOnScreen == 15 )&&( wsRedMask == 0x7c00 )&&( wsGreenMask == 0x3e0 )&&( wsBlueMask ==   0x1f ) ) return wsRGB15;
1206  if ( ( wsDepthOnScreen == 15 )&&( wsRedMask ==   0x1f )&&( wsGreenMask == 0x3e0 )&&( wsBlueMask == 0x7c00 ) ) return wsBGR15;
1207  return 0;
1208 }
1209
1210 void wsSetTitle( wsTWindow * win,char * name )
1211 { XStoreName( wsDisplay,win->WindowID,name ); }
1212
1213 void wsSetMousePosition( wsTWindow * win,int x, int y )
1214 { XWarpPointer( wsDisplay,wsRootWin,win->WindowID,0,0,0,0,x,y ); }
1215
1216 #ifdef ENABLE_DPMS
1217 static int dpms_disabled=0;
1218 static int timeout_save=0;
1219
1220 void wsScreenSaverOn( Display *mDisplay )
1221 {
1222  int nothing;
1223 #ifdef CONFIG_XDPMS
1224  if ( dpms_disabled )
1225   {
1226    if ( DPMSQueryExtension( mDisplay,&nothing,&nothing ) )
1227     {
1228      if ( !DPMSEnable( mDisplay ) ) mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_WS_DpmsUnavailable ); // restoring power saving settings
1229       else
1230        {
1231         // DPMS does not seem to be enabled unless we call DPMSInfo
1232         BOOL onoff;
1233         CARD16 state;
1234         DPMSInfo( mDisplay,&state,&onoff );
1235         if ( onoff ) mp_msg( MSGT_GPLAYER,MSGL_V,"Successfully enabled DPMS.\n" );
1236          else mp_msg( MSGT_GPLAYER,MSGL_STATUS,MSGTR_WS_DpmsNotEnabled );
1237        }
1238     }
1239   }
1240 #endif
1241  if ( timeout_save )
1242   {
1243    int dummy, interval, prefer_blank, allow_exp;
1244    XGetScreenSaver( mDisplay,&dummy,&interval,&prefer_blank,&allow_exp );
1245    XSetScreenSaver( mDisplay,timeout_save,interval,prefer_blank,allow_exp );
1246    XGetScreenSaver( mDisplay,&timeout_save,&interval,&prefer_blank,&allow_exp );
1247   }
1248 }
1249
1250 void wsScreenSaverOff( Display * mDisplay )
1251 {
1252  int interval,prefer_blank,allow_exp,nothing;
1253 #ifdef CONFIG_XDPMS
1254  if ( DPMSQueryExtension( mDisplay,&nothing,&nothing ) )
1255   {
1256    BOOL onoff;
1257    CARD16 state;
1258    DPMSInfo( mDisplay,&state,&onoff );
1259    if ( onoff )
1260     {
1261       Status stat;
1262       mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"Disabling DPMS.\n" );
1263       dpms_disabled=1;
1264       stat=DPMSDisable( mDisplay );  // monitor powersave off
1265       mp_dbg( MSGT_GPLAYER,MSGL_DBG2,"stat: %d.\n",stat );
1266    }
1267   }
1268 #endif
1269  XGetScreenSaver( mDisplay,&timeout_save,&interval,&prefer_blank,&allow_exp );
1270  if ( timeout_save ) XSetScreenSaver( mDisplay,0,interval,prefer_blank,allow_exp ); // turning off screensaver
1271 }
1272 #endif
1273
1274 void wsSetShape( wsTWindow * win,char * data )
1275 {
1276 #ifdef CONFIG_XSHAPE
1277  if ( !wsUseXShape ) return;
1278  if ( data )
1279   {
1280    win->Mask=XCreateBitmapFromData( wsDisplay,win->WindowID,data,win->Width,win->Height );
1281    XShapeCombineMask( wsDisplay,win->WindowID,ShapeBounding,0,0,win->Mask,ShapeSet );
1282    XFreePixmap( wsDisplay,win->Mask );
1283   }
1284   else XShapeCombineMask( wsDisplay,win->WindowID,ShapeBounding,0,0,None,ShapeSet );
1285 #endif
1286 }
1287
1288 void wsSetIcon( Display * dsp,Window win,Pixmap icon,Pixmap mask )
1289 {
1290  XWMHints * wm;
1291  long       data[2];
1292  Atom       iconatom;
1293
1294  wm=XGetWMHints( dsp,win );
1295  if ( !wm ) wm=XAllocWMHints();
1296
1297  wm->icon_pixmap=icon;
1298  wm->icon_mask=mask;
1299  wm->flags|=IconPixmapHint | IconMaskHint;
1300
1301  XSetWMHints( dsp,win,wm );
1302
1303  data[0]=icon;
1304  data[1]=mask;
1305  iconatom=XInternAtom( dsp,"KWM_WIN_ICON",0 );
1306  XChangeProperty( dsp,win,iconatom,iconatom,32,PropModeReplace,(unsigned char *)data,2 );
1307
1308  XFree( wm );
1309 }
1310
1311 #include "wsmkeys.h"