int visual_depth (Screen *screen, Visual *visual) { Display *dpy = DisplayOfScreen (screen); XVisualInfo vi_in, *vi_out; int out_count, depth; vi_in.screen = screen_number (screen); vi_in.visualid = XVisualIDFromVisual (visual); vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, &vi_in, &out_count); if (! vi_out) abort (); depth = vi_out[0].depth; XFree ((char *) vi_out); return depth; }
GLXContext * init_GL(ModeInfo * mi) { Display *dpy = mi->dpy; Window window = mi->window; Screen *screen = mi->xgwa.screen; Visual *visual = mi->xgwa.visual; GLXContext glx_context = 0; XVisualInfo vi_in, *vi_out; int out_count; vi_in.screen = screen_number (screen); vi_in.visualid = XVisualIDFromVisual (visual); vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, &vi_in, &out_count); if (! vi_out) abort (); { XSync (dpy, False); orig_ehandler = XSetErrorHandler (BadValue_ehandler); glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE); XSync (dpy, False); XSetErrorHandler (orig_ehandler); if (got_error) glx_context = 0; } XFree((char *) vi_out); if (!glx_context) { fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n", progname, (unsigned int) XVisualIDFromVisual (visual)); exit(1); } glXMakeCurrent (dpy, window, glx_context); { GLboolean rgba_mode = 0; glGetBooleanv(GL_RGBA_MODE, &rgba_mode); if (!rgba_mode) { glIndexi (WhitePixelOfScreen (screen)); glClearIndex (BlackPixelOfScreen (screen)); } } /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT for single-buffered contexts, and GL_BACK for double-buffered contexts." However, I find that this is not always the case, at least with Mesa 3.4.2 -- sometimes the default seems to be GL_FRONT even when glGet(GL_DOUBLEBUFFER) is true. So, let's make sure. Oh, hmm -- maybe this only happens when we are re-using the xscreensaver window, and the previous GL hack happened to die with the other buffer selected? I'm not sure. Anyway, this fixes it. */ { GLboolean d = False; glGetBooleanv (GL_DOUBLEBUFFER, &d); if (d) glDrawBuffer (GL_BACK); else glDrawBuffer (GL_FRONT); } /* GLXContext is already a pointer type. Why this function returns a pointer to a pointer, I have no idea... */ { GLXContext *ptr = (GLXContext *) malloc(sizeof(GLXContext)); *ptr = glx_context; return ptr; } }
GLXContext * init_GL(ModeInfo * mi) { Display *dpy = mi->dpy; Window window = mi->window; Screen *screen = mi->xgwa.screen; Visual *visual = mi->xgwa.visual; XVisualInfo vi_in, *vi_out; int out_count; if (mi->glx_context) { glXMakeCurrent (dpy, window, mi->glx_context); return &mi->glx_context; } # ifdef HAVE_JWZGLES jwzgles_make_current(jwzgles_make_state(state)); # endif vi_in.screen = screen_number (screen); vi_in.visualid = XVisualIDFromVisual (visual); vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, &vi_in, &out_count); if (! vi_out) abort (); { XSync (dpy, False); orig_ehandler = XSetErrorHandler (BadValue_ehandler); mi->glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE); XSync (dpy, False); XSetErrorHandler (orig_ehandler); if (got_error) mi->glx_context = 0; } XFree((char *) vi_out); if (!mi->glx_context) { fprintf(stderr, "%s: couldn't create GL context for visual 0x%x.\n", progname, (unsigned int) XVisualIDFromVisual (visual)); exit(1); } glXMakeCurrent (dpy, window, mi->glx_context); { GLboolean rgba_mode = 0; glGetBooleanv(GL_RGBA_MODE, &rgba_mode); if (!rgba_mode) { glIndexi (WhitePixelOfScreen (screen)); glClearIndex (BlackPixelOfScreen (screen)); } } /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT for single-buffered contexts, and GL_BACK for double-buffered contexts." However, I find that this is not always the case, at least with Mesa 3.4.2 -- sometimes the default seems to be GL_FRONT even when glGet(GL_DOUBLEBUFFER) is true. So, let's make sure. Oh, hmm -- maybe this only happens when we are re-using the xscreensaver window, and the previous GL hack happened to die with the other buffer selected? I'm not sure. Anyway, this fixes it. */ { GLboolean d = False; glGetBooleanv (GL_DOUBLEBUFFER, &d); if (d) glDrawBuffer (GL_BACK); else glDrawBuffer (GL_FRONT); } /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */ clear_gl_error (); /* Process the -background argument. */ { char *s = get_string_resource(mi->dpy, "background", "Background"); XColor c = { 0, }; if (! XParseColor (dpy, mi->xgwa.colormap, s, &c)) fprintf (stderr, "%s: can't parse color %s; using black.\n", progname, s); glClearColor (c.red / 65535.0, c.green / 65535.0, c.blue / 65535.0, 1.0); } glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* GLXContext is already a pointer type. Why this function returns a pointer to a pointer, I have no idea... */ return &mi->glx_context; }
/* Synchronize the contents of si->ssi to the current state of the monitors. Doesn't change anything if nothing has changed; otherwise, alters and reuses existing saver_screen_info structs as much as possible. Returns True if anything changed. */ Bool update_screen_layout (saver_info *si) { monitor **monitors = scan_monitors (si); int count = 0; int good_count = 0; int i, j; int seen_screens[100] = { 0, }; if (! layouts_differ_p (monitors, si->monitor_layout)) { free_monitors (monitors); return False; } free_monitors (si->monitor_layout); si->monitor_layout = monitors; check_monitor_sanity (si->monitor_layout); while (monitors[count]) { if (monitors[count]->sanity == S_SANE) good_count++; count++; } if (si->ssi_count == 0) { si->ssi_count = 10; si->screens = (saver_screen_info *) calloc (sizeof(*si->screens), si->ssi_count); } if (si->ssi_count <= good_count) { si->ssi_count = good_count + 10; si->screens = (saver_screen_info *) realloc (si->screens, sizeof(*si->screens) * si->ssi_count); memset (si->screens + si->nscreens, 0, sizeof(*si->screens) * (si->ssi_count - si->nscreens)); } if (! si->screens) abort(); si->nscreens = good_count; /* Regenerate the list of GL visuals as needed. */ if (si->best_gl_visuals) free (si->best_gl_visuals); si->best_gl_visuals = 0; for (i = 0, j = 0; i < count; i++) { monitor *m = monitors[i]; saver_screen_info *ssi = &si->screens[j]; Screen *old_screen = ssi->screen; int sn; if (monitors[i]->sanity != S_SANE) continue; ssi->global = si; ssi->number = j; sn = screen_number (m->screen); ssi->screen = m->screen; ssi->real_screen_number = sn; ssi->real_screen_p = (seen_screens[sn] == 0); seen_screens[sn]++; ssi->default_visual = get_visual_resource (ssi->screen, "visualID", "VisualID", False); ssi->current_visual = ssi->default_visual; ssi->current_depth = visual_depth (ssi->screen, ssi->current_visual); /* If the screen changed (or if this is the first time) we need a new toplevel shell for this screen's depth. */ if (ssi->screen != old_screen) initialize_screen_root_widget (ssi); ssi->poll_mouse_last_root_x = -1; ssi->poll_mouse_last_root_y = -1; ssi->x = m->x; ssi->y = m->y; ssi->width = m->width; ssi->height = m->height; # ifndef DEBUG_MULTISCREEN { saver_preferences *p = &si->prefs; if (p->debug_p # ifdef QUAD_MODE && !p->quad_p # endif ) ssi->width /= 2; } # endif j++; } si->default_screen = &si->screens[0]; return True; }
void describe_monitor_layout (saver_info *si) { monitor **monitors = si->monitor_layout; int count = 0; int good_count = 0; int bad_count = 0; int implausible_p = !plausible_aspect_ratio_p (monitors); while (monitors[count]) { if (monitors[count]->sanity == S_SANE) good_count++; else bad_count++; count++; } if (monitors[0]->err) /* deferred error msg */ { char *token = strtok (monitors[0]->err, "\n"); while (token) { fprintf (stderr, "%s: %s\n", blurb(), token); token = strtok (0, "\n"); } free (monitors[0]->err); monitors[0]->err = 0; } if (count == 0) fprintf (stderr, "%s: no screens!\n", blurb()); else { int i; fprintf (stderr, "%s: screens in use: %d\n", blurb(), good_count); for (i = 0; i < count; i++) { monitor *m = monitors[i]; if (m->sanity != S_SANE) continue; fprintf (stderr, "%s: %3d/%d: %dx%d+%d+%d", blurb(), m->id, screen_number (m->screen), m->width, m->height, m->x, m->y); if (m->desc && *m->desc) fprintf (stderr, " (%s)", m->desc); fprintf (stderr, "\n"); } if (bad_count > 0) { fprintf (stderr, "%s: rejected screens: %d\n", blurb(), bad_count); for (i = 0; i < count; i++) { monitor *m = monitors[i]; monitor *e = monitors[m->enemy]; if (m->sanity == S_SANE) continue; fprintf (stderr, "%s: %3d/%d: %dx%d+%d+%d", blurb(), m->id, screen_number (m->screen), m->width, m->height, m->x, m->y); if (m->desc && *m->desc) fprintf (stderr, " (%s)", m->desc); fprintf (stderr, " -- "); switch (m->sanity) { case S_SANE: abort(); break; case S_ENCLOSED: fprintf (stderr, "enclosed by %d (%dx%d+%d+%d)\n", e->id, e->width, e->height, e->x, e->y); break; case S_DUPLICATE: fprintf (stderr, "duplicate of %d\n", e->id); break; case S_OVERLAP: fprintf (stderr, "overlaps %d (%dx%d+%d+%d)\n", e->id, e->width, e->height, e->x, e->y); break; case S_OFFSCREEN: fprintf (stderr, "off screen (%dx%d)\n", WidthOfScreen (e->screen), HeightOfScreen (e->screen)); break; case S_DISABLED: fprintf (stderr, "output disabled\n"); break; } } } if (implausible_p) fprintf (stderr, "%s: WARNING: single screen aspect ratio is %dx%d = %.2f\n" "%s: probable X server bug in Xinerama/RANDR!\n", blurb(), monitors[0]->width, monitors[0]->height, monitors[0]->width / (double) monitors[0]->height, blurb()); } }
static void * noseguy_init (Display *d, Window w) { struct state *st = (struct state *) calloc (1, sizeof(*st)); unsigned long fg, bg, text_fg, text_bg; XWindowAttributes xgwa; Colormap cmap; char *fontname; XGCValues gcvalues; st->dpy = d; st->window = w; st->first_time = 1; fontname = get_string_resource (st->dpy, "font", "Font"); XGetWindowAttributes (st->dpy, st->window, &xgwa); st->Width = xgwa.width + 2; st->Height = xgwa.height + 2; cmap = xgwa.colormap; st->tc = textclient_open (st->dpy); { int w = 40; int h = 15; textclient_reshape (st->tc, w, h, w, h, /* Passing MAXLINES isn't actually necessary */ 0); } init_images(st); st->xftfont = XftFontOpenXlfd (st->dpy, screen_number (xgwa.screen), fontname); XftColorAllocName (st->dpy, xgwa.visual, xgwa.colormap, get_string_resource (st->dpy, "textForeground", "Foreground"), &st->xftcolor); st->xftdraw = XftDrawCreate (st->dpy, st->window, xgwa.visual, xgwa.colormap); fg = get_pixel_resource (st->dpy, cmap, "foreground", "Foreground"); bg = get_pixel_resource (st->dpy, cmap, "background", "Background"); text_fg = get_pixel_resource (st->dpy, cmap, "textForeground", "Foreground"); text_bg = get_pixel_resource (st->dpy, cmap, "textBackground", "Background"); /* notice when unspecified */ if (! get_string_resource (st->dpy, "textForeground", "Foreground")) text_fg = bg; if (! get_string_resource (st->dpy, "textBackground", "Background")) text_bg = fg; gcvalues.foreground = fg; gcvalues.background = bg; st->fg_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcvalues); gcvalues.foreground = bg; gcvalues.background = fg; st->bg_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcvalues); gcvalues.foreground = text_fg; gcvalues.background = text_bg; st->text_fg_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcvalues); gcvalues.foreground = text_bg; gcvalues.background = text_fg; st->text_bg_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcvalues); st->x = st->Width / 2; st->y = st->Height / 2; st->state = IS_MOVING; st->next_fn = move; st->walk_up = 1; return st; }
record_anim_state * screenhack_record_anim_init (Screen *screen, Window window, int target_frames) { Display *dpy = DisplayOfScreen (screen); record_anim_state *st; # ifndef USE_GL XGCValues gcv; # endif /* !USE_GL */ if (target_frames <= 0) return 0; st = (record_anim_state *) calloc (1, sizeof(*st)); st->fps = 30; st->screen = screen; st->window = window; st->target_frames = target_frames; st->start_time = double_time(); st->frame_count = 0; st->fade_frames = st->fps * 1.5; if (st->fade_frames >= (st->target_frames / 2) - st->fps) st->fade_frames = 0; # ifdef HAVE_GDK_PIXBUF { Window root; int x, y; unsigned int w, h, d, bw; XGetGeometry (dpy, window, &root, &x, &y, &w, &h, &bw, &d); gdk_pixbuf_xlib_init_with_depth (dpy, screen_number (screen), d); # ifdef HAVE_GTK2 # if !GLIB_CHECK_VERSION(2, 36 ,0) g_type_init(); # endif # else /* !HAVE_GTK2 */ xlib_rgb_init (dpy, screen); # endif /* !HAVE_GTK2 */ } # else /* !HAVE_GDK_PIXBUF */ # error GDK_PIXBUF is required # endif /* !HAVE_GDK_PIXBUF */ XGetWindowAttributes (dpy, st->window, &st->xgwa); # ifdef USE_GL st->data = (char *) calloc (st->xgwa.width, st->xgwa.height * 3); st->data2 = (char *) calloc (st->xgwa.width, st->xgwa.height * 3); # else /* !USE_GL */ st->gc = XCreateGC (dpy, st->window, 0, &gcv); st->p = XCreatePixmap (dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth); st->img = XCreateImage (dpy, st->xgwa.visual, st->xgwa.depth, ZPixmap, 0, 0, st->xgwa.width, st->xgwa.height, 8, 0); st->img->data = (char *) calloc (st->img->height, st->img->bytes_per_line); # endif /* !USE_GL */ # ifndef HAVE_JWXYZ XFetchName (dpy, st->window, &st->title); { char *s = strchr(st->title, ':'); if (s) *s = 0; } # endif /* !HAVE_JWXYZ */ return st; }
Bool allocate_alpha_colors (Screen *screen, Visual *visual, Colormap cmap, int *nplanesP, Bool additive_p, unsigned long **plane_masks, unsigned long *base_pixelP , ModeInfo* mi) { #ifdef WIN32 return False; #else Display *dpy = DisplayOfScreen (screen); XColor *colors; int nplanes = *nplanesP; int i; if (!has_writable_cells (mi)) cmap = 0; if (!cmap) /* A TrueColor visual, or similar. */ { int depth = visual_depth (screen, visual); unsigned long masks; XVisualInfo vi_in, *vi_out; /* Find out which bits the R, G, and B components actually occupy on this visual. */ vi_in.screen = screen_number (screen); vi_in.visualid = XVisualIDFromVisual (visual); vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, &vi_in, &i); if (! vi_out) return False; masks = vi_out[0].red_mask | vi_out[0].green_mask | vi_out[0].blue_mask; XFree ((char *) vi_out); if (nplanes > depth) nplanes = depth; *nplanesP = nplanes; *base_pixelP = 0; *plane_masks = (unsigned long *) calloc(sizeof(unsigned long), nplanes); /* Pick the planar values randomly, but constrain them to fall within the bit positions of the R, G, and B fields. */ for (i = 0; i < nplanes; i++) (*plane_masks)[i] = LRAND() & masks; } else /* A PseudoColor visual, or similar. */ { if (nplanes > 31) nplanes = 31; *plane_masks = (unsigned long *) malloc(sizeof(unsigned long) * nplanes); nplanes = allocate_color_planes (dpy, cmap, nplanes, *plane_masks, base_pixelP); *nplanesP = nplanes; if (nplanes <= 1) { free(*plane_masks); *plane_masks = 0; return False; } colors = (XColor *) calloc (nplanes, sizeof (XColor)); for (i = 0; i < nplanes; i++) { /* pick the base colors. If we are in subtractive mode, pick higher intensities. */ hsv_to_rgb (NRAND( 360 ), NRAND( 100000 ) / 100000.0 , NRAND( 100000 ) / 200000.0 + (additive_p ? 0.2 : 0.5), &colors[i].red, &colors[i].green, &colors[i].blue); } initialize_transparency_colormap (dpy, cmap, nplanes, *base_pixelP, *plane_masks, colors, additive_p , mi ); XFree ((XPointer) colors); } return True; #endif }