X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=xoptions.c;h=cd18a57e41217b8735fa2a5a1f4a4f8412a3a82c;hb=7e0222e64da6706bf0dc2468f459b98e4346206b;hp=b3c88c442f8b01acf0f7f82cc6f53b09a932bdf8;hpb=d92feb6fa2927dc74eda4d9f1fca2265de4b95d1;p=xboard.git diff --git a/xoptions.c b/xoptions.c index b3c88c4..cd18a57 100644 --- a/xoptions.c +++ b/xoptions.c @@ -68,6 +68,9 @@ extern char *getenv(); #include #include +#include +#include + #include "common.h" #include "backend.h" #include "xboard.h" @@ -140,6 +143,18 @@ static Arg formArgs[] = { }; void +MarkMenuItem (char *menuRef, int state) +{ + MenuItem *item = MenuNameToItem(menuRef); + + if(item) { + Arg args[2]; + XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None); + XtSetValues(item->handle, args, 1); + } +} + +void GetWidgetText (Option *opt, char **buf) { Arg arg; @@ -409,7 +424,7 @@ Widget shells[NrOfDialogs]; DialogClass parents[NrOfDialogs]; WindowPlacement *wp[NrOfDialogs] = { // Beware! Order must correspond to DialogClass enum NULL, &wpComment, &wpTags, NULL, NULL, NULL, NULL, &wpMoveHistory, &wpGameList, &wpEngineOutput, &wpEvalGraph, - NULL, NULL, NULL, NULL, &wpMain + NULL, NULL, NULL, NULL, /*&wpMain*/ NULL }; int @@ -535,19 +550,44 @@ GraphEventProc(Widget widget, caddr_t client_data, XEvent *event) { // handle expose and mouse events on Graph widget Dimension w, h; Arg args[16]; - int j, button=10, f=1; - Option *opt; + int j, button=10, f=1, sizing=0; + Option *opt, *graph = (Option *) client_data; + PointerCallback *userHandler = graph->target; + if (!XtIsRealized(widget)) return; switch(event->type) { - case Expose: - if (((XExposeEvent*)event)->count > 0) return; // don't bother if further exposure is pending - /* Get client area */ + case Expose: // make handling of expose events generic, just copying from memory buffer (->choice) to display (->textValue) + /* Get window size */ j = 0; XtSetArg(args[j], XtNwidth, &w); j++; XtSetArg(args[j], XtNheight, &h); j++; XtGetValues(widget, args, j); - break; + + if(w < graph->max || w > graph->max + 1 || h != graph->value) { // use width fudge of 1 pixel + if(((XExposeEvent*)event)->count >= 0) { // suppress sizing on expose for ordered redraw in response to sizing. + sizing = 1; + graph->max = w; graph->value = h; // note: old values are kept if we we don't exceed width fudge + } + } else w = graph->max; + + if(sizing && ((XExposeEvent*)event)->count > 0) { graph->max = 0; return; } // don't bother if further exposure is pending during resize + if(!graph->textValue || sizing) { // create surfaces of new size for display widget + if(graph->textValue) cairo_surface_destroy((cairo_surface_t *)graph->textValue); + graph->textValue = (char*) cairo_xlib_surface_create(xDisplay, XtWindow(widget), DefaultVisual(xDisplay, 0), w, h); + } + if(sizing) { // the memory buffer was already created in GenericPopup(), + // to give drawing routines opportunity to use it before first expose event + // (which are only processed when main gets to the event loop, so after all init!) + // so only change when size is no longer good + if(graph->choice) cairo_surface_destroy((cairo_surface_t *) graph->choice); + graph->choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); + break; + } + w = ((XExposeEvent*)event)->width; + if(((XExposeEvent*)event)->x + w > graph->max) w--; // cut off fudge pixel + if(w) ExposeRedraw(graph, ((XExposeEvent*)event)->x, ((XExposeEvent*)event)->y, w, ((XExposeEvent*)event)->height); + return; case MotionNotify: f = 0; w = ((XButtonEvent*)event)->x; h = ((XButtonEvent*)event)->y; @@ -565,7 +605,7 @@ GraphEventProc(Widget widget, caddr_t client_data, XEvent *event) } } button *= f; - opt = ((PointerCallback*) client_data)(button, w, h); + opt = userHandler(button, w, h); if(opt) { // user callback specifies a context menu; pop it up XUngrabPointer(xDisplay, CurrentTime); XtCallActionProc(widget, "XawPositionSimpleMenu", event, &(opt->name), 1); @@ -574,6 +614,15 @@ GraphEventProc(Widget widget, caddr_t client_data, XEvent *event) XSync(xDisplay, False); } +void +GraphExpose (Option *opt, int x, int y, int w, int h) +{ + XExposeEvent e; + if(!opt->handle) return; + e.x = x; e.y = y; e.width = w; e.height = h; e.count = -1; e.type = Expose; // count = -1: kludge to suppress sizing + GraphEventProc(opt->handle, (caddr_t) opt, (XEvent *) &e); // fake expose event +} + static void GenericCallback (Widget w, XtPointer client_data, XtPointer call_data) { // all Buttons in a dialog (including OK, cancel) invoke this @@ -744,7 +793,6 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent if(engineDlg) { // Settings popup for engine: format through heuristic int n = currentCps->nrOptions; - if(!n) { DisplayNote(_("Engine has no options")); currentCps = NULL; return 0; } if(n > 50) width = 4; else if(n>24) width = 2; else width = 1; height = n / width + 1; if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = SAME_ROW; // OK on same line @@ -965,8 +1013,9 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent option[i].handle = (void*) (last = XtCreateManagedWidget("graph", widgetClass, form, args, j)); XtAddEventHandler(last, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask, False, - (XtEventHandler) GraphEventProc, option[i].target); // mandatory user-supplied expose handler + (XtEventHandler) GraphEventProc, &option[i]); // mandatory user-supplied expose handler if(option[i].min & SAME_ROW) last = forelast, forelast = lastrow; + option[i].choice = (char**) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, option[i].max, option[i].value); // image buffer break; case PopUp: // note: used only after Graph, so 'last' refers to the Graph widget option[i].handle = (void*) CreateComboPopup(last, option + i, i + 256*dlgNr, TRUE, option[i].value);