static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char *t) { pa_x11_wrapper*w; Display *d; if (!(d = XOpenDisplay(name))) { pa_log("XOpenDisplay() failed"); return NULL; } w = pa_xnew(pa_x11_wrapper, 1); PA_REFCNT_INIT(w); w->core = c; w->property_name = pa_xstrdup(t); w->display = d; PA_LLIST_HEAD_INIT(pa_x11_client, w->clients); PA_LLIST_HEAD_INIT(pa_x11_internal, w->internals); w->defer_event = c->mainloop->defer_new(c->mainloop, defer_event, w); w->io_event = c->mainloop->io_new(c->mainloop, ConnectionNumber(d), PA_IO_EVENT_INPUT, display_io_event, w); XAddConnectionWatch(d, x11_watch, (XPointer) w); pa_assert_se(pa_shared_set(c, w->property_name, w) >= 0); return w; }
bool x11_init(XRESOURCES* res, CFG* config){ Window root; XSetWindowAttributes window_attributes; unsigned width, height; Atom wm_state_fullscreen; int xdbe_major, xdbe_minor; XTextProperty window_name; pid_t pid = getpid(); //allocate some structures XSizeHints* size_hints = XAllocSizeHints(); XWMHints* wm_hints = XAllocWMHints(); XClassHint* class_hints = XAllocClassHint(); if(!size_hints || !wm_hints || !class_hints){ fprintf(stderr, "Failed to allocate X data structures\n"); return false; } //x data initialization res->display = XOpenDisplay(NULL); if(!(res->display)){ fprintf(stderr, "Failed to open display\n"); XFree(size_hints); XFree(wm_hints); XFree(class_hints); return false; } if(config->double_buffer){ config->double_buffer = (XdbeQueryExtension(res->display, &xdbe_major, &xdbe_minor) != 0); } else{ config->double_buffer = false; } errlog(config, LOG_INFO, "Double buffering %s\n", config->double_buffer ? "enabled":"disabled"); res->screen = DefaultScreen(res->display); root = RootWindow(res->display, res->screen); //start xft if(!XftInit(NULL)){ fprintf(stderr, "Failed to initialize Xft\n"); XFree(size_hints); XFree(wm_hints); XFree(class_hints); return false; } //set up colors res->text_color = colorspec_parse(config->text_color, res->display, res->screen); res->bg_color = colorspec_parse(config->bg_color, res->display, res->screen); res->debug_color = colorspec_parse(config->debug_color, res->display, res->screen); //set up window params window_attributes.background_pixel = res->bg_color.pixel; window_attributes.cursor = None; window_attributes.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; width = DisplayWidth(res->display, res->screen); height = DisplayHeight(res->display, res->screen); //create window res->main = XCreateWindow(res->display, root, 0, 0, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, CWBackPixel | CWCursor | CWEventMask, &window_attributes); //set window properties if(XStringListToTextProperty(&(config->window_name), 1, &window_name) == 0){ fprintf(stderr, "Failed to create string list, aborting\n"); return false; } wm_hints->flags = 0; class_hints->res_name = "xecho"; class_hints->res_class = "xecho"; XSetWMProperties(res->display, res->main, &window_name, NULL, NULL, 0, NULL, wm_hints, class_hints); XFree(window_name.value); XFree(size_hints); XFree(wm_hints); XFree(class_hints); //set fullscreen mode if(!config->windowed){ wm_state_fullscreen = XInternAtom(res->display, "_NET_WM_STATE_FULLSCREEN", False); XChangeProperty(res->display, res->main, XInternAtom(res->display, "_NET_WM_STATE", False), XA_ATOM, 32, PropModeReplace, (unsigned char*) &wm_state_fullscreen, 1); } XChangeProperty(res->display, res->main, XInternAtom(res->display, "_NET_WM_PID", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&pid, 1); //allocate back drawing buffer if(config->double_buffer){ res->back_buffer = XdbeAllocateBackBufferName(res->display, res->main, XdbeBackground); } //make xft drawable from window res->drawable = XftDrawCreate(res->display, (config->double_buffer?res->back_buffer:res->main), DefaultVisual(res->display, res->screen), DefaultColormap(res->display, res->screen)); if(!res->drawable){ fprintf(stderr, "Failed to allocate drawable\n"); return false; } //register for WM_DELETE_WINDOW messages res->wm_delete = XInternAtom(res->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(res->display, res->main, &(res->wm_delete), 1); //map window XMapRaised(res->display, res->main); //get x socket fds if(!xfd_add(&(res->xfds), XConnectionNumber(res->display))){ fprintf(stderr, "Failed to allocate xfd memory\n"); return false; } if(XAddConnectionWatch(res->display, xconn_watch, (void*)(&(res->xfds))) == 0){ fprintf(stderr, "Failed to register connection watch procedure\n"); return false; } return true; }
/** ** X11 initialize. */ global void CloneInitDisplay(void) { int i; Window window; XGCValues gcvalue; XSizeHints hints; XWMHints wmhints; XClassHint classhint; XSetWindowAttributes attributes; int shm_major,shm_minor; Bool pixmap_support; XShmSegmentInfo shminfo; XVisualInfo xvi; XPixmapFormatValues *xpfv; if( !(TheDisplay=XOpenDisplay(NULL)) ) { fprintf(stderr,"Cannot connect to X-Server.\n"); exit(-1); } TheScreen=DefaultScreen(TheDisplay); // I need shared memory pixmap extension. if( !XShmQueryVersion(TheDisplay,&shm_major,&shm_minor,&pixmap_support) ) { fprintf(stderr,"SHM-Extensions required.\n"); exit(-1); } if( !pixmap_support ) { fprintf(stderr,"SHM-Extensions with pixmap supported required.\n"); exit(-1); } // Look for a nice visual #ifdef USE_HICOLOR if(XMatchVisualInfo(TheDisplay, TheScreen, 16, TrueColor, &xvi)) goto foundvisual; if(XMatchVisualInfo(TheDisplay, TheScreen, 15, TrueColor, &xvi)) goto foundvisual; fprintf(stderr,"Sorry, this version is for 15/16-bit displays only.\n"); #else if(XMatchVisualInfo(TheDisplay, TheScreen, 8, PseudoColor, &xvi)) goto foundvisual; fprintf(stderr,"Sorry, this version is for 8-bit displays only.\n"); #endif #if 0 if(XMatchVisualInfo(TheDisplay, TheScreen, 24, TrueColor, &xvi)) goto foundvisual; #endif exit(-1); foundvisual: xpfv=XListPixmapFormats(TheDisplay, &i); for(i--;i>=0;i--) if(xpfv[i].depth==xvi.depth) break; if(i<0) { fprintf(stderr,"No Pixmap format for visual depth?\n"); exit(-1); } VideoDepth=xvi.depth; VideoWidth = 640; VideoHeight = 480; MapWidth = 14; // FIXME: Not the correct way MapHeight = 14; shminfo.shmid=shmget(IPC_PRIVATE, (VideoWidth*xpfv[i].bits_per_pixel+xpfv[i].scanline_pad-1) / xpfv[i].scanline_pad * xpfv[i].scanline_pad * VideoHeight / 8, IPC_CREAT|0777); XFree(xpfv); if( !shminfo.shmid==-1 ) { fprintf(stderr,"shmget failed.\n"); exit(-1); } VideoMemory=(VMemType*)shminfo.shmaddr=shmat(shminfo.shmid,0,0); if( shminfo.shmaddr==(void*)-1 ) { shmctl(shminfo.shmid,IPC_RMID,0); fprintf(stderr,"shmat failed.\n"); exit(-1); } shminfo.readOnly=False; if( !XShmAttach(TheDisplay,&shminfo) ) { shmctl(shminfo.shmid,IPC_RMID,0); fprintf(stderr,"XShmAttach failed.\n"); exit(-1); } // Mark segment as deleted as soon as both clone and the X server have // attached to it. The POSIX spec says that a segment marked as deleted // can no longer have addition processes attach to it, but Linux will let // them anyway. shmctl(shminfo.shmid,IPC_RMID,0); TheMainDrawable=attributes.background_pixmap= XShmCreatePixmap(TheDisplay,DefaultRootWindow(TheDisplay) ,shminfo.shmaddr,&shminfo ,VideoWidth,VideoHeight ,xvi.depth); attributes.cursor = XCreateFontCursor(TheDisplay,XC_tcross-1); attributes.backing_store = NotUseful; attributes.save_under = False; attributes.event_mask = KeyPressMask|KeyReleaseMask|/*ExposureMask|*/ FocusChangeMask|ButtonPressMask|PointerMotionMask|ButtonReleaseMask; i = CWBackPixmap|CWBackingStore|CWSaveUnder|CWEventMask|CWCursor; if(xvi.class==PseudoColor) { i|=CWColormap; attributes.colormap = XCreateColormap( TheDisplay, xvi.screen, xvi.visual, AllocNone); // FIXME: Really should fill in the colormap right now } window=XCreateWindow(TheDisplay,DefaultRootWindow(TheDisplay) ,0,0,VideoWidth,VideoHeight,3 ,xvi.depth,InputOutput,xvi.visual ,i,&attributes); TheMainWindow=window; gcvalue.graphics_exposures=False; GcLine=XCreateGC(TheDisplay,window,GCGraphicsExposures,&gcvalue); // // Clear initial window. // XSetForeground(TheDisplay,GcLine,BlackPixel(TheDisplay,TheScreen)); XFillRectangle(TheDisplay,TheMainDrawable,GcLine,0,0 ,VideoWidth,VideoHeight); WmDeleteWindowAtom=XInternAtom(TheDisplay,"WM_DELETE_WINDOW",False); // // Set some usefull min/max sizes as well as a 1.3 aspect // #if 0 if( geometry ) { hints.flags=0; f=XParseGeometry(geometry ,&hints.x,&hints.y,&hints.width,&hints.height); if( f&XValue ) { if( f&XNegative ) { hints.x+=DisplayWidth-hints.width; } hints.flags|=USPosition; // FIXME: win gravity } if( f&YValue ) { if( f&YNegative ) { hints.y+=DisplayHeight-hints.height; } hints.flags|=USPosition; // FIXME: win gravity } if( f&WidthValue ) { hints.flags|=USSize; } if( f&HeightValue ) { hints.flags|=USSize; } } else { #endif hints.width=VideoWidth; hints.height=VideoHeight; hints.flags=PSize; #if 0 } #endif hints.min_width=VideoWidth; hints.min_height=VideoHeight; hints.max_width=VideoWidth; hints.max_height=VideoHeight; hints.min_aspect.x=4; hints.min_aspect.y=3; hints.max_aspect.x=4; hints.max_aspect.y=3; hints.width_inc=4; hints.height_inc=3; hints.flags|=PMinSize|PMaxSize|PAspect|PResizeInc; wmhints.input=True; wmhints.initial_state=NormalState; wmhints.window_group=window; wmhints.flags=InputHint|StateHint|WindowGroupHint; classhint.res_name="aleclone"; classhint.res_class="AleClone"; XSetStandardProperties(TheDisplay,window ,"ALE Clone","ALE Clone",None,(char**)0,0,&hints); XSetClassHint(TheDisplay,window,&classhint); XSetWMHints(TheDisplay,window,&wmhints); XSetWMProtocols(TheDisplay,window,&WmDeleteWindowAtom,1); XMapWindow(TheDisplay,window); // // Input handling. // XAddConnectionWatch(TheDisplay,MyConnectionWatch,NULL); }