Mercurial > mplayer.hg
diff Gui/wm/ws.c @ 1693:d237c5d4b216
GUI version n-1
author | arpi |
---|---|
date | Sat, 25 Aug 2001 21:04:29 +0000 |
parents | |
children | 7ddc63b84f1f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Gui/wm/ws.c Sat Aug 25 21:04:29 2001 +0000 @@ -0,0 +1,1077 @@ + +// -------------------------------------------------------------------------- +// AutoSpace Window System for Linux/Win32 v0.85 +// Writed by pontscho/fresh!mindworkz +// -------------------------------------------------------------------------- + +#include <X11/Xlib.h> +#include <X11/Xproto.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +#include "ws.h" +#include "wsconv.h" +#include "../../config.h" + +#include <X11/extensions/xf86dga.h> +#include <X11/extensions/xf86dgastr.h> +#include <X11/extensions/XShm.h> +#include <X11/extensions/shape.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +typedef struct +{ + long flags; + long functions; + long decorations; + long input_mode; + long status; +} MotifWmHints; + +Atom wsMotifHints; + +unsigned int wsMaxX = 0; // Screen width. +unsigned int wsMaxY = 0; // Screen height. + +Display * wsDisplay; +int wsScreen; +Window wsRootWin; +XEvent wsEvent; +int wsWindowDepth; +GC wsHGC; +MotifWmHints wsMotifWmHints; +Atom wsTextProperlyAtom = None; + +int wsDepthOnScreen = 0; +int wsRedMask = 0; +int wsGreenMask = 0; +int wsBlueMask = 0; +int wsOutMask = 0; + +int wsTrue = True; + +wsTWindow * wsWindowList[5] = { NULL,NULL,NULL,NULL,NULL }; +int wsWLCount = 0; + +unsigned long wsKeyTable[512]; + +int wsUseXShm = 1; +int wsUseDGA = 1; +int wsUseXShape = 1; + +int XShmGetEventBase( Display* ); +inline int wsSearch( Window win ); + +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 +#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL + +#define MWM_TEAROFF_WINDOW (1L<<0) + +void wsWindowDecoration( wsTWindow * win,long d ) +{ + wsMotifHints=XInternAtom( wsDisplay,"_MOTIF_WM_HINTS",0 ); + if ( wsMotifHints != None ) + { + memset( &wsMotifWmHints,0,sizeof( MotifWmHints ) ); + wsMotifWmHints.flags=( d?0:MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS ); + wsMotifWmHints.functions=( d?0:MWM_FUNC_MOVE | MWM_FUNC_CLOSE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE ); + wsMotifWmHints.decorations=( d?MWM_DECOR_ALL:0 ); + XChangeProperty( wsDisplay,win->WindowID,wsMotifHints,wsMotifHints,32, + PropModeReplace,(unsigned char *)&wsMotifWmHints,5 ); + } +} + +// ---------------------------------------------------------------------------------------------- +// Init X Window System. +// ---------------------------------------------------------------------------------------------- + +int wsIOErrorHandler( Display * dpy ) +{ + fprintf( stderr,"[ws] io error in display.\n" ); + exit( 0 ); +} + +int wsErrorHandler( Display * dpy,XErrorEvent * Event ) +{ + char type[128]; + XGetErrorText( wsDisplay,Event->error_code,type,128 ); + fprintf(stderr,"[ws] Error in display.\n"); + fprintf(stderr,"[ws] Error code: %d ( %s )\n",Event->error_code,type ); + fprintf(stderr,"[ws] Request code: %d\n",Event->request_code ); + fprintf(stderr,"[ws] Minor code: %d\n",Event->minor_code ); + exit( 0 ); +} + +void wsXInit( void ) +{ + char * DisplayName = ":0.0"; + int eventbase; + int errorbase; + + if ( getenv( "DISPLAY" ) ) DisplayName=getenv( "DISPLAY" ); + wsDisplay=XOpenDisplay( DisplayName ); + if ( !wsDisplay ) + { + fprintf( stderr,"[ws] couldn't open the display !\n" ); + exit( 0 ); + } + + if ( !XShmQueryExtension( wsDisplay ) ) + { + fprintf( stderr,"[ws] sorry, your system is not supported X shared memory extension.\n" ); + wsUseXShm=0; + } +// if ( !XDGAQueryExtension( wsDisplay,&eventbase,&errorbase ) ) + { + fprintf( stderr,"[ws] sorry, your system is not supported DGA extension.\n" ); + wsUseDGA=0; + } + #ifdef HAVE_XSHAPE + if ( !XShapeQueryExtension( wsDisplay,&eventbase,&errorbase ) ) + { + fprintf( stderr,"[ws] sorry, your system is not supported XShape extension.\n" ); + wsUseXShape=0; + } + #else + wsUseXShape=0; + #endif + + XSynchronize( wsDisplay,True ); + + wsScreen=DefaultScreen( wsDisplay ); + wsRootWin=RootWindow( wsDisplay,wsScreen ); + wsMaxX=DisplayWidth( wsDisplay,wsScreen ); + wsMaxY=DisplayHeight( wsDisplay,wsScreen ); + + wsGetDepthOnScreen(); + #ifdef DEBUG + { + int minor,major,shp; + fprintf( stderr,"[ws] Screen depth: %d\n",wsDepthOnScreen ); + fprintf( stderr,"[ws] red mask: 0x%x\n",wsRedMask ); + fprintf( stderr,"[ws] green mask: 0x%x\n",wsGreenMask ); + fprintf( stderr,"[ws] blue mask: 0x%x\n",wsBlueMask ); + if ( wsUseXShm ) + { + XShmQueryVersion( wsDisplay,&major,&minor,&shp ); + fprintf( stderr,"[ws] XShm version is %d.%d\n",major,minor ); + } + if ( wsUseDGA ) + { +// XDGAQueryVersion( wsDisplay,&major,&minor ); +// fprintf( stderr,"[ws] DGA version is %d.%d\n",major,minor ); + } + #ifdef HAVE_XSHAPE + if ( wsUseXShape ) + { + XShapeQueryVersion( wsDisplay,&major,&minor ); + fprintf( stderr,"[ws] XShape version is %d.%d\n",major,minor ); + } + #endif + } + #endif + initConverter(); + wsOutMask=wsGetOutMask(); + switch ( wsOutMask ) + { + case wsRGB32: + wsConvFunc=BGR8880_to_RGB8880_c; + break; + case wsBGR32: + wsConvFunc=BGR8880_to_BGR8880_c; + break; + case wsRGB24: + #ifdef xHAVE_MMX + wsConvFunc=BGR8880_to_RGB888_mmx; + #else + wsConvFunc=BGR8880_to_RGB888_c; + #endif + break; + case wsBGR24: + wsConvFunc=BGR8880_to_BGR888_c; + break; + case wsRGB16: + wsConvFunc=BGR8880_to_RGB565_c; + break; + case wsBGR16: + wsConvFunc=BGR8880_to_BGR565_c; + break; + case wsRGB15: + wsConvFunc=BGR8880_to_RGB555_c; + break; + case wsBGR15: + wsConvFunc=BGR8880_to_BGR555_c; + break; + } + XSetIOErrorHandler( wsIOErrorHandler ); + XSetErrorHandler( wsErrorHandler ); +} + +// ---------------------------------------------------------------------------------------------- +// Create window. +// X,Y : window position +// wX,wY : size of window +// bW : border width +// cV : visible mouse cursor on window +// D : visible frame, title, etc. +// sR : screen ratio +// ---------------------------------------------------------------------------------------------- + +XClassHint wsClassHint; +XTextProperty wsTextProperty; +Window LeaderWindow; + +void wsCreateWindow( wsTWindow * win,int X,int Y,int wX,int hY,int bW,int cV,unsigned char D,char * label ) +{ + win->Property=D; + if ( D & wsShowFrame ) win->Decorations=1; + wsHGC=DefaultGC( wsDisplay,wsScreen ); +// The window position and size. + switch ( X ) + { + case -1: win->X=( wsMaxX / 2 ) - ( wX / 2 ); break; + case -2: win->X=wsMaxX - wX - 1; break; + default: win->X=X; break; + } + switch ( Y ) + { + case -1: win->Y=( wsMaxY / 2 ) - ( hY / 2 ); break; + case -2: win->Y=wsMaxY - hY - 1; break; + default: win->Y=Y; break; + } + win->Width=wX; + win->Height=hY; + win->OldX=win->X; + win->OldY=win->Y; + win->OldWidth=win->Width; + win->OldHeight=win->Height; + +// Border size for window. + win->BorderWidth=bW; +// Hide Mouse Cursor + win->wsCursor=None; + win->wsMouseEventType=cV; + win->wsCursorData[0]=0; + win->wsCursorPixmap=XCreateBitmapFromData( wsDisplay,wsRootWin,win->wsCursorData,1,1 ); + if ( !(cV & wsShowMouseCursor) ) win->wsCursor=XCreatePixmapCursor( wsDisplay,win->wsCursorPixmap,win->wsCursorPixmap,&win->wsColor,&win->wsColor,0,0 ); + + XGetWindowAttributes( wsDisplay,wsRootWin,&win->Attribs ); + if ( win->Attribs.depth < 15 ) + { + fprintf( stderr,"[ws] sorry, this color depth is not enough.\n" ); + exit( 0 ); + } + XMatchVisualInfo( wsDisplay,wsScreen,win->Attribs.depth,TrueColor,&win->VisualInfo ); + +// --- + win->AtomLeaderClient=XInternAtom( wsDisplay,"WM_CLIENT_LEADER",False ); + win->AtomDeleteWindow=XInternAtom( wsDisplay,"WM_DELETE_WINDOW",False ); + win->AtomTakeFocus=XInternAtom( wsDisplay,"WM_TAKE_FOCUS",False ); + win->AtomRolle=XInternAtom( wsDisplay,"WM_WINDOW_ROLE",False ); + win->AtomProtocols=XInternAtom( wsDisplay,"WM_PROTOCOLS",False ); + { + char buf[32]; int i; + sprintf( buf,"_%s_REMOTE",label ); + for( i=0;i<strlen( buf );i++ ) + if ( ( buf[i] >= 'a' )&&( buf[i] <= 'z' ) ) buf[i]=buf[i] - 32; + for( i=0;i<strlen( buf );i++ ) + if ( buf[i] == ' ' ) buf[i]='_'; + fprintf( stderr,"[ws] atomname: %s\n",buf ); + win->AtomRemote=XInternAtom( wsDisplay,buf,False ); + } + win->AtomsProtocols[0]=win->AtomDeleteWindow; + win->AtomsProtocols[1]=win->AtomTakeFocus; + win->AtomsProtocols[2]=win->AtomRolle; +// --- + +// win->WindowAttrib.background_pixel=BlackPixel( wsDisplay,wsScreen ); +// win->WindowAttrib.border_pixel=BlackPixel( wsDisplay,wsScreen ); + win->WindowAttrib.background_pixel=BlackPixel( wsDisplay,wsScreen ); + win->WindowAttrib.border_pixel=WhitePixel( wsDisplay,wsScreen ); + win->WindowAttrib.colormap=XCreateColormap( wsDisplay,wsRootWin,win->VisualInfo.visual,AllocNone ); + win->WindowAttrib.event_mask=StructureNotifyMask | FocusChangeMask | + //SubstructureRedirectMask | + //SubstructureNotifyMask | + //ResizeRedirectMask | + //GCGraphicsExposures | + ExposureMask | PropertyChangeMask | + EnterWindowMask | LeaveWindowMask | + VisibilityChangeMask | + KeyPressMask | KeyReleaseMask; + if ( ( cV & wsHandleMouseButton ) ) win->WindowAttrib.event_mask|=ButtonPressMask | ButtonReleaseMask; + if ( ( cV & wsHandleMouseMove ) ) win->WindowAttrib.event_mask|=PointerMotionMask; + win->WindowAttrib.cursor=win->wsCursor; + win->WindowAttrib.override_redirect=False; + if ( D & wsOverredirect ) win->WindowAttrib.override_redirect=True; + +// win->WindowAttrib.save_under=True; +// win->WindowAttrib.do_not_propagate_mask = True; + + win->WindowMask=CWBackPixel | CWBorderPixel | + CWColormap | CWEventMask | CWCursor | + CWX | CWY | CWWidth | CWHeight | + CWOverrideRedirect; + + win->WindowID=XCreateWindow( wsDisplay, + (win->Parent != 0?win->Parent:wsRootWin), + win->X,win->Y,win->Width,win->Height,win->BorderWidth, + win->VisualInfo.depth, + InputOutput, + win->VisualInfo.visual, + win->WindowMask,&win->WindowAttrib ); + + wsClassHint.res_name=label; + wsClassHint.res_class="mPlayer"; + XSetClassHint( wsDisplay,win->WindowID,&wsClassHint ); + + win->SizeHint.flags=PPosition | PSize | PResizeInc; // | PBaseSize + win->SizeHint.x=win->X; + win->SizeHint.y=win->Y; + win->SizeHint.width=win->Width; + win->SizeHint.height=win->Height; + if ( D & wsMaxSize ) + { + win->SizeHint.flags|=PMaxSize; + win->SizeHint.min_width=win->Width; + win->SizeHint.min_height=win->Height; + } + if ( D & wsMinSize ) + { + win->SizeHint.flags|=PMinSize; + win->SizeHint.max_width=win->Width; + win->SizeHint.max_height=win->Height; + } + win->SizeHint.height_inc=1; + win->SizeHint.width_inc=1; +// win->SizeHint.base_width=win->Width; +// win->SizeHint.base_height=win->Height; + XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint ); + + win->WMHints.flags=InputHint | StateHint; + win->WMHints.input=True; + win->WMHints.initial_state=NormalState; + XSetWMHints( wsDisplay,win->WindowID,&win->WMHints ); + + wsWindowDecoration( win,win->Decorations ); + XStoreName( wsDisplay,win->WindowID,label ); + XmbSetWMProperties( wsDisplay,win->WindowID,label,label,NULL,0,NULL,NULL,NULL ); + + XSetWMProtocols( wsDisplay,win->WindowID,win->AtomsProtocols,3 ); + XChangeProperty( wsDisplay,win->WindowID, + win->AtomLeaderClient, + XA_WINDOW,32,PropModeReplace, + (unsigned char *)&LeaderWindow,1 ); + + wsTextProperty.value=label; + wsTextProperty.encoding=XA_STRING; + wsTextProperty.format=8; + wsTextProperty.nitems=strlen( label ); + XSetWMIconName( wsDisplay,win->WindowID,&wsTextProperty ); + + XChangeProperty( wsDisplay,win->WindowID, + win->AtomRemote,XA_STRING, + 8,PropModeReplace, + "REALIZED",8 ); + +// win->Font=XLoadQueryFont( wsDisplay,"-adobe-helvetica-bold-r-normal--14-140-75-75-p-77-iso8859-1" ); +// -adobe-times-medium-r-normal--14-140-75-75-p-77-iso8859-1" ); +// -misc-fixed-bold-r-normal--13-120-75-75-C-80-iso8859-1" ); +// -misc-fixed-bold-r-normal--15-140-75-75-C-90-iso8859-1" ); +// -misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1" ); +// -adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1" ); +// -adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1" ); +// -*-helvetica-bold-o-normal--14-*-*-*-p-*-iso8859-1" ); +// if ( !win->Font ) win->Font=XLoadQueryFont( wsDisplay,"fixed" ); +// if ( !win->Font ) +// { +// fprintf( stderr,"[main] could not load font.\n" ); +// exit( 0 ); +// } +// win->FontHeight=win->Font->ascent + win->Font->descent; +// +// #ifdef DEBUG +// fprintf( stderr,"[ws] font height: %d\n",win->FontHeight ); +// #endif + +// win->wGCV.font=win->Font->fid; +// win->wGCV.foreground=wsBlack; +// win->wGCV.background=wsBlack; + + win->wGC=XCreateGC( wsDisplay,win->WindowID, +// GCForeground | GCBackground, + 0, + &win->wGCV ); + + win->Visible=0; + win->Focused=0; + win->Mapped=0; + win->Rolled=0; + if ( D & wsShowWindow ) XMapWindow( wsDisplay,win->WindowID ); + + wsCreateImage( win ); +// --- End of creating -------------------------------------------------------------------------- + + wsWindowList[wsWLCount++]=win; + + XFlush( wsDisplay ); + XSync( wsDisplay,False ); + + win->ReDraw=NULL; + win->ReSize=NULL; + win->Idle=NULL; + win->MouseHandler=NULL; + win->KeyHandler=NULL; + #ifdef DEBUG + fprintf( stderr,"[ws] window is created. ( %s ).\n",label ); + #endif +} + +void wsDestroyWindow( wsTWindow * win ) +{ + int l; + l=wsSearch( win->WindowID ); + wsWindowList[l]=NULL; + if ( win->wsCursor != None ) + { + XFreeCursor( wsDisplay,win->wsCursor ); + win->wsCursor=None; + } + XUnmapWindow( wsDisplay,win->WindowID ); + wsDestroyImage( win ); + XDestroyWindow( wsDisplay,win->WindowID ); + win->ReDraw=NULL; + win->ReSize=NULL; + win->Idle=NULL; + win->MouseHandler=NULL; + win->KeyHandler=NULL; + win->Visible=0; + win->Focused=0; + win->Mapped=0; + win->Rolled=0; +} + +// ---------------------------------------------------------------------------------------------- +// Handle events. +// ---------------------------------------------------------------------------------------------- + +inline int wsSearch( Window win ) +{ + int i; + for ( i=0;i<wsWLCount;i++ ) if ( wsWindowList[i]->WindowID == win ) return i; + return -1; +} + +Bool wsEvents( Display * display,XEvent * Event,XPointer arg ) +{ + KeySym keySym; + unsigned long i = 0; + int l; + int x,y; + Window child_window = 0; + + l=wsSearch( Event->xany.window ); + if ( l == -1 ) return !wsTrue; + switch( Event->type ) + { + case ClientMessage: + if ( Event->xclient.message_type == wsWindowList[l]->AtomProtocols ) + { + if ( Event->xclient.data.l[0] == wsWindowList[l]->AtomDeleteWindow ) + { wsTrue=False; break; } + if ( Event->xclient.data.l[0] == wsWindowList[l]->AtomTakeFocus ) + { i=wsWindowFocusIn; wsWindowList[l]->Focused=wsFocused; goto expose; } + if ( Event->xclient.data.l[0] == wsWindowList[l]->AtomRolle ) + { fprintf( stderr,"[ws] rolled.\n" ); } + } + break; + +// case CirculateRequest:fprintf( stderr,"[ws,r] win: 0x%x\n",(int)Event->xcirculaterequest.window ); break; +// case CirculateNotify: fprintf( stderr,"[ws,c] win: 0x%x\n",(int)Event->xcirculate.window ); break; + + case MapNotify: i=wsWindowMapped; wsWindowList[l]->Mapped=wsMapped; goto expose; + case UnmapNotify: i=wsWindowUnmapped; wsWindowList[l]->Mapped=wsNone; goto expose; + case FocusIn: + if ( wsWindowList[l]->Focused == wsFocused ) break; + i=wsWindowFocusIn; wsWindowList[l]->Focused=wsFocused; goto expose; + case FocusOut: + if ( wsWindowList[l]->Focused == wsNone ) break; + i=wsWindowFocusOut; wsWindowList[l]->Focused=wsNone; goto expose; + case VisibilityNotify: + switch( Event->xvisibility.state ) + { + case VisibilityUnobscured: i=wsWindowVisible; wsWindowList[l]->Visible=wsVisible; goto expose; + case VisibilityFullyObscured: i=wsWindowNotVisible; wsWindowList[l]->Visible=wsNotVisible; goto expose; + case VisibilityPartiallyObscured: i=wsWindowPartialVisible; wsWindowList[l]->Visible=wsPVisible; goto expose; + } +expose: + wsWindowList[l]->State=i; + if ( wsWindowList[l]->ReDraw ) wsWindowList[l]->ReDraw( wsDisplay,Event->xany.window ); + break; + + case Expose: + wsWindowList[l]->State=wsWindowExpose; + if ( ( wsWindowList[l]->ReDraw )&&( !Event->xexpose.count ) ) wsWindowList[l]->ReDraw( wsDisplay,Event->xany.window ); + break; + + case ConfigureNotify: + XTranslateCoordinates( wsDisplay,wsWindowList[l]->WindowID,wsRootWin,0,0,&x,&y,&child_window ); + if ( ( wsWindowList[l]->X != x )||( wsWindowList[l]->Y != y )||( wsWindowList[l]->Width != Event->xconfigure.width )||( wsWindowList[l]->Height != Event->xconfigure.height ) ) + { + wsWindowList[l]->X=x; wsWindowList[l]->Y=y; + wsWindowList[l]->Width=Event->xconfigure.width; wsWindowList[l]->Height=Event->xconfigure.height; +// fprintf( stderr,"[ws] resize: %d,%d %dx%d\n",wsWindowList[l]->X,wsWindowList[l]->Y,Event->xconfigure.width,Event->xconfigure.height ); + if ( wsWindowList[l]->ReSize ) wsWindowList[l]->ReSize( wsWindowList[l]->X,wsWindowList[l]->Y,wsWindowList[l]->Width,wsWindowList[l]->Height ); + } + + wsWindowList[l]->Rolled=wsNone; + if ( Event->xconfigure.y < 0 ) + { i=wsWindowRolled; wsWindowList[l]->Rolled=wsRolled; goto expose; } + + break; + + case KeyPress: i=wsKeyPressed; goto keypressed; + case KeyRelease: i=wsKeyReleased; +keypressed: + wsWindowList[l]->Alt=0; + wsWindowList[l]->Shift=0; + wsWindowList[l]->NumLock=0; + wsWindowList[l]->Control=0; + wsWindowList[l]->CapsLock=0; + if ( Event->xkey.state & Mod1Mask ) wsWindowList[l]->Alt=1; + if ( Event->xkey.state & Mod2Mask ) wsWindowList[l]->NumLock=1; + if ( Event->xkey.state & ControlMask ) wsWindowList[l]->Control=1; + if ( Event->xkey.state & ShiftMask ) wsWindowList[l]->Shift=1; + if ( Event->xkey.state & LockMask ) wsWindowList[l]->CapsLock=1; + keySym=XKeycodeToKeysym( wsDisplay,Event->xkey.keycode,0 ); + if ( keySym != NoSymbol ) + { + keySym=( (keySym&0xff00) != 0?( (keySym&0x00ff) + 256 ):( keySym ) ); + wsKeyTable[ keySym ]=i; + if ( wsWindowList[l]->KeyHandler ) + wsWindowList[l]->KeyHandler( Event->xkey.state,i,keySym ); + } + break; + + case MotionNotify: i=wsMoveMouse; goto buttonreleased; + case ButtonRelease: i=Event->xbutton.button + 128; goto buttonreleased; + case ButtonPress: i=Event->xbutton.button; goto buttonreleased; + case EnterNotify: i=wsEnterWindow; goto buttonreleased; + case LeaveNotify: i=wsLeaveWindow; +buttonreleased: + if ( wsWindowList[l]->MouseHandler ) + wsWindowList[l]->MouseHandler( i,Event->xbutton.x,Event->xbutton.y,Event->xmotion.x_root,Event->xmotion.y_root ); + break; + + case PropertyNotify: +// fprintf(stderr,"[ws] PropertyNotify %s\n",XGetAtomName( wsDisplay,Event->xproperty.atom ) ); + if ( Event->xproperty.atom == wsWindowList[l]->AtomRemote ) + { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char * args = NULL; + +// fprintf( stderr,"[ws] remote property notify.\n" ); + XGetWindowProperty( wsDisplay, + Event->xproperty.window, + Event->xproperty.atom, + 0,( 65536 / sizeof( long ) ), + False,XA_STRING, + &type,&format,&nitems,&bytesafter, + &args ); + if ( ( nitems )&&( wsWindowList[l]->RemoteHandler ) ) + { + args[strlen( args ) - 1]=0; + wsWindowList[l]->RemoteHandler( args ); + args[strlen( args ) - 1]=1; + XFree( args ); + } + } + break; + + } + XFlush( wsDisplay ); + XSync( wsDisplay,False ); + return !wsTrue; +// return True; +} + +Bool wsDummyEvents( Display * display,XEvent * Event,XPointer arg ) +{ return True; } + +void wsMainLoop( void ) +{ + fprintf( stderr,"[ws] init threads: %d\n",XInitThreads() ); + XSynchronize( wsDisplay,False ); + XLockDisplay( wsDisplay ); +// XIfEvent( wsDisplay,&wsEvent,wsEvents,NULL ); + while( wsTrue ) + { + XIfEvent( wsDisplay,&wsEvent,wsDummyEvents,NULL ); + wsEvents( wsDisplay,&wsEvent,NULL ); + } + XUnlockDisplay( wsDisplay ); +} + +// ---------------------------------------------------------------------------------------------- +// Switch to fullscreen. +// ---------------------------------------------------------------------------------------------- +void wsFullScreen( wsTWindow * win ) +{ + int decoration = 0; + XUnmapWindow( wsDisplay,win->WindowID ); + win->SizeHint.flags=0; + if ( win->isFullScreen ) + { + win->X=win->OldX; + win->Y=win->OldY; + win->Width=win->OldWidth; + win->Height=win->OldHeight; + win->isFullScreen=False; + if ( win->Property & wsMaxSize ) + { + win->SizeHint.flags|=PMaxSize; + win->SizeHint.max_width=win->Width; + win->SizeHint.max_height=win->Height; + } + if ( win->Property & wsMinSize ) + { + win->SizeHint.flags|=PMinSize; + win->SizeHint.min_width=win->Width; + win->SizeHint.min_height=win->Height; + } + decoration=win->Decorations; + wsScreenSaverOn( wsDisplay ); + } + else + { + win->OldX=win->X; win->OldY=win->Y; + win->OldWidth=win->Width; win->OldHeight=win->Height; + win->X=0; win->Y=0; + win->Width=wsMaxX; win->Height=wsMaxY; + win->isFullScreen=True; +// if ( win->Property & wsMaxSize ) +// { +// win->SizeHint.flags|=PMaxSize; +// win->SizeHint.min_width=0; +// win->SizeHint.min_height=0; +// } +// if ( win->Property & wsMinSize ) +// { +// win->SizeHint.flags|=PMinSize; +// win->SizeHint.max_width=4096; +// win->SizeHint.max_height=4096; +// } + wsScreenSaverOff( wsDisplay ); + } + + win->SizeHint.flags|=PPosition | PSize; + win->SizeHint.x=win->X; + win->SizeHint.y=win->Y; + win->SizeHint.width=win->Width; + win->SizeHint.height=win->Height; + XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint ); + + XMoveResizeWindow( wsDisplay,win->WindowID,win->X,win->Y,win->Width,win->Height ); + wsWindowDecoration( win,decoration ); + XRaiseWindow( wsDisplay,win->WindowID ); + XMapWindow( wsDisplay,win->WindowID ); +} + +// ---------------------------------------------------------------------------------------------- +// Redraw screen. +// ---------------------------------------------------------------------------------------------- +void wsPostRedisplay( wsTWindow * win ) +{ + if ( win->ReDraw ) + { + win->ReDraw( wsDisplay,win->WindowID ); + XFlush( wsDisplay ); + } +} + +// ---------------------------------------------------------------------------------------------- +// Do Exit. +// ---------------------------------------------------------------------------------------------- +void wsDoExit( void ) +{ wsTrue=False; wsResizeWindow( wsWindowList[0],32,32 ); } + +// ---------------------------------------------------------------------------------------------- +// Put 'Image' to window. +// ---------------------------------------------------------------------------------------------- +void wsConvert( wsTWindow * win,unsigned char * Image,unsigned int Size ) +{ if ( wsConvFunc ) wsConvFunc( Image,win->ImageData,win->xImage->width * win->xImage->height ); } + +void wsPutImage( wsTWindow * win ) +{ + if ( wsUseXShm ) + { + XShmPutImage( wsDisplay,win->WindowID,win->wGC,win->xImage, + 0,0, + ( win->Width - win->xImage->width ) / 2,( win->Height - win->xImage->height ) / 2, + win->xImage->width,win->xImage->height,0 ); +// win->Width,win->Height,0 ); + } + else + { + XPutImage( wsDisplay,win->WindowID,win->wGC,win->xImage, + 0,0, + ( win->Width - win->xImage->width ) / 2,( win->Height - win->xImage->height ) / 2, + win->xImage->width,win->xImage->height ); + } +} + +// ---------------------------------------------------------------------------------------------- +// Move window to x, y. +// ---------------------------------------------------------------------------------------------- +void wsMoveWindow( wsTWindow * win,int x, int y ) +{ + switch ( x ) + { + case -1: win->X=( wsMaxX / 2 ) - ( win->Width / 2 ); break; + case -2: win->X=wsMaxX - win->Width; break; + default: win->X=x; break; + } + switch ( y ) + { + case -1: win->Y=( wsMaxY / 2 ) - ( win->Height / 2 ); break; + case -2: win->Y=wsMaxY - win->Height; break; + default: win->Y=y; break; + } + + win->SizeHint.flags=PPosition; + win->SizeHint.x=win->X; + win->SizeHint.y=win->Y; + XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint ); + + XMoveWindow( wsDisplay,win->WindowID,win->X,win->Y ); +} + +// ---------------------------------------------------------------------------------------------- +// Resize window to sx, sy. +// ---------------------------------------------------------------------------------------------- +void wsResizeWindow( wsTWindow * win,int sx, int sy ) +{ + win->Width=sx; + win->Height=sy; + + win->SizeHint.flags=PSize; + win->SizeHint.width=win->Width; + win->SizeHint.height=win->Height; + if ( win->Property & wsMinSize ) + { + win->SizeHint.flags|=PMinSize; + win->SizeHint.min_width=win->Width; + win->SizeHint.min_height=win->Height; + } + if ( win->Property & wsMaxSize ) + { + win->SizeHint.flags|=PMaxSize; + win->SizeHint.max_width=win->Width; + win->SizeHint.max_height=win->Height; + } + XSetWMNormalHints( wsDisplay,win->WindowID,&win->SizeHint ); + XResizeWindow( wsDisplay,win->WindowID,sx,sy ); +} + +// ---------------------------------------------------------------------------------------------- +// Iconify window. +// ---------------------------------------------------------------------------------------------- +void wsIconify( wsTWindow win ) +{ XIconifyWindow( wsDisplay,win.WindowID,0 ); } + +// ---------------------------------------------------------------------------------------------- +// Move top the window. +// ---------------------------------------------------------------------------------------------- +void wsMoveTopWindow( wsTWindow * win ) +{ XRaiseWindow( wsDisplay,win->WindowID ); } +//{ XUnmapWindow( wsDisplay,win.WindowID ); XMapWindow( wsDisplay,win.WindowID ); } + +// ---------------------------------------------------------------------------------------------- +// Set window background to 'color'. +// ---------------------------------------------------------------------------------------------- +void wsSetBackground( wsTWindow * win,int color ) +{ XSetWindowBackground( wsDisplay,win->WindowID,color ); } + +void wsSetBackgroundRGB( wsTWindow * win,int r,int g,int b ) +{ + int color = 0; + switch ( wsOutMask ) + { + case wsRGB32: + case wsRGB24: color=( r << 16 ) + ( g << 8 ) + b; break; + case wsBGR32: + case wsBGR24: color=( b << 16 ) + ( g << 8 ) + r; break; + case wsRGB16: PACK_RGB16( r,g,b,color ); break; + case wsBGR16: PACK_RGB16( b,g,r,color ); break; + case wsRGB15: PACK_RGB15( r,g,b,color ); break; + case wsBGR15: PACK_RGB15( b,g,r,color ); break; + } + XSetWindowBackground( wsDisplay,win->WindowID,color ); +} + + +// ---------------------------------------------------------------------------------------------- +// Draw string at x,y with fc ( foreground color ) and bc ( background color ). +// ---------------------------------------------------------------------------------------------- +void wsDrawString( wsTWindow win,int x,int y,char * str,int fc,int bc ) +{ + XSetForeground( wsDisplay,win.wGC,bc ); + XFillRectangle( wsDisplay,win.WindowID,win.wGC,x,y, + XTextWidth( win.Font,str,strlen( str ) ) + 20, + win.FontHeight + 2 ); + XSetForeground( wsDisplay,win.wGC,fc ); + XDrawString( wsDisplay,win.WindowID,win.wGC,x + 10,y + 13,str,strlen( str ) ); +} + +// ---------------------------------------------------------------------------------------------- +// Calculation string width. +// ---------------------------------------------------------------------------------------------- +int wsTextWidth( wsTWindow win,char * str ) +{ return XTextWidth( win.Font,str,strlen( str ) ) + 20; } + +// ---------------------------------------------------------------------------------------------- +// Show / hide mouse cursor. +// ---------------------------------------------------------------------------------------------- +void wsVisibleMouse( wsTWindow * win,int m ) +{ + switch ( m ) + { + case wsShowMouseCursor: + if ( win->wsCursor != None ) + { + XFreeCursor( wsDisplay,win->wsCursor ); + win->wsCursor=None; + } + XDefineCursor( wsDisplay,win->WindowID,0 ); + break; + case wsHideMouseCursor: + win->wsCursor=XCreatePixmapCursor( wsDisplay,win->wsCursorPixmap,win->wsCursorPixmap,&win->wsColor,&win->wsColor,0,0 ); + XDefineCursor( wsDisplay,win->WindowID,win->wsCursor ); + break; + } + XFlush( wsDisplay ); +} + +int wsGetDepthOnScreen( void ) +{ + int bpp,ibpp; + XImage * mXImage; + XWindowAttributes attribs; + + mXImage=XGetImage( wsDisplay,wsRootWin,0,0,1,1,AllPlanes,ZPixmap ); + bpp=mXImage->bits_per_pixel; + + XGetWindowAttributes( wsDisplay,wsRootWin,&attribs ); + ibpp=attribs.depth; + mXImage=XGetImage( wsDisplay,wsRootWin,0,0,1,1,AllPlanes,ZPixmap ); + bpp=mXImage->bits_per_pixel; + if ( ( ibpp + 7 ) / 8 != ( bpp + 7 ) / 8 ) ibpp=bpp; + wsDepthOnScreen=ibpp; + wsRedMask=mXImage->red_mask; + wsGreenMask=mXImage->green_mask; + wsBlueMask=mXImage->blue_mask; + XDestroyImage( mXImage ); + return ibpp; +} + +void wsXDone( void ) +{ +// if ( wsSwitchedAnotherVideoMode ) wsChangeVideoMode( wsOldXResolution,wsOldYResolution ); +// if ( wsUseDGA ) XF86DGADirectVideo( wsDisplay,wsScreen,0 ); + XCloseDisplay( wsDisplay ); +} + +void wsVisibleWindow( wsTWindow * win,int show ) +{ + switch( show ) + { + case wsShowWindow: XMapWindow( wsDisplay,win->WindowID ); break; + case wsHideWindow: XUnmapWindow( wsDisplay,win->WindowID ); break; + } + XFlush( wsDisplay ); +} + +void wsDestroyImage( wsTWindow * win ) +{ + if ( win->xImage ) + { + XDestroyImage( win->xImage ); + if ( wsUseXShm ) + { + XShmDetach( wsDisplay,&win->Shminfo ); + shmdt( win->Shminfo.shmaddr ); + } + } + win->xImage=NULL; +} + +void wsCreateImage( wsTWindow * win ) +{ + int CompletionType = -1; + if ( wsUseXShm ) + { + CompletionType=XShmGetEventBase( wsDisplay ) + ShmCompletion; + win->xImage=XShmCreateImage( wsDisplay,win->VisualInfo.visual, + win->Attribs.depth,ZPixmap,NULL,&win->Shminfo,win->Width,win->Height ); + if ( win->xImage == NULL ) + { + fprintf( stderr,"[ws] shared memory extension error.\n" ); + exit( 0 ); + } +// #ifdef DEBUG +// fprintf( stderr,"[ws] Screen depth: %d\n",win->xImage->bits_per_pixel ); +// #endif + win->Shminfo.shmid=shmget( IPC_PRIVATE,win->xImage->bytes_per_line * win->xImage->height,IPC_CREAT|0777 ); + if ( win->Shminfo.shmid < 0 ) + { + XDestroyImage( win->xImage ); + fprintf( stderr,"[ws] shared memory extension error.\n" ); + exit( 0 ); + } + win->Shminfo.shmaddr=(char *)shmat( win->Shminfo.shmid,0,0 ); + + if ( win->Shminfo.shmaddr == ((char *) -1) ) + { + XDestroyImage( win->xImage ); + if ( win->Shminfo.shmaddr != ((char *) -1) ) shmdt( win->Shminfo.shmaddr ); + fprintf( stderr,"[ws] shared memory extension error.\n" ); + exit( 0 ); + } + win->xImage->data=win->Shminfo.shmaddr; + win->Shminfo.readOnly=0; + XShmAttach( wsDisplay,&win->Shminfo ); + shmctl( win->Shminfo.shmid,IPC_RMID,0 ); + } + else + { + win->xImage=XCreateImage( wsDisplay,win->VisualInfo.visual,win->Attribs.depth, + ZPixmap,0,0,win->Width,win->Height, + (wsDepthOnScreen == 3) ? 32 : wsDepthOnScreen, + 0 ); + if ( ( win->xImage->data=malloc( win->xImage->bytes_per_line * win->xImage->height ) ) == NULL ) + { + fprintf( stderr,"[ws] sorry, not enough memory for draw buffer.\n" ); + exit( 0 ); + } + } + win->ImageData=(unsigned char *)win->xImage->data; + win->ImageDataw=(unsigned short int *)win->xImage->data; + win->ImageDatadw=(unsigned int *)win->xImage->data; +} + +void wsResizeImage( wsTWindow * win ) +{ wsDestroyImage( win ); wsCreateImage( win ); } + +int wsGetOutMask( void ) +{ + if ( ( wsDepthOnScreen == 32 )&&( wsRedMask == 0xff0000 )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0x0000ff ) ) return wsRGB32; + if ( ( wsDepthOnScreen == 32 )&&( wsRedMask == 0x0000ff )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0xff0000 ) ) return wsBGR32; + if ( ( wsDepthOnScreen == 24 )&&( wsRedMask == 0xff0000 )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0x0000ff ) ) return wsRGB24; + if ( ( wsDepthOnScreen == 24 )&&( wsRedMask == 0x0000ff )&&( wsGreenMask == 0x00ff00 )&&( wsBlueMask == 0xff0000 ) ) return wsBGR24; + if ( ( wsDepthOnScreen == 16 )&&( wsRedMask == 0xf800 )&&( wsGreenMask == 0x7e0 )&&( wsBlueMask == 0x1f ) ) return wsRGB16; + if ( ( wsDepthOnScreen == 16 )&&( wsRedMask == 0x1f )&&( wsGreenMask == 0x7e0 )&&( wsBlueMask == 0xf800 ) ) return wsBGR16; + if ( ( wsDepthOnScreen == 15 )&&( wsRedMask == 0x7c00 )&&( wsGreenMask == 0x3e0 )&&( wsBlueMask == 0x1f ) ) return wsRGB15; + if ( ( wsDepthOnScreen == 15 )&&( wsRedMask == 0x1f )&&( wsGreenMask == 0x3e0 )&&( wsBlueMask == 0x7c00 ) ) return wsBGR15; + return 0; +} + +void wsSetTitle( wsTWindow * win,char * name ) +{ XStoreName( wsDisplay,win->WindowID,name ); } + +void wsSetMousePosition( wsTWindow * win,int x, int y ) +{ XWarpPointer( wsDisplay,wsRootWin,win->WindowID,0,0,0,0,x,y ); } + +static int dpms_disabled=0; +static int timeout_save=0; + +void wsScreenSaverOn( Display *mDisplay ) +{ + int nothing; + if ( dpms_disabled ) + { + if ( DPMSQueryExtension( mDisplay,¬hing,¬hing ) ) + { + if ( !DPMSEnable( mDisplay ) ) fprintf( stderr,"DPMS not available ?\n" ); // restoring power saving settings + else + { + // DPMS does not seem to be enabled unless we call DPMSInfo + BOOL onoff; + CARD16 state; + DPMSInfo( mDisplay,&state,&onoff ); + if ( onoff ) fprintf( stderr,"Successfully enabled DPMS.\n" ); + else fprintf( stderr,"Could not enable DPMS.\n" ); + } + } + } + + if ( timeout_save ) + { + int dummy, interval, prefer_blank, allow_exp; + XGetScreenSaver( mDisplay,&dummy,&interval,&prefer_blank,&allow_exp ); + XSetScreenSaver( mDisplay,timeout_save,interval,prefer_blank,allow_exp ); + XGetScreenSaver( mDisplay,&timeout_save,&interval,&prefer_blank,&allow_exp ); + } +} + +void wsScreenSaverOff( Display * mDisplay ) +{ + int interval,prefer_blank,allow_exp,nothing; + + if ( DPMSQueryExtension( mDisplay,¬hing,¬hing ) ) + { + BOOL onoff; + CARD16 state; + DPMSInfo( mDisplay,&state,&onoff ); + if ( onoff ) + { + Status stat; + fprintf( stderr,"Disabling DPMS.\n" ); + dpms_disabled=1; + stat=DPMSDisable( mDisplay ); // monitor powersave off + fprintf( stderr,"stat: %d.\n",stat ); + } + } + XGetScreenSaver( mDisplay,&timeout_save,&interval,&prefer_blank,&allow_exp ); + if ( timeout_save ) XSetScreenSaver( mDisplay,0,interval,prefer_blank,allow_exp ); // turning off screensaver +} + +void wsSetShape( wsTWindow * win,char * data ) +{ +#ifdef HAVE_XSHAPE + if ( ( !wsUseXShape )||( !data ) ) return; + win->Mask=XCreateBitmapFromData( wsDisplay,win->WindowID,data,win->Width,win->Height ); + XShapeCombineMask( wsDisplay,win->WindowID,ShapeBounding,0,0,win->Mask,ShapeSet ); + XFreePixmap( wsDisplay,win->Mask ); +#endif +} + +#include "wsmkeys.h"