diff options
-rw-r--r-- | generic/tkZinc.c | 271 |
1 files changed, 176 insertions, 95 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c index 77f5661..3baa747 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -65,6 +65,9 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " #include <sys/shm.h> #include <X11/extensions/XShm.h> #endif +#ifdef GLX +#include <GL/glx.h> +#endif #if 0 @@ -490,6 +493,23 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->interp = interp; wi->dpy = Tk_Display(tkwin); wi->screen = Tk_Screen(tkwin); + wi->has_glx = False; +#ifdef GLX + if (glXQueryExtension(wi->dpy, &first_err, &first_evt)) { + if (glXQueryVersion(wi->dpy, &major_op, &minor_op)) { + if ((major_op == 1) && (minor_op >= 2)) { +#if 0 + printf("GLX version %d.%d\n", major_op, minor_op); + printf("OpenGL version %s\n", (char *) glGetString(GL_VERSION)); + printf(" moteur de rendu : %s\n", (char *) glGetString(GL_RENDERER)); + printf(" fabriquant : %s\n", (char *) glGetString(GL_VENDOR)); + printf(" extensions présentes : %s\n", (char *) glGetString(GL_EXTENSIONS)); +#endif + wi->has_glx = True; + } + } + } +#endif wi->has_x_shm = False; #ifdef SHM if (XQueryExtension(wi->dpy, "MIT-SHM", &major_op, &first_evt, &first_err)) { @@ -619,12 +639,12 @@ ZincObjCmd(ClientData client_data, /* Main window associated with (ClientData) wi); Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING, FetchSelection, (ClientData) wi, XA_STRING); - + if (Configure(interp, wi, argc-2, args+2, 0) != TCL_OK) { Tk_DestroyWindow(tkwin); return ZN_ERROR; } - + ResetBBox(&wi->exposed_area); wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0; wi->damaged_area.corner.x = wi->width = wi->opt_width; @@ -639,6 +659,43 @@ ZincObjCmd(ClientData client_data, /* Main window associated with CreateSharedImageBuffer(wi); #endif #endif +#ifdef GLX + if (wi->has_glx) { + int val; + int attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_BUFFER_SIZE, 16, + GLX_STENCIL_SIZE, 1, None }; + + wi->gl_visual = glXChooseVisual(wi->dpy, XScreenNumberOfScreen(wi->screen), attribs); + if (!wi->gl_visual) { + wi->render = False; + } + printf("Visual is 0x%x, ", (int) wi->gl_visual->visualid); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_RGBA, &val); + printf("RGBA %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_DOUBLEBUFFER, &val); + printf("Double Buffer %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_STENCIL_SIZE, &val); + printf("Stencil %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_BUFFER_SIZE, &val); + printf("depth %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_RED_SIZE, &val); + printf("red %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_GREEN_SIZE, &val); + printf("green %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_BLUE_SIZE, &val); + printf("blue %d, ", val); + glXGetConfig(wi->dpy, wi->gl_visual, GLX_ALPHA_SIZE, &val); + printf("alpha %d\n", val); + wi->gl_context = glXCreateContext(wi->dpy, wi->gl_visual, NULL, True); + if (!wi->gl_context) { + wi->render = False; + } + printf("Context: %d\n", glXIsDirect(wi->dpy, wi->gl_context)); + Tk_SetWindowVisual(wi->win, wi->gl_visual->visual, + Tk_Depth(wi->win), Tk_Colormap(wi->win)); + } +#endif } if (!wi->render) { wi->draw_buffer = XCreatePixmap(wi->dpy, RootWindowOfScreen(wi->screen), @@ -1673,11 +1730,11 @@ DoItem(Tcl_Interp *interp, Tk_Uid tag_uid) { if (tag_uid == NULL) { - Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), - NewLongObj(item->id)); + Tcl_Obj *l; + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, NewLongObj(item->id)); if (part != ZN_NO_PART) { - Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), - Tcl_NewIntObj(part)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(part)); } } else { @@ -2198,14 +2255,20 @@ Contour(WidgetInfo *wi, return ZN_ERROR; } cmd = ops[index]; - + result = ZnItemWithTagOrId(wi, args[4], wi->top_group, True, &shape, search_var); if ((result == ZN_ERROR) || (shape == ZN_NO_ITEM)) { Tcl_ResetResult(wi->interp); if (ParseCoordList(wi, args[4], &points, &num_points) == ZN_ERROR) { return ZN_ERROR; } - POLY_CONTOUR1(&poly, points, num_points); + POLY_CONTOUR1(&poly, NULL, num_points); + /* + * Allocate a fresh point array, ParseCoordList returns a shared + * array. + */ + poly.contours[0].points = (ZnPoint *) ZnMalloc(num_points*sizeof(ZnPoint)); + memcpy(poly.contours[0].points, points, num_points*sizeof(ZnPoint)); } else { /* @@ -2296,11 +2359,13 @@ Coords(WidgetInfo *wi, result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True, &item, search_var); if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) { + Tcl_AppendResult(wi->interp, " unknown item \"", + Tcl_GetString(args[2]), "\"", NULL); return ZN_ERROR; } num_points = 0; - /* printf(" coords: argc=%d, item %d class: %s\n", - argc, item->id, item->class->name);*/ + /* printf(" coords: argc=%d, item %d class: %s\n", + argc, item->id, item->class->name); */ if (argc == 3) { /* Get all coords of default contour (0). */ if (item->class->Coords(item, 0, 0, COORDS_READ_ALL, @@ -2346,8 +2411,9 @@ Coords(WidgetInfo *wi, * Try to see if the next param is a vertex index, * a contour index or a coord list. */ - /*printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i]));*/ + /* printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i])); */ if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != ZN_OK) { + Tcl_ResetResult(wi->interp); if (((argc == 5) && (cmd != COORDS_ADD) && (cmd != COORDS_REMOVE)) || (argc == 6) || (argc == 7)) { Tcl_AppendResult(wi->interp, " incorrect contour index \"", @@ -2378,6 +2444,7 @@ Coords(WidgetInfo *wi, } return ZN_OK; } + contour = index; if (argc == 4) { /* Get all coords of contour. */ @@ -2395,13 +2462,13 @@ Coords(WidgetInfo *wi, } return ZN_OK; } - /* * Try to see if the next param is a vertex index or a coord list. */ i++; /*printf(" coords: arg %d is %s\n", i, Tcl_GetString(args[i]));*/ if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != ZN_OK) { + Tcl_ResetResult(wi->interp); if ((argc == 7) || ((argc == 6) && (cmd != COORDS_ADD))) { Tcl_AppendResult(wi->interp, " incorrect coord index \"", Tcl_GetString(args[i]), "\"", NULL); @@ -2489,7 +2556,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ int num = 0, i, j; char *end, *str; ZnTransfo *t = NULL; - Tcl_Obj *l, *lobjs[10]; + Tcl_Obj *l; TagSearch *search_var = NULL; Tcl_HashEntry *entry; static char *sub_cmd_strings[] = { @@ -2683,15 +2750,11 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ } } if (!IsEmptyBBox(&bbox)) { - lobjs[0] = NewDoubleObj(bbox.orig.x+wi->inset); - lobjs[1] = NewDoubleObj(bbox.orig.y+wi->inset); - lobjs[2] = NewDoubleObj(bbox.corner.x+wi->inset); - lobjs[3] = NewDoubleObj(bbox.corner.y+wi->inset); - l = Tcl_NewListObj(4, lobjs); - Tcl_SetObjResult(interp, l); -#ifdef PTK - Tcl_DecrRefCount(l); -#endif + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, NewDoubleObj(bbox.orig.x+wi->inset)); + Tcl_ListObjAppendElement(interp, l, NewDoubleObj(bbox.orig.y+wi->inset)); + Tcl_ListObjAppendElement(interp, l, NewDoubleObj(bbox.corner.x+wi->inset)); + Tcl_ListObjAppendElement(interp, l, NewDoubleObj(bbox.corner.y+wi->inset)); } } break; @@ -3519,18 +3582,13 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ int num_actions; GetChrono(wi->total_draw_chrono, &ttime, &num_actions); GetChrono(wi->this_draw_chrono, <ime, NULL); - lobjs[0] = Tcl_NewIntObj(num_actions); - lobjs[1] = Tcl_NewIntObj(ltime); - lobjs[2] = Tcl_NewIntObj(ttime); - l = Tcl_NewListObj(3, lobjs); - /*lobjs[2] = Tcl_NewIntObj(wi->damaged_area_w); - lobjs[3] = Tcl_NewIntObj(wi->damaged_area_h); - lobjs[4] = Tcl_NewIntObj(ttime); - l = Tcl_NewListObj(5, lobjs);*/ - Tcl_SetObjResult(interp, l); -#ifdef PTK - Tcl_DecrRefCount(l); -#endif + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(num_actions)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ltime)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime)); + /*Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_w)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_h)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime));*/ } } break; @@ -4105,14 +4163,16 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. */ } result = ZnItemWithTagOrId(wi, args[2], wi->top_group, True, &item, &search_var); - if ((result == ZN_ERROR) || (item == ZN_NO_ITEM)) { + if (result == ZN_ERROR) { goto error; } - l = NewStringObj(item->class->name); - Tcl_SetObjResult(interp, l); + if (item != ZN_NO_ITEM) { + l = NewStringObj(item->class->name); + Tcl_SetObjResult(interp, l); #ifdef PTK - Tcl_DecrRefCount(l); + Tcl_DecrRefCount(l); #endif + } } break; /* @@ -4483,6 +4543,11 @@ Event(ClientData client_data, /* Information about widget. */ if (event->type == MapNotify) { if (!wi->gc) { wi->realized = True; +#ifdef GLX + if (wi->render) { + glXMakeCurrent(wi->dpy, ZnWindowId(wi->win), wi->gl_context); + } +#endif /* * Get the work GC and suppress GraphicExpose * and NoExpose events reception. @@ -4693,7 +4758,7 @@ DoEvent(WidgetInfo *wi, part = ZN_NO_PART; } - if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, part)) { + if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, ZN_NO_PART)) { return; } @@ -4707,6 +4772,7 @@ DoEvent(WidgetInfo *wi, num_tags = 0; its = items; bind_part = ((wi->current_part != ZN_NO_PART) && + item->class->IsSensitive(item, part) && (wi->current_item->class->num_parts || wi->current_item->class->has_fields)); /* @@ -4818,7 +4884,9 @@ PickCurrentItem(WidgetInfo *wi, XEvent *event) { int button_down; +#ifdef LEFT_GRAB int prev_left_grabbed_item; +#endif /* * Check whether or not a button is down. If so, we'll log entry @@ -4828,10 +4896,12 @@ PickCurrentItem(WidgetInfo *wi, */ button_down = wi->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask); +#ifdef LEFT_GRAB prev_left_grabbed_item = wi->events_flags & LEFT_GRABBED_ITEM; if (!button_down) { wi->events_flags &= ~LEFT_GRABBED_ITEM; } +#endif /* * Save information about this event in the widget. The saved event @@ -4901,8 +4971,11 @@ PickCurrentItem(WidgetInfo *wi, wi->new_item = ZN_NO_ITEM; } - if ((wi->new_item == wi->current_item) && (wi->new_part == wi->current_part) && - !(wi->events_flags & LEFT_GRABBED_ITEM)) { + if ((wi->new_item == wi->current_item) && (wi->new_part == wi->current_part) +#ifdef LEFT_GRAB + && !(wi->events_flags & LEFT_GRABBED_ITEM) +#endif + ) { /* * Nothing to do: the current item/part hasn't changed. */ @@ -4918,18 +4991,19 @@ PickCurrentItem(WidgetInfo *wi, * calling leave when the grab is released. */ if (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) && - (wi->current_item != ZN_NO_ITEM) && - wi->current_item->class->IsSensitive(wi->current_item, wi->current_part) && - !(wi->events_flags & LEFT_GRABBED_ITEM) && - !prev_left_grabbed_item) { + (wi->current_item != ZN_NO_ITEM) +#ifdef LEFT_GRAB + && !(wi->events_flags & LEFT_GRABBED_ITEM) + && !prev_left_grabbed_item +#endif + ) { XEvent event; Item item = wi->current_item; event = wi->pick_event; event.type = LeaveNotify; - /*printf("==LEAVE== %d, sensitive %d\n", wi->current_item->id, - wi->current_item->class->IsSensitive(wi->current_item, wi->current_part));*/ + /*printf("== LEAVE %d %d ==\n", wi->current_item->id, wi->current_part);*/ /* * If the event's detail happens to be NotifyInferior the * binding mechanism will discard the event. To be consistent, @@ -4954,18 +5028,22 @@ PickCurrentItem(WidgetInfo *wi, * item was deleted. */ } +#ifdef LEFT_GRAB if (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) && button_down) { wi->events_flags |= LEFT_GRABBED_ITEM; return; } +#endif +#ifdef LEFT_GRAB /* * Special note: it's possible that wi->new_item == wi->current_item * here. This can happen, for example, if LEFT_GRABBED_ITEM was set or * if there is only a change in the part number. */ wi->events_flags &= ~LEFT_GRABBED_ITEM; +#endif /* * Added to enable DoEvent to make a special case for enter/leaves * between fields in the same item. It may interact with @@ -4981,8 +5059,7 @@ PickCurrentItem(WidgetInfo *wi, } wi->current_part = wi->new_part; - if ((wi->current_item != ZN_NO_ITEM) && - wi->current_item->class->IsSensitive(wi->current_item, wi->current_part)) { + if (wi->current_item != ZN_NO_ITEM) { XEvent event; /* @@ -4993,7 +5070,7 @@ PickCurrentItem(WidgetInfo *wi, /* * Then emit a fake Enter event on it. */ - /*printf("==ENTER==\n");*/ + /*printf("== ENTER %d %d ==\n",wi->current_item->id, wi->current_part);*/ event = wi->pick_event; event.type = EnterNotify; event.xcrossing.detail = NotifyAncestor; @@ -5078,8 +5155,7 @@ Bind(ClientData client_data, /* Information about widget. */ wi->state = event->xbutton.state; PickCurrentItem(wi, event); wi->state ^= mask; - if ((wi->current_item != ZN_NO_ITEM) && - wi->current_item->class->IsSensitive(wi->current_item, wi->current_part)) { + if (wi->current_item != ZN_NO_ITEM) { DoEvent(wi, event); } } @@ -5372,6 +5448,15 @@ Destroy(char *mem_ptr) /* Info about the widget. */ } #endif #endif +#ifdef GLX + if (wi->gl_context) { + glXDestroyContext(wi->dpy, wi->gl_context); + } + if (wi->gl_visual) { + XFree(wi->gl_visual); + } +#endif + Tcl_DeleteTimerHandler(wi->blink_handler); Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0); @@ -5470,7 +5555,7 @@ Redisplay(ClientData client_data) /* Information about the widget. */ ResetBBox(&merge); CopyBBox(&wi->damaged_area, &merge); wi->damaged_area_w = wi->damaged_area.corner.x-wi->damaged_area.orig.x; - wi->damaged_area_h = wi->damaged_area.corner.y-wi->damaged_area.orig.y; + wi->damaged_area_h = wi->damaged_area.corner.y-wi->damaged_area.orig.y; AddBBoxToBBox(&merge, &wi->exposed_area); if (!IsEmptyBBox(&merge)) { BBox2XRect(&merge, &r); @@ -5481,6 +5566,18 @@ Redisplay(ClientData client_data) /* Information about the widget. */ r.x, r.y, r.x+wi->inset, r.y+wi->inset, r.width, r.height); #endif #endif +#ifdef GLX + /* Switch the GL buffers. */ + glXSwapBuffers(wi->dpy, ZnWindowId(wi->win)); + /* + * Wait the end of GL update if we need to do some X + * drawing (specifically borders and highlight). + */ + if ((wi->border_width > 0) || + (wi->highlight_width > 0)) { + glXWaitGL(); + } +#endif } else { XCopyArea(wi->dpy, @@ -5839,7 +5936,7 @@ MapInfoObjCmd(ClientData client_data, { int index, index2, result; MapInfoMaster *master; - Tcl_Obj *l, *lobjs[7]; + Tcl_Obj *l; static char *sub_cmd_strings[] = { "add", "count", "create", "delete", "duplicate", "get", "remove", "replace", "scale", "translate", NULL @@ -6147,17 +6244,13 @@ MapInfoObjCmd(ClientData client_data, int x_from, y_from, x_to, y_to; MapInfoGetLine(master->map_info, insert, NULL, &line_style, &line_width, &x_from, &y_from, &x_to, &y_to); - lobjs[0] = NewStringObj(MapInfoLineStyleToString(line_style)); - lobjs[1] = Tcl_NewIntObj(line_width); - lobjs[2] = Tcl_NewIntObj(x_from); - lobjs[3] = Tcl_NewIntObj(y_from); - lobjs[4] = Tcl_NewIntObj(x_to); - lobjs[5] = Tcl_NewIntObj(y_to); - l = Tcl_NewListObj(6, lobjs); - Tcl_SetObjResult(interp, l); -#ifdef PTK - Tcl_DecrRefCount(l); -#endif + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(line_width)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x_from)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y_from)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x_to)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y_to)); } break; case ZN_E_SYMBOL: @@ -6165,14 +6258,10 @@ MapInfoObjCmd(ClientData client_data, int x, y; char symbol; MapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol); - lobjs[0] = Tcl_NewIntObj(x); - lobjs[1] = Tcl_NewIntObj(y); - lobjs[2] = Tcl_NewIntObj(symbol); - l = Tcl_NewListObj(3, lobjs); - Tcl_SetObjResult(interp, l); -#ifdef PTK - Tcl_DecrRefCount(l); -#endif + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(symbol)); } break; case ZN_E_TEXT: @@ -6183,16 +6272,12 @@ MapInfoObjCmd(ClientData client_data, MapInfoLineStyle line_style; MapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style, &x, &y, &text); - lobjs[0] = Tcl_NewIntObj(x); - lobjs[1] = Tcl_NewIntObj(y); - lobjs[2] = NewStringObj(MapInfoTextStyleToString(text_style)); - lobjs[3] = NewStringObj(MapInfoLineStyleToString(line_style)); - lobjs[4] = NewStringObj(text); - l = Tcl_NewListObj(5, lobjs); - Tcl_SetObjResult(interp, l); -#ifdef PTK - Tcl_DecrRefCount(l); -#endif + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y)); + Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoTextStyleToString(text_style))); + Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); + Tcl_ListObjAppendElement(interp, l, NewStringObj(text)); } break; case ZN_E_ARC: @@ -6203,18 +6288,14 @@ MapInfoObjCmd(ClientData client_data, unsigned int radius; MapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width, ¢er_x, ¢er_y, &radius, &start, &extent); - lobjs[0] = NewStringObj(MapInfoLineStyleToString(line_style)); - lobjs[1] = Tcl_NewIntObj(line_width); - lobjs[2] = Tcl_NewIntObj(center_x); - lobjs[3] = Tcl_NewIntObj(center_y); - lobjs[4] = Tcl_NewIntObj(radius); - lobjs[5] = Tcl_NewIntObj(start); - lobjs[6] = Tcl_NewIntObj(extent); - l = Tcl_NewListObj(7, lobjs); - Tcl_SetObjResult(interp, l); -#ifdef PTK - Tcl_DecrRefCount(l); -#endif + l = Tcl_GetObjResult(interp); + Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(line_width)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(center_x)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(center_y)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(radius)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(start)); + Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(extent)); } break; } |