diff --git a/lib/modules/Protocols.pmod/X.pmod/Extensions.pmod b/lib/modules/Protocols.pmod/X.pmod/Extensions.pmod index 1ab7c0c32d9910e54944673745192d1930e35564..274759bec62defbbbd6a50357d25a18a739b72f5 100644 --- a/lib/modules/Protocols.pmod/X.pmod/Extensions.pmod +++ b/lib/modules/Protocols.pmod/X.pmod/Extensions.pmod @@ -51,11 +51,13 @@ class Shape void ShapeRectangles( object window, int xo, int yo, string kind, string operation, - array (object) rectangles ) + object(Types.Rectangle)| + array(object(Types.Rectangle)) rectangles ) { int k = shape_kind[kind]; int o = shape_op[operation]; - string rects = (rectangles->to_string())*""; + string rects = (objectp(rectangles)?rectangles->to_string(): + (rectangles->to_string())*""); object req = Requests.ExtensionRequest( major, 0, 0 ); req->code = 1; diff --git a/lib/modules/Protocols.pmod/X.pmod/Requests.pmod b/lib/modules/Protocols.pmod/X.pmod/Requests.pmod index 24f80a3649ec780ee70f5225f38f8b8018ce6808..74051dac804e00791ac56df6d9aa307a1897f7ce 100644 --- a/lib/modules/Protocols.pmod/X.pmod/Requests.pmod +++ b/lib/modules/Protocols.pmod/X.pmod/Requests.pmod @@ -501,8 +501,8 @@ class PolyFillRectangle string to_string() { - return build_request(sprintf("%4c%4c%@s", drawable, gc, - rectangles->to_string())); + return build_request(sprintf("%4c%4c%s", drawable, gc, + rectangles->to_string()*"")); } } @@ -525,13 +525,13 @@ class PutImage string to_string() { - string pad=""; + string pad=""; while(((strlen(data)+strlen(pad))%4)) pad += "\0"; pad = build_request(sprintf("%4c" "%4c" - "%2c" "%2c" - "%2c" "%2c" - "%c" "%c" "\0\0" - "%s%s", + "%2c" "%2c" + "%2c" "%2c" + "%c" "%c" "\0\0" + "%s%s", drawable, gc, width, height, dst_x, dst_y, left_pad, depth, diff --git a/lib/modules/Protocols.pmod/X.pmod/Types.pmod b/lib/modules/Protocols.pmod/X.pmod/Types.pmod index 3d1a68f66ed6e26cfe60360313155965f8ac9f9b..c9cd2f33cd4a84ab3e71a023f98802c601915f7a 100644 --- a/lib/modules/Protocols.pmod/X.pmod/Types.pmod +++ b/lib/modules/Protocols.pmod/X.pmod/Types.pmod @@ -22,6 +22,8 @@ class Visual { inherit XResource; + int depth; + int c_class; int bitsPerRGB; int colorMapEntries; @@ -121,10 +123,10 @@ class Colormap req->blue = b; array a = display->blocking_request( req ); - return a[0] && (alloced[sprintf("%2c%2c%2c", r, g, b)]= - a[1]); + return a[0] && (alloced[sprintf("%2c%2c%2c", r, g, b)]=a[1]); } + void create(object disp, int i, object vis) { display = disp; @@ -583,6 +585,12 @@ class Window void ShapeMask( string kind, int xo, int yo, string operation, object (Pixmap) mask ) { + if(kind == "both") + { + ShapeMask( "clip", xo, yo, operation, mask); + ShapeMask( "bounding", xo, yo, operation, mask); + return; + } if(!display->extensions["SHAPE"]) error("No shape extension available.\n"); display->extensions["SHAPE"]-> @@ -591,6 +599,12 @@ class Window void ShapeOffset( string kind, int xo, int yo ) { + if(kind == "both") + { + ShapeOffset( "clip", xo, yo ); + ShapeOffset( "bounding", xo, yo ); + return; + } if(!display->extensions["SHAPE"]) error("No shape extension available.\n"); display->extensions["SHAPE"]->ShapeOffset( this_object(), kind, xo, yo ); diff --git a/lib/modules/Protocols.pmod/X.pmod/XImage.pmod b/lib/modules/Protocols.pmod/X.pmod/XImage.pmod new file mode 100644 index 0000000000000000000000000000000000000000..00bccca4ac49c26b475bbf87588759053846a6fe --- /dev/null +++ b/lib/modules/Protocols.pmod/X.pmod/XImage.pmod @@ -0,0 +1,289 @@ +#include "error.h" + +// Image --> X module. +// Needs: Pike 0.6 + + +// Base class. +class XImage +{ + class funcall + { + function f; + object parent; + + void `()( mixed ... args ) + { + mixed q = f( @args ); + if(objectp(q)) parent->set_image( q ); + return q; + } + + void create(function q, object p) { f = q;parent=p; } + } + + object image; // The real image. + + + + void clear_caches(int x, int y, int width, int height) + { + // Changed by the inheriting class. + } + + void redraw(int x, int y, int width, int height) + { + // Changed by the inheriting class. + } + + void copy(mixed ... args) + { + return image->copy( @args ); + } + + varargs object paste(object what, int x, int y) + { + image->paste(what, x, y); + clear_caches(x,y,what->xsize(),what->ysize()); + redraw(x,y,what->xsize(),what->ysize()); + } + + varargs object paste_mask(object what, object mask, int x, int y) + { + image->paste_mask(what, mask, x, y); + clear_caches(x,y,what->xsize(),what->ysize()); + redraw(x,y,what->xsize(),what->ysize()); + } + + void set_image(object to) + { + image = to; + clear_caches(0,0,image->xsize(),image->ysize()); + redraw(0,0,image->xsize(),image->ysize()); + } + + mixed `->( string ind ) + { + mixed x; + if((x = `[](this_object(),ind))) + return x; + x = funcall(image[ind], this_object() ); + } + +} + + +// Steels a few callbacks from the window. + +class WindowImage +{ + inherit XImage; + object (Types.Window) window; + object (Types.RootWindow) root; // extends window + object (Types.Visual) visual; + object (Types.Colormap) colormap; + object (Image.colortable) ccol; + object (Types.GC) dgc; + + int best; + + int depth, bpp; + function converter; + int linepad; + int rmask, gmask, bmask; + + void set_render(string type) + { + if(type == "best") best=1; + } + + + object allocate_colortable() + { + array wanted; + if(best) + wanted = image->select_colors( 100 ); + else + wanted = image->select_colors( 32 ); + + if(sizeof(wanted) < 10) + { + object i = Image.image(100,100); + i->tuned_box(0,0, 100, 50, + ({ ({0,255,255 }),({255,255,255 }), + ({0,0,255 }),({255,0,255 }) })); + i->tuned_box(0,0, 100, 50, + ({ ({0,0,255 }),({255,0,255 }), + ({0,255,255 }),({255,255,0 }) })); + i = i->hsv_to_rgb(); + wanted += i->select_colors(100); + } + + int max_pixel; + + Array.map((array)wanted, + lambda(array o){ + return colormap->AllocColor(o[0]*257,o[1]*257,o[2]*257); + }); + + foreach(values(colormap->alloced), mapping m) + if(m && m->pixel > max_pixel) + max_pixel = m->pixel; + + array res = allocate( max_pixel+1 ); + + foreach(values(colormap->alloced), mapping m) + if(m) res[ m->pixel ] = ({ m->red/257, m->green/257, m->blue/257 }); +// What to do with unallocated colors? + res = replace( res, 0, ({ 255,0,255 }) ); + + object ct = Image.colortable( res ); + ct->cubicles(12, 12, 12); + if(best) + ct->floyd_steinberg(); + else + ct->ordered(); +// werror(sprintf("colortable: %O\n", res)); + return ct; + } + + void clear_caches(int x, int y, int width, int height) + { + // no inteligence yet... + } + + void redraw(int x, int y, int width, int height) + { + int lheight = height; + int slice = (window->display->maxRequestSize/depth)*32 / width; + if(x+width > image->xsize()) + width = image->xsize()-x; + if(width<=0) return; + + if(y+lheight > image->ysize()) + { + height = image->ysize()-y; + lheight = image->ysize()-y; + } + if(lheight<=0) return; + + while(lheight>0) + { + lheight -= slice; + if(lheight < 0) slice += lheight; + object mimg = image->copy(x,y,x+width-1,y+slice-1); + + if(rmask) + window->PutImage( dgc, depth, x, y, width, slice, + converter( mimg, bpp, linepad, rmask, gmask, bmask, + @(ccol?({ccol}):({})))); + else + { + if(!ccol) ccol = allocate_colortable(); + string data = converter( mimg, bpp, linepad, depth, ccol ); + window->PutImage( dgc, bpp, x, y, width, slice, data ); + } + y += slice; + } + } + + void exposed(mixed event) + { + redraw(event->x, event->y, event->width, event->height); + } + + + void create(object (Types.Window) w) + { + window = w; + if(!w->visual) + { + object q = w->parent; + if(q) + do { + if(q->visual) + { + visual = q->visual; + break; + } else { + q = q->parent; + } + } while(q); + q = w; + while(q) { root = q; q = q->parent; } + + if(!visual) + visual = root->visual; + } else + visual = w->visual; + + + + if(root->visual == visual) + { + werror("using default visual\n"); + colormap = root->defaultColorMap; + } + else + colormap = w->CreateColormap( visual, 0 ); + rmask = visual->redMask; + gmask = visual->greenMask; + bmask = visual->blueMask; + depth = visual->depth; + bpp = visual->bitsPerRGB; + linepad = 32; // FIXME! + + switch(_Xlib.visual_classes[visual->c_class]) + { + case "StaticGray": + ccol = Image.colortable(0,0,0, ({0,0,0}), ({255,255,255}), 1<<depth); + converter = Image.X.encode_pseudocolor; + break; + case "GrayScale": + ccol = Image.colortable(0,0,0, ({0,0,0}), ({255,255,255}), 1<<depth); + converter = Image.X.encode_pseudocolor; + break; + case "PseudoColor": + ccol = 0; + converter = Image.X.encode_pseudocolor; + break; + case "StaticColor": + case "TrueColor": + if(depth < 16) + { + ccol = Image.colortable(1<<depth, 1<<rmask, 1<<gmask, 1<<bmask); + ccol->ordered(); + } + converter = Image.X.encode_truecolor_masks; + break; + case "DirectColor": + error("Cannot handle Direct Color visual yet."); + break; + } + dgc = window->CreateGC(); + + w->set_event_callback("_Expose", exposed); // internal callback... + w->SelectInput("Exposure"); + } +} + +class PixmapImage +{ + inherit XImage; + object pixmap; + object (Types.Window) window, root; + object (Types.Visual) visual; + object (Types.Colormap) colormap; + + int depth; + function converter; + int linepad; + int rmask, gmask, bmask; + + + void create(object (Types.Pixmap) p, object (Types.Window) w) + { + pixmap = p; + window = w; + } +} diff --git a/lib/modules/Protocols.pmod/X.pmod/Xlib.pmod b/lib/modules/Protocols.pmod/X.pmod/Xlib.pmod index 9641739b5da0bfb016e5f9a9ec8a0b94c0746817..5c7d567b8a37096125b7e55e719391e9b453813f 100644 --- a/lib/modules/Protocols.pmod/X.pmod/Xlib.pmod +++ b/lib/modules/Protocols.pmod/X.pmod/Xlib.pmod @@ -113,6 +113,11 @@ class Display inherit id_manager; inherit Atom.atom_manager; + + + void close_callback(mixed id); + void read_callback(mixed id, string data); + // FIXME! Should use some sort of (global) db. mapping compose_patterns = decode_value(Stdio.read_bytes("db/compose.db")); @@ -211,9 +216,7 @@ class Display /* This function leaves the socket in blocking mode */ int flush() { /* FIXME: Not thread-safe */ - // trace(5); set_blocking(); - int written = write(buffer); if (written < strlen(buffer)) return 0; @@ -234,7 +237,7 @@ class Display int wid; object w; - werror(sprintf("Event: %s\n", event->type)); +// werror(sprintf("Event: %s\n", event->type)); if (event->wid && (w = lookup_id(event->wid)) && ((w->event_callbacks["_"+event->type]) ||(w->event_callbacks[event->type]))) @@ -359,6 +362,7 @@ class Display { int visualID = struct->get_uint(4); object v = Types.Visual(this_object(), visualID); + v->depth = depth; v->c_class = struct->get_uint(1); v->bitsPerRGB = struct->get_uint(1); v->colorMapEntries = struct->get_uint(2); @@ -620,7 +624,6 @@ class Display break; } } - void read_callback(mixed id, string data) { // werror(sprintf("Xlib: received '%s'\n", data)); @@ -650,7 +653,7 @@ class Display handle_action(a); set_nonblocking(read_callback, write_callback, close_callback); } - + int open(string|void display) { int async = !!connect_handler; @@ -712,6 +715,7 @@ class Display if (!connect(host, port)) return 0; } + set_buffer( 65536 ); screen_number = (int) fields[2]; @@ -756,7 +760,6 @@ class Display get_keyboard_mapping(); set_nonblocking(read_callback, write_callback, close_callback); return 1; - break; case ACTION_CONNECT_FAILED: werror("Connection failed: "+a[1]+"\n"); return 0; @@ -813,10 +816,12 @@ class Display pending_actions->put(a); } } + if (!pending_actions->is_empty()) call_out(process_pending_actions, 0); else set_nonblocking(read_callback,write_callback,close_callback); + return ({ success, result }); } diff --git a/lib/modules/Protocols.pmod/X.pmod/_Xlib.pmod b/lib/modules/Protocols.pmod/X.pmod/_Xlib.pmod index 0b39a561c02d278af340cd49601039b60a1b96f0..c0cce15cfb5ac782200db45388bcfcdc2dfa4cf8 100644 --- a/lib/modules/Protocols.pmod/X.pmod/_Xlib.pmod +++ b/lib/modules/Protocols.pmod/X.pmod/_Xlib.pmod @@ -162,3 +162,13 @@ array(string) error_codes = "Length", /* Request length incorrect */ "Implementation" /* server is defective */ }); + +array(string) visual_classes = +({ + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor", +});