/* Find a widget by name, or NULL if it doesn't exist. The widget chosen in the case of * duplicate names is undefined. */ struct widget *widget_find(const struct pgstring *name) { struct widget_find_data iterator_data; iterator_data.result = NULL; iterator_data.string = name; handle_iterate(PG_TYPE_WIDGET,&widget_find_iterator,&iterator_data); return iterator_data.result; }
/* Call the resize() function on all widgets with handles */ void resizeall(void) { struct divtree *tree; handle_iterate(PG_TYPE_WIDGET,&resizeall_iterate,NULL); for (tree=dts->top;tree;tree=tree->next) tree->flags |= DIVTREE_NEED_RESIZE; }
/* Set the video mode using the current driver. This is the implementation * of the setmode client request */ g_error video_setmode(u16 xres,u16 yres,u16 bpp,u16 flagmode,u32 flags) { g_error e; struct divtree *tree; struct sprite *spr; u8 converting_mode,oldbpp; /* Must be done first */ if (vidwrap->exitmode) { e = VID(exitmode)(); errorcheck; } /* Default values, combine flags */ if (!xres) xres = vid->xres; if (!yres) yres = vid->yres; if (!bpp) bpp = vid->bpp; switch (flagmode) { case PG_FM_ON: flags |= vid->flags; break; case PG_FM_OFF: flags = vid->flags & (~flags); break; case PG_FM_TOGGLE: flags ^= vid->flags; break; } vid->flags = flags; /* If the new bpp is different, use modeconvert/modeunconvert */ oldbpp = vid->bpp; converting_mode = (bpp != vid->bpp); if (converting_mode) { e = bitmap_iterate((handle_iterator)vid->bitmap_modeunconvert, NULL); errorcheck; e = handle_iterate(PG_TYPE_PALETTE,(handle_iterator)array_hwrtopg, NULL); errorcheck; } /* Might want to tell the driver! */ e = (*vid->setmode) (xres,yres,bpp,flags); errorcheck; /* By default logical coordinates are also physical */ vid->lxres = vid->xres; vid->lyres = vid->yres; /* Synchronize vid->display info automatically if we're using stdbitmap */ if (vid->display && vid->bitmap_getsize==def_bitmap_getsize) { if (((struct stdbitmap *)vid->display)->rend) g_free(((struct stdbitmap *)vid->display)->rend); ((struct stdbitmap *)vid->display)->freebits = 0; ((struct stdbitmap *)vid->display)->w = vid->xres; ((struct stdbitmap *)vid->display)->h = vid->yres; ((struct stdbitmap *)vid->display)->bpp = vid->bpp; } /* Reset wrapper library (before using VID macro) */ vidwrap_static = vidlib_static; vidwrap = &vidwrap_static; { /* Generate text colors table */ u32 *tc; int i; /* Default VGA 16-color palette, copied from the Linux console */ static const u32 default_palette[] = { 0x000000, 0xaa0000, 0x00aa00, 0xaaaa00, 0x0000aa, 0xaa00aa, 0x00aaaa, 0xaaaaaa, 0x555555, 0xff5555, 0x55ff55, 0xffff55, 0x5555ff, 0xff55ff, 0x55ffff, 0xffffff, }; /* Allocate space for textcolors if we haven't already */ if (!res[PGRES_DEFAULT_TEXTCOLORS]) { u32 *ptr; e = g_malloc((void**)&ptr,sizeof(u32)*17); errorcheck; ptr[0] = 16; e = mkhandle(&res[PGRES_DEFAULT_TEXTCOLORS],PG_TYPE_PALETTE,-1,(void*)ptr); errorcheck; } e = rdhandle((void **) &tc, PG_TYPE_PALETTE, -1, res[PGRES_DEFAULT_TEXTCOLORS]); errorcheck; /* Transcribe our static palette */ memcpy(tc+1, default_palette, sizeof(default_palette)); /* If we won't be doing it anyway later, go ahead and convert these to hwrcolors */ if (!converting_mode) { e = array_pgtohwr(&tc); errorcheck; } } /* Add wrapper libraries if necessary. At compile-time, support adding * 90, 180, or 270 degrees as a hardware rotation */ #ifdef CONFIG_ROTATIONBASE_90 /***** 90 degree default */ #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE90) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE180) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE if (!(vid->flags & PG_VID_ROTATEMASK)) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #else #ifdef CONFIG_ROTATIONBASE_180 /***** 180 degree default */ #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE270) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE90) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE180 if (!(vid->flags & PG_VID_ROTATEMASK)) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #else #ifdef CONFIG_ROTATIONBASE_270 /***** 270 degree default */ #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE180) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE270) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #ifdef CONFIG_ROTATE270 if (!(vid->flags & PG_VID_ROTATEMASK)) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #else /***** 0 degree default */ #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE90) { vidwrap_rotate90(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE180) { vidwrap_rotate180(vidwrap); vid->lxres = vid->xres; vid->lyres = vid->yres; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE270) { vidwrap_rotate270(vidwrap); vid->lxres = vid->yres; vid->lyres = vid->xres; } #endif #endif #endif #endif /* Should we ignore the base screen rotation for keyboard events? */ #ifdef CONFIG_ROTATIONBASE_NOKEYS vidwrap->coord_keyrotate = &def_coord_keyrotate; #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE90) vidwrap->coord_keyrotate = &rotate90_coord_keyrotate; #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE180) vidwrap->coord_keyrotate = &rotate180_coord_keyrotate; #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE270) vidwrap->coord_keyrotate = &rotate270_coord_keyrotate; #endif #endif /* CONFIG_ROTATIONBASE_NOKEYS */ /* Ignore the base screen rotation for pointing events? */ #ifdef CONFIG_ROTATIONBASE_NOPOINTING vidwrap->coord_physicalize = &def_coord_logicalize; vidwrap->coord_logicalize = &def_coord_logicalize; #ifdef CONFIG_ROTATE if (vid->flags & PG_VID_ROTATE90) { vidwrap->coord_physicalize = &rotate90_coord_physicalize; vidwrap->coord_logicalize = &rotate90_coord_logicalize; } #endif #ifdef CONFIG_ROTATE180 if (vid->flags & PG_VID_ROTATE180) { vidwrap->coord_physicalize = &rotate180_coord_logicalize; vidwrap->coord_logicalize = &rotate180_coord_logicalize; } #endif #ifdef CONFIG_ROTATE270 if (vid->flags & PG_VID_ROTATE270) { vidwrap->coord_physicalize = &rotate270_coord_physicalize; vidwrap->coord_logicalize = &rotate270_coord_logicalize; } #endif #endif /* CONFIG_ROTATIONBASE_NOPOINTING */ /* Since changing video modes pretty much obliterates all onscreen * sprites, and the previous location might be offscreen now, * reset the backbuffer on all sprites */ for (spr=spritelist;spr;spr=spr->next) spr->onscreen = 0; /* Resize the root divnodes of all divtrees in the dtstack */ if (dts) /* (if this is in early init, dtstack isn't here yet) */ for (tree=dts->top;tree;tree=tree->next) { tree->head->r.w = vid->lxres; tree->head->r.h = vid->lyres; tree->head->calc.w = vid->lxres; tree->head->calc.h = vid->lyres; tree->head->flags |= DIVNODE_NEED_RECALC | DIVNODE_FORCE_CHILD_RECALC | DIVNODE_NEED_REBUILD; tree->flags |= DIVTREE_NEED_RECALC | DIVTREE_ALL_REDRAW | DIVTREE_CLIP_POPUP; } /* Convert to the new color depth if necessary */ if (converting_mode) { e = bitmap_iterate((handle_iterator)vid->bitmap_modeconvert, NULL); errorcheck; e = handle_iterate(PG_TYPE_PALETTE,(handle_iterator)array_pgtohwr, NULL); errorcheck; } /* Done swtiching the mode, give the driver a shot at changing * things around */ e = VID(entermode)(); errorcheck; /* Reload things when increasing color depth */ if (oldbpp < bpp) { /* Reload any themes the server is responsible for */ e = reload_initial_themes(); errorcheck; /* FIXME: notify all clients that they can reload here */ } return success; }
void magic_button(s16 key) { switch (key) { case PGKEY_SLASH: /* CTRL-ALT-SLASH exits */ pgserver_mainloop_stop(); return; #ifdef DEBUG_KEYS /* The rest only work in debug mode */ case PGKEY_d: /* CTRL-ALT-d lists all debugging commands */ guru("Someone set up us the bomb!\n" "All your divnode are belong to us!\n" "\n" "Debugging keys:\n" " CTRL-ALT-H: [H]andle tree dump to stdout\n" " CTRL-ALT-S: [S]tring dump to stdout\n" " CTRL-ALT-T: Div[t]ree dump to stdout\n" " CTRL-ALT-M: [M]emory use profile\n" " CTRL-ALT-B: [B]lack screen\n" " CTRL-ALT-Y: Uns[y]nchronize screen buffers\n" " CTRL-ALT-U: Bl[u]e screen\n" " CTRL-ALT-P: Bitma[p] dump to video display\n" " CTRL-ALT-O: Divn[o]de outline\n" " CTRL-ALT-A: [A]pplication dump to stdout\n" " CTRL-ALT-R: Hotspot g[r]aph\n" " CTRL-ALT-I: Mode [I]nfo\n" ); return; case PGKEY_h: /* CTRL-ALT-h dumps the handle tree */ handle_dump(); return; case PGKEY_s: /* CTRL-ALT-s dumps all strings */ string_dump(); return; case PGKEY_n: /* CTRL-ALT-n dumps all gropnodes */ grop_dump(); return; case PGKEY_t: /* CTRL-ALT-t dumps all divnodes */ div_dump(); return; case PGKEY_g: /* Just for fun :) */ guru("GURU MEDITATION #3263827\n\nCongratulations!\n" " Either you have read the source code or\n" " you have very persistently banged your\n" " head on the keyboard ;-)"); return; case PGKEY_m: /* CTRL-ALT-m displays a memory profile */ guru("Memory Profile\n\n" "Total memory use: %d bytes in %d allocations\n\n" "%d bytes in %d gropnodes\n" "%d bytes in %d zombie gropnodes\n" "%d bytes in %d divnodes\n" "%d bytes in %d widgets\n" "%d bytes in %d handle nodes", memamt,memref, num_grops*sizeof(struct gropnode),num_grops, grop_zombie_count*sizeof(struct gropnode),grop_zombie_count, num_divs*sizeof(struct divnode),num_divs, num_widgets*sizeof(struct widget),num_widgets, num_handles*sizeof(struct handlenode),num_handles); return; case PGKEY_b: /* CTRL-ALT-b blanks the screen */ { s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); VID(rect) (magic_cursor_display(), 0,0,lxres,lyres, VID(color_pgtohwr) (0),PG_LGOP_NONE); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_y: /* CTRL-ALT-y unsynchronizes the screen buffers */ { /* The buffers in PicoGUI normally like to be synchronized. * Data flows from the divtree to the backbuffer to the screen. * The purpose of this debugging key is to put a different * image on the screen (a black rectangle) than is in the rest * of the pipeline, so that by watching the data ooze out one * can tell if the correct update regions are being used and * in general prod at the video driver. * This would be very simple if not for the fact that only the video * driver has access to the screen's buffer. The procedure here is * to pump the black screen all the way through, then reinitializing * the backbuffer while being very carefull not to update right away * or mess up the sprites. */ struct divtree *p; s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); /* Push through the black screen */ VID(rect) (magic_cursor_display(), 0,0,lxres,lyres, VID(color_pgtohwr) (0),PG_LGOP_NONE); VID(update) (magic_cursor_display(),0,0,lxres,lyres); /* Force redrawing everything to the backbuffer */ for (p=dts->top;p;p=p->next) p->flags |= DIVTREE_ALL_REDRAW; update(NULL,0); /* Note the zero flag! */ /* Clear the update rectangle, breaking the pipeline that usually works so well :) */ for (p=dts->top;p;p=p->next) p->update_rect.w = 0; /* The above zero flag left sprites off. With sprites off it's tough to use the mouse! */ VID(sprite_showall) (); } return; case PGKEY_u: /* CTRL-ALT-u makes a blue screen */ { s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); VID(rect) (magic_cursor_display(),0,0,lxres,lyres, VID(color_pgtohwr) (0x0000FF), PG_LGOP_NONE); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_p: /* CTRL-ALT-p shows all loaded bitmaps */ { struct debug_bitmaps_data data; s16 lxres,lyres; VID(bitmap_getsize)(VID(window_debug)(), &lxres, &lyres); memset(&data,0,sizeof(data)); guru("Table of loaded bitmaps:"); handle_iterate(PG_TYPE_BITMAP,&debug_bitmaps,&data); VID(update) (VID(window_debug)(),0,0,lxres,lyres); } return; case PGKEY_o: /* CTRL-ALT-o traces all divnodes */ { s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); r_divnode_trace(dts->top->head); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_a: /* CTRL-ALT-a shows application info */ { struct app_info *a; const struct pgstring *name; for (a=applist;a;a=a->next) { if (iserror(rdhandle((void**)&name,PG_TYPE_PGSTRING,-1,a->name))) name = pgstring_tmpwrap("(error reading handle)"); printf("app: '"); pgstring_print(name); printf("' type=%d owner=%d\n",a->type,a->owner); } } return; case PGKEY_r: /* CTRL-ALT-r draws the hotspot graph */ { struct hotspot *p; s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); for (p=hotspotlist;p;p=p->next) hotspot_draw(p); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_i: /* CTRL-ALT-i gets video mode info */ { int x,y,celw,celh, pixelx,pixely; hwrcolor i, white, black, numcolors; s16 lxres,lyres; VID(bitmap_getsize)(VID(window_debug)(), &lxres, &lyres); guru("Video mode:\n" "Logical %dx%d, physical %dx%d, %d-bit color\n" "\n" "Color palette:\n", vid->lxres, vid->lyres, vid->xres, vid->yres, vid->bpp); if (vid->bpp <= 8) { /* Actual palette display */ i = 0; celw = (lxres-20) >> 4; celh = (lyres-70) >> 4; if (celw < celh) celh = celw; else celw = celh; white = VID(color_pgtohwr)(PGC_WHITE); black = VID(color_pgtohwr)(PGC_BLACK); numcolors = 1 << vid->bpp; for (y=0;y<16;y++) for (x=0;x<16 && i<numcolors;x++,i++) { pixelx = x*celw+10; pixely = y*celh+60; /* Display a rectangle of the color with black and white borders. * This is a lot like what the scribble app does, but we don't have * the convenience of a "frame" gropnode at this low level. */ VID(slab)(VID(window_debug)(),pixelx,pixely,celw,white,PG_LGOP_NONE); VID(slab)(VID(window_debug)(),pixelx,pixely+celh,celw,white,PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx,pixely,celh,white,PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx+celw,pixely,celh,white,PG_LGOP_NONE); VID(slab)(VID(window_debug)(),pixelx+1,pixely+1,celw-2, black, PG_LGOP_NONE); VID(slab)(VID(window_debug)(),pixelx+1,pixely-1+celh,celw-2, black, PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx+1,pixely+1,celh-2, black, PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx-1+celh,pixely+1,celh-2, black, PG_LGOP_NONE); VID(rect)(VID(window_debug)(),pixelx+2,pixely+2,celw-3,celh-3, i , PG_LGOP_NONE); } } else { /* Just some RGB gradients */ y = 60; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0xFFFFFF, PG_LGOP_NONE); y += 30; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0xFF0000, PG_LGOP_NONE); y += 30; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0x00FF00, PG_LGOP_NONE); y += 30; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0x0000FF, PG_LGOP_NONE); y += 30; } VID(update) (VID(window_debug)(),0,0,lxres,lyres); }