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