/* TVscreen Widget for Bt848 frame grabber driver Copyright (C) 1996,97 Marcus Metzler (mocm@thp.uni-koeln.de) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * TVscreen.c */ #include "TVscreenP.h" #include #include /*#define DEBUG*/ #define DEFAULT_WIDTH 320 #define DEFAULT_HEIGHT 240 #define PAL_WIDTH 922 #define PAL_HEIGHT 576 #define NTSC_WIDTH 640 #define NTSC_HEIGHT 480 #define DEFAULT_DELAY 100 #define offset(field) XtOffsetOf(TVscreenRec, field) static XtResource resources[] = { { XtNdevName, XtCDevName, XtRString, sizeof(String), offset(TVscreen.devname), XtRImmediate, NULL }, { XtNcap, XtCCap, XtRBoolean, sizeof(Boolean), offset(TVscreen.CAP_ON), XtRImmediate, (XtPointer) False }, { XtNnorm, XtCNorm, XtRInt, sizeof(int), offset(TVscreen.NORM), XtRImmediate, (XtPointer) DNORM }, { XtNfreq, XtCFreq, XtRInt, sizeof(int), offset(TVscreen.FREQ), XtRImmediate, (XtPointer) 0 }, { XtNinputSelect, XtCInputSelect, XtRInt, sizeof(int), offset(TVscreen.INPUT), XtRImmediate, (XtPointer) DIN }, { XtNdelay, XtCDelay, XtRInt, sizeof(int), offset(TVscreen.DELAY), XtRImmediate, (XtPointer) DEFAULT_DELAY }, { XtNbright, XtCBright, XtRInt, sizeof(int), offset(TVscreen.Bright), XtRImmediate, (XtPointer) DBRI }, { XtNcol, XtCCol, XtRInt, sizeof(int), offset(TVscreen.Color), XtRImmediate, (XtPointer) DCOL }, { XtNhue, XtCHue, XtRInt, sizeof(int), offset(TVscreen.Hue), XtRImmediate, (XtPointer) DHUE }, { XtNcontrast, XtCContrast, XtRInt, sizeof(int), offset(TVscreen.Contrast), XtRImmediate, (XtPointer) DCONTRAST }, { XtNrefresh, XtCRefresh, XtRBoolean, sizeof(Boolean), offset(TVscreen.REFRESH), XtRImmediate, (XtPointer) True }, { XtNbpp, XtCBpp, XtRInt, sizeof(int), offset(TVscreen.bpp), XtRImmediate, (XtPointer) 0 }, { XtNvis, XtCVis, XtRString, sizeof(String), offset(TVscreen.visname), XtRImmediate, NULL }, { XtNsnap, XtCSnap, XtRBoolean, sizeof(Boolean), offset(TVscreen.snap), XtRImmediate, (XtPointer) False }, { XtNrealW, XtCRealW, XtRInt, sizeof(int), offset(TVscreen.realw), XtRImmediate, (XtPointer) 0 }, { XtNaudio, XtCAudio, XtRInt, sizeof(int), offset(TVscreen.audio), XtRImmediate, (XtPointer) 1 }, }; /* Declaration of methods */ static void Initialize(); static void Realize(); static Boolean SetValues(); static void destroy(); static XtGeometryResult QueryGeometry(); static int rx,ry,rh,rw; /* the following are actions of TVscreen */ static void pConfig(); static void addclip(); static void maketab(); static int getclip(); static void bt848_dma(); static void SetGeo(); static void cap(); static void setmaxsize(); static void ref(); static void refresh(); XErrorHandler xerror(); static Window lastrwin; static XtIntervalId timer; static Boolean Move=False; TVscreenClassRec tvscreenClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &coreClassRec, /* class_name */ "TVscreen", /* widget_size */ sizeof(TVscreenRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeCompressMultiple, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ destroy, /* resize */ NULL, /* expose */ NULL, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ QueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* extension */ 0, }, }; WidgetClass tvscreenWidgetClass = (WidgetClass) & tvscreenClassRec; /* Realize */ static void Realize(Widget w, XtValueMask *value_mask, XSetWindowAttributes *attributes) { TVscreenWidget tw=(TVscreenWidget) w; XtCreateWindow(w, (unsigned int) InputOutput, tw->TVscreen.visual, *value_mask, attributes); if (tw->TVscreen.CAP_ON){ #ifndef NOCARD struct video_channel vc; #endif tw->TVscreen.Change=TRUE; #ifndef NOCARD vc.channel = tw->TVscreen.INPUT; vc.norm = tw->TVscreen.NORM; if(ioctl(tw->TVscreen.fbttv, VIDIOCSWIN, &tw->TVscreen.vwin)) perror("VIDIOCSWIN"); /* Set the input */ if(ioctl(tw->TVscreen.fbttv, VIDIOCSCHAN, &vc)) perror("VIDIOCSCHAN"); /* Set the frequency */ if(ioctl(tw->TVscreen.fbttv, VIDIOCSFREQ, &tw->TVscreen.frequency)) perror("VIDIOCSFREQ"); #endif } } XErrorHandler xerror(Display *dpy, XErrorEvent *event) { switch (event->error_code){ case BadWindow: #ifdef DEBUG printf("Bad Window ingnored\n"); #endif return 0 ; break; case BadMatch: #ifdef DEBUG printf("BadMatch ingnored\n"); #endif return 0 ; break; case BadColor: #ifdef DEBUG printf("BadColor ingnored\n"); #endif return 0 ; break; default: return 0; } } void ref(TVscreenWidget w) { #ifndef NOCARD int scr,depth; XSetWindowAttributes xswa; unsigned long mask; Window rwin,rootW; Display *disp; if (w->TVscreen.REFRESH){ disp=XtDisplay((Widget)w); scr=DefaultScreen(disp); rootW= RootWindow(disp, scr); depth=w->core.depth; xswa.override_redirect = True; xswa.backing_store = NotUseful; xswa.save_under = False; xswa.background_pixel=BlackPixel(disp,scr); xswa.backing_store=NotUseful; mask = (CWBackPixel | CWSaveUnder | CWBackingStore| CWOverrideRedirect ); if(Move){ rwin = XCreateWindow(disp,rootW,0, 0, w->TVscreen.vbuf.width,w->TVscreen.vbuf.height, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &xswa); Move=False; } else { rwin = XCreateWindow(disp,rootW, w->TVscreen.vwin.x-80, w->TVscreen.vwin.y-80, w->TVscreen.vwin.width+80,w->TVscreen.vwin.height+80, 0,CopyFromParent, InputOutput, CopyFromParent, mask, &xswa); } lastrwin=rwin; XMapWindow(disp, rwin); XUnmapWindow(disp, rwin); XDestroyWindow(disp, rwin); } #endif } static void refresh(w) TVscreenWidget w; { if (timer) XtRemoveTimeOut(timer); timer=XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w), w->TVscreen.DELAY,(XtTimerCallbackProc)ref,w); } #ifndef NOCARD static void addclip(cr,ncr,x,y,w,h) struct video_clip *cr; int *ncr; uint x,y,w,h; { cr[*ncr].x=x; cr[*ncr].y=y; cr[*ncr].width=w; cr[*ncr].height=h; *ncr=*ncr+1; } #endif static void maketab(w, ncr) TVscreenWidget w; int ncr; { #ifndef NOCARD w->TVscreen.vwin.clips=w->TVscreen.cliprecs; w->TVscreen.vwin.clipcount=ncr; /* * Set the clipping up. */ if(ioctl(w->TVscreen.fbttv, VIDIOCSWIN, &w->TVscreen.vwin)) perror("set clipping"); #endif } #ifndef NOCARD static int getclip(w) TVscreenWidget w; { int ncr=0; int x,y,x2,y2,wx,wy; uint ww,wh; struct video_window vwin; struct video_buffer vbuf; Display *disp; XWindowAttributes wts; Window parent,win,parent2, root, rroot, *children, swin; uint nchildren, i; struct video_clip *cr; Widget widpar; if (!XtIsRealized((Widget)w)) return; disp=XtDisplay((Widget)w); vwin=w->TVscreen.vwin; vbuf=w->TVscreen.vbuf; widpar=(Widget) w; while(XtParent(widpar)) widpar=XtParent(widpar); if((win=XtWindow(widpar))==None) return; XQueryTree(disp,win, &rroot, &parent, &children, &nchildren); if(nchildren) XFree((char *)children); cr=w->TVscreen.cliprecs; wx=vwin.x; wy=vwin.y; wh=vwin.height; ww=vwin.width; root=DefaultRootWindow(disp); swin=win; while (parent!=root) { swin=parent; XQueryTree(disp, swin, &rroot, &parent, &children, &nchildren); if (nchildren) XFree((char *) children); } XQueryTree(disp, root, &rroot, &parent2, &children, &nchildren); for (i=0; iTVscreen.vwin; wh=vwin.height; ww=vwin.width; if (!(wts.map_state & IsViewable)) return False; x=wts.x-vwin.x; y=wts.y-vwin.y; x2=x+wts.width+2*wts.border_width-1; y2=y+wts.height+2*wts.border_width-1; if ((x2 < 0) || (x >= (int)ww) || (y2 < 0) || (y >= (int)wh)) return False; return True; } #endif static void bt848_dma(w,data) Widget w; uint data; { #ifndef NOCARD int f; TVscreenWidget cw = (TVscreenWidget) w; f=cw->TVscreen.fbttv; /* ioctl(f, BTTV_DMA, &data);*/ #endif } static void cap(w,W) TVscreenWidget w; int W; { if( XtIsRealized((Widget)w)) { #ifndef NOCARD int one=1; int zero=0; if(W && w->TVscreen.CAP_ON) { if(ioctl(w->TVscreen.fbttv, VIDIOCCAPTURE, &one)) perror("capture on"); } else { if(ioctl(w->TVscreen.fbttv, VIDIOCCAPTURE, &zero)) perror("capture off"); } #endif } } static void setmaxsize(cw) TVscreenWidget cw; { uint max_h,max_w; switch (cw->TVscreen.NORM){ case PAL: case SECAM: max_w=PAL_WIDTH; max_h=PAL_HEIGHT; break; case NTSC: max_w=NTSC_WIDTH; max_h=NTSC_HEIGHT; break; default: max_w=DEFAULT_WIDTH; max_h=DEFAULT_HEIGHT; break; } cw->TVscreen.max_width=max_w; cw->TVscreen.max_height=max_h; } /* --------------------------------------------------------------------- */ #define AUDIO_AUTO 0 #define AUDIO_MONO 1 #define AUDIO_STEREO 2 #define AUDIO_BILANG1 3 #define AUDIO_BILANG2 4 static int amodes[5] = { 0, VIDEO_SOUND_MONO, VIDEO_SOUND_STEREO, VIDEO_SOUND_LANG1, VIDEO_SOUND_LANG2 }; static char *audio_mode_name[] = { "auto", "mono", "stereo", "bi-lang 1", "bi-lang 2", NULL }; void set_audiomode(TVscreenWidget w, int mode) { struct video_audio va; if (w->TVscreen.audio_state != mode) { #ifdef AUDIO_DEBUG fprintf(stderr,"set_audiomode: switch to %s\n",audio_mode_name[mode]); #endif va.audio=0; va.flags=0; va.mode=amodes[mode]; ioctl(w->TVscreen.fbttv,VIDIOCSAUDIO,&va); w->TVscreen.audio_state = mode; } } /* for "audio = auto" */ void audio_watch(XtPointer client_data, XtIntervalId *id) { } static void Initialize(treq, tnew, args, num_args) Widget treq, tnew; ArgList args; Cardinal *num_args; { Widget parent; char *bttvname; Screen *screen; Window rootw; int col; uint rwidth; TVscreenWidget new = (TVscreenWidget) tnew; int major, minor, bank, ram; Display *disp; ushort i,r,rr; Colormap cmap; XColor *my; Visual *v; unsigned char *tm; int msize,ii; struct video_mbuf mbuf; #ifndef NOCARD if(new->TVscreen.devname) bttvname=new->TVscreen.devname; else bttvname="/dev/video"; new->TVscreen.devname=bttvname; if ((new->TVscreen.fbttv=open(bttvname,O_RDWR)) < 0) { printf("Cannot open %s\n",bttvname); exit(1); } if(ioctl(new->TVscreen.fbttv, VIDIOCGWIN, &(new->TVscreen.vwin))) perror("get window"); if(ioctl(new->TVscreen.fbttv, VIDIOCGFBUF, &(new->TVscreen.vbuf))) perror("get frame buffer"); if(ioctl(new->TVscreen.fbttv, VIDIOCGTUNER, &(new->TVscreen.vtuner))) perror("get tuner"); new->TVscreen.vwin.width=DEFAULT_WIDTH; new->TVscreen.vwin.height=DEFAULT_HEIGHT; new->TVscreen.vwin.x=0; new->TVscreen.vwin.y=0; new->TVscreen.vbuf.width=XtScreen(tnew)->width; new->TVscreen.vbuf.height=XtScreen(tnew)->height; new->TVscreen.vbuf.base=0; new->TVscreen.vwin.clipcount=0; rwidth=new->TVscreen.vbuf.width; disp=XtDisplay(tnew); #ifndef NODGA if (XF86DGAQueryVersion(disp, &major, &minor)) XF86DGAGetVideoLL(disp, DefaultScreen(disp), &(new->TVscreen.vbuf.base), &rwidth, &bank, &ram); else #endif #endif if (rwidth<960) if (rwidth>640) rwidth=960; if (new->TVscreen.realw) rwidth=new->TVscreen.realw; new->TVscreen.dual=find_visual(tnew,new->TVscreen.visname, &new->TVscreen.visual); v= new->TVscreen.visual; #ifndef NOCARD if (new->TVscreen.bpp) new->TVscreen.vbuf.depth=new->TVscreen.bpp; else new->TVscreen.vbuf.depth=tnew->core.depth; if (new->TVscreen.dual) new->TVscreen.vbuf.depth=32; new->TVscreen.vbuf.bytesperline=rwidth*(0x38&(new->TVscreen.vbuf.depth+1))/8; if(ioctl(new->TVscreen.fbttv, VIDIOCSFBUF, &new->TVscreen.vbuf)) { perror("set frame buffer"); exit(1); } /* Alloc memory for snapshot */ if(ioctl(new->TVscreen.fbttv, VIDIOCGMBUF, &(new->TVscreen.mbuf))) perror("get mbuf"); msize = new->TVscreen.mbuf.size; /*printf("msize: 0x%08x\n",msize);*/ tm=(unsigned char *)mmap(0,msize,PROT_READ|PROT_WRITE, MAP_SHARED,new->TVscreen.fbttv,0); if (tm==(unsigned char *)-1) { printf("Cannot mmap memory for snapshot\n"); exit(1); } #ifdef DEBUG printf("tm: 0x%08x\n", (int) tm); #endif new->TVscreen.TargetMem=tm; #endif new->TVscreen.CMSET=False; if (v->class == PseudoColor){ new->TVscreen.CMSET=True; my=new->TVscreen.colors; for (i=0;i<256;i++){ my[i].pixel=i; my[i].flags = DoRed | DoGreen | DoBlue; } XQueryColors(disp, new->core.colormap, my, 256); cmap=XCreateColormap(disp, DefaultRootWindow(disp),v, AllocAll); new->core.colormap=cmap; for (i=0;i<225;i++){ /* Set Colors 16 - 240 */ r=i%25; my[i+16].green =(65535*(i/25)/8); my[i+16].red =(65535*(r/5)/4); rr=r%5; my[i+16].blue =(65535*rr/4); } XStoreColors(disp,cmap,my,256); } new->core.width=DEFAULT_WIDTH; new->core.height=DEFAULT_HEIGHT; parent=tnew; while (parent->core.parent){ parent=parent->core.parent; } XtAddEventHandler(tnew,SubstructureNotifyMask | VisibilityChangeMask | StructureNotifyMask | ExposureMask | EnterWindowMask |LeaveWindowMask, FALSE,pConfig,new); XtAddEventHandler(parent,SubstructureNotifyMask | VisibilityChangeMask | StructureNotifyMask | ExposureMask, FALSE,pConfig,new); rootw=DefaultRootWindow(XtDisplay(tnew)); XSelectInput(XtDisplay(tnew),rootw, VisibilityChangeMask | SubstructureNotifyMask | ExposureMask |StructureNotifyMask); XtRegisterDrawable(XtDisplay(tnew),rootw,tnew); new->TVscreen.Change=FALSE; setmaxsize(new); new->core.background_pixel=BlackPixel(XtDisplay(new), DefaultScreen(XtDisplay(new))); timer=0; XSetErrorHandler((XErrorHandler) xerror); } static void SetGeo(cw) TVscreenWidget cw; { #ifndef NOCARD Widget parent; Position x,y; int dx,dy; Boolean CHECK; int oldx,oldy,oldw,oldh; oldx=cw->TVscreen.vwin.x; oldy=cw->TVscreen.vwin.y; oldw=cw->TVscreen.vwin.width; oldh=cw->TVscreen.vwin.height; CHECK=cw->TVscreen.Change; cw->TVscreen.vwin.flags=0; if (!XtIsRealized((Widget) cw)) return; parent=(Widget) cw; while(XtParent(parent)) parent=XtParent(parent); XtTranslateCoords((Widget)cw,0,0,&x,&y); if(oldh!=cw->core.height) CHECK=TRUE; if(oldw!=cw->core.width) CHECK=TRUE; dx=0;dy=0; if (cw->core.width > cw->TVscreen.max_width){ dx=(cw->core.width- oldw)/2; if(oldw != cw->TVscreen.max_width){ CHECK=TRUE; cw->TVscreen.vwin.width=cw->TVscreen.max_width & ~3; } } else { cw->TVscreen.vwin.width=cw->core.width & ~3; } if (cw->core.height > cw->TVscreen.max_height) { dy=(cw->core.height- cw->TVscreen.vwin.height)/2; if(oldh != cw->TVscreen.max_height) { CHECK=TRUE; cw->TVscreen.vwin.height=cw->TVscreen.max_height & ~3; } } else cw->TVscreen.vwin.height=cw->core.height & ~3; if(oldx!=x+dx){ Move=True; CHECK=True; } if(oldy!=y+dy){ Move=True; CHECK=True; } if ((cw->TVscreen.vbuf.depth==24)&&((x+dx)&3)) { parent->core.x=parent->core.x-((x+dx) &3); } else if ((cw->TVscreen.vbuf.depth==16)&&((x+dx)&1)) { parent->core.x=parent->core.x-((x+dx) &1); } else if ((cw->TVscreen.vbuf.depth==15)&&((x+dx)&1)) { parent->core.x=parent->core.x-((x+dx) &1); } if ((y+dy)&1) { parent->core.y=parent->core.y-((y+dy) &1); } if(CHECK) { cw->TVscreen.vwin.x=x+dx; cw->TVscreen.vwin.y=y+dy; if (cw->TVscreen.CAP_ON) { if(ioctl(cw->TVscreen.fbttv, VIDIOCSWIN, &cw->TVscreen.vwin)) perror("set clipped window"); } } if(cw->TVscreen.CAP_ON && CHECK) getclip(cw); if(!cw->TVscreen.Change && cw->TVscreen.CAP_ON && cw->TVscreen.Fresh) { refresh(cw); cw->TVscreen.Fresh=False; } cw->TVscreen.Change=FALSE; #endif } static Boolean SetValues(current, request, new, args, num_args) Widget current, request, new; ArgList args; Cardinal *num_args; { Widget parent; TVscreenWidget curcw = (TVscreenWidget) current; TVscreenWidget newcw = (TVscreenWidget) new; Boolean do_redisplay = False; int pictmod=0; struct video_picture vp; struct video_channel vc; #ifndef NOCARD if (newcw->TVscreen.CAP_ON){ if (!curcw->TVscreen.CAP_ON) { getclip(current); do_redisplay =True; newcw->TVscreen.Change=TRUE; SetGeo(newcw); } } else { vc.channel=newcw->TVscreen.INPUT; vc.norm=newcw->TVscreen.NORM; if (curcw->TVscreen.CAP_ON) { cap(newcw,0); system("xrefresh"); } if(ioctl(newcw->TVscreen.fbttv, VIDIOCSCHAN, &vc)) perror("change tuner"); } if (newcw->TVscreen.frequency!=(ushort) newcw->TVscreen.FREQ) { newcw->TVscreen.frequency=newcw->TVscreen.FREQ; if(ioctl(newcw->TVscreen.fbttv, VIDIOCSFREQ, &newcw->TVscreen.frequency)) perror("change frequency"); } if (curcw->TVscreen.NORM != newcw->TVscreen.NORM || curcw->TVscreen.INPUT !=newcw->TVscreen.INPUT) { vc.channel=newcw->TVscreen.INPUT; vc.norm=newcw->TVscreen.NORM; newcw->TVscreen.Change=TRUE; setmaxsize(newcw); SetGeo(newcw); if (newcw->TVscreen.NORM==NTSC) newcw->TVscreen.Fresh=TRUE; SetGeo(newcw); if(ioctl(newcw->TVscreen.fbttv, VIDIOCSCHAN, &vc)) perror("change norm"); } if(ioctl(newcw->TVscreen.fbttv, VIDIOCGPICT, &vp)==-1) perror("get picture params"); if (curcw->TVscreen.Bright !=newcw->TVscreen.Bright) { vp.brightness=(newcw->TVscreen.Bright+128)<<8; pictmod=1; } if (curcw->TVscreen.Color !=newcw->TVscreen.Color) { vp.colour=newcw->TVscreen.Color<<7; pictmod=1; } if (curcw->TVscreen.Hue !=newcw->TVscreen.Hue) { vp.hue=((unsigned int)(newcw->TVscreen.Hue+128))<<8; pictmod=1; } if (curcw->TVscreen.Contrast !=newcw->TVscreen.Contrast) { vp.contrast=newcw->TVscreen.Contrast<<7; pictmod=1; } if(pictmod) { if(ioctl(newcw->TVscreen.fbttv, VIDIOCSPICT, &vp)) perror("set picture params"); } if (curcw->TVscreen.audio != newcw->TVscreen.audio || newcw->TVscreen.audio == 0){ set_audiomode(newcw,newcw->TVscreen.audio); } #endif return do_redisplay; } static void pConfig(wi,client_data,event) Widget wi; XtPointer client_data; XEvent *event; { int fbttv; TVscreenWidget w=(TVscreenWidget) client_data; static Boolean UNMAPPED=False; XWindowAttributes wts1,wts2; Window checkw1,checkw2,wwin; Widget parent; if (!XtIsRealized((Widget)w)||(wwin=XtWindow((Widget)w)) == None) return; parent=(Widget)w; while (parent->core.parent){ parent=parent->core.parent; } fbttv=w->TVscreen.fbttv; w->TVscreen.Fresh=True; cap(w,0); checkw1=event->xmap.window; checkw2=event->xany.window; if (w->TVscreen.CAP_ON) { if ( wwin==checkw1 || wwin==checkw2 ) w->TVscreen.Fresh=False; else { if (checkw1){ XGetWindowAttributes(XtDisplay(w), checkw1, &wts1); #ifndef NOCARD if(!onscreen(w,wts1)) w->TVscreen.Fresh=False; #endif } if (checkw2) { XGetWindowAttributes(XtDisplay(w), checkw2, &wts2); #ifndef NOCARD if(!onscreen(w,wts2)) w->TVscreen.Fresh=False; #endif } } } switch (event->type) { case VisibilityNotify: switch (event->xvisibility.state) { case VisibilityUnobscured: if (w->TVscreen.CAP_ON) { if (checkw2 != DefaultRootWindow(XtDisplay(w))) { w->TVscreen.Change=TRUE; SetGeo(w); } } break; case VisibilityFullyObscured: if (checkw2 != DefaultRootWindow(XtDisplay(w))) cap(w,0); break; case VisibilityPartiallyObscured: if (w->TVscreen.CAP_ON) { if (checkw2 != DefaultRootWindow(XtDisplay(w))) { w->TVscreen.Change=TRUE; SetGeo(w); } } break; } break; case MapNotify: if ((DefaultRootWindow(XtDisplay(w)) != checkw2) && UNMAPPED){ UNMAPPED=False; w->TVscreen.CAP_ON=True; cap(w,1); if ( w->TVscreen.Fresh ){ refresh(w); } } if ((lastrwin != checkw1) && (w->TVscreen.CAP_ON) ){ if ( w->TVscreen.Fresh ){ refresh(w); } } break; case ConfigureNotify: cap(w,0); SetGeo(w); break; case DestroyNotify: if (wwin == checkw2){ #ifdef DEBUG printf("Destroy\n"); #endif cap(w,0); } break; case UnmapNotify: if (DefaultRootWindow(XtDisplay(w)) != checkw2){ cap(w,0); if (w->TVscreen.CAP_ON) UNMAPPED=True; if (w->TVscreen.CAP_ON) { if ( w->TVscreen.Fresh ){ refresh(w); #ifdef DEBUG printf("UnmapNotify refresh\n"); #endif } } w->TVscreen.CAP_ON=False; #ifdef DEBUG printf("Unmap\n"); #endif } else if (wwin != event->xmap.window) if(w->TVscreen.CAP_ON) { #ifndef NOCARD getclip(w); #endif } break; case EnterNotify: if (wwin == checkw2){ if (w->TVscreen.CAP_ON && w->TVscreen.CMSET){ XInstallColormap(XtDisplay(w),w->core.colormap); } } break; case LeaveNotify: /* Looks better this way */ /* if (wwin == checkw2){ if (w->TVscreen.CAP_ON && w->TVscreen.CMSET){ XUninstallColormap(XtDisplay(w),w->core.colormap); } } */ break; } if(w->TVscreen.CAP_ON) { cap(w,1); } } static XtGeometryResult QueryGeometry(w, proposed, answer) Widget w; XtWidgetGeometry *proposed, *answer; { int reqm; TVscreenWidget cw = (TVscreenWidget) w; /* set fields we care about */ reqm= CWWidth | CWHeight; answer->request_mode =reqm; /* initial width and height */ #ifndef NOCARD /* initial width and height */ answer->width = (cw->TVscreen.vwin.width > cw->TVscreen.max_width) ? cw->TVscreen.max_width : cw->TVscreen.vwin.width; answer->height = (cw->TVscreen.vwin.height > cw->TVscreen.max_height) ? cw->TVscreen.max_height : cw->TVscreen.vwin.height; if (cw->TVscreen.vbuf.depth==24) { answer->width = answer->width & ~3; answer->height = answer->height & ~3; } else if (cw->TVscreen.vbuf.depth==16) { answer->width = answer->width & ~1; answer->height = answer->height & ~1; } else if (cw->TVscreen.vbuf.depth==15) { answer->width = answer->width & ~1; answer->height = answer->height & ~1; } answer->width = DEFAULT_WIDTH; answer->height = DEFAULT_HEIGHT; #endif if ( ((proposed->request_mode & (reqm)) == (reqm)) && proposed->width == answer->width && proposed->height == answer->height) return XtGeometryYes; else if (answer->width == cw->core.width && answer->height == cw->core.height) return XtGeometryNo; else return XtGeometryAlmost; } static void destroy(nw) Widget nw; { Widget parent; Window rootw; TVscreenWidget w=(TVscreenWidget) nw; w->TVscreen.CAP_ON=False; cap(w,0); if(w->TVscreen.CMSET){ XFreeColormap(XtDisplay(w),w->core.colormap); } parent=nw; while (parent->core.parent){ parent=parent->core.parent; } XtRemoveEventHandler(nw,SubstructureNotifyMask | VisibilityChangeMask | StructureNotifyMask | ExposureMask | EnterWindowMask |LeaveWindowMask, FALSE,pConfig,w); XtRemoveEventHandler(parent,SubstructureNotifyMask | VisibilityChangeMask | StructureNotifyMask | ExposureMask, FALSE,pConfig,w); if (timer) XtRemoveTimeOut(timer); rootw=DefaultRootWindow(XtDisplay(nw)); XtUnregisterDrawable(XtDisplay(nw),rootw); close(w->TVscreen.fbttv); #ifdef DEBUG printf("Widget destroyed\n"); #endif }