Allow resizing of board window
authorH.G. Muller <h.g.muller@hccnet.nl>
Fri, 5 Oct 2012 12:07:53 +0000 (14:07 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Sun, 21 Oct 2012 09:28:12 +0000 (11:28 +0200)
In full png mode the size of the board window is no longer locked.
After resizing, the square size is calculated as the largest one that
would fit the window, and the window is then shrunk around it. To prevent
excessive redrawing during sizing, the redraw is delayed by putting it
in DragProc.

xboard.c
xoptions.c

index 55655a5..a33b765 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -927,6 +927,15 @@ ConvertToLine (int argc, char **argv)
 
 //--------------------------------------------------------------------------------------------
 
+void
+NewSurfaces ()
+{
+    // delete surfaces after size becomes invalid, so they will be recreated
+    if(csBoardWindow) cairo_surface_destroy(csBoardWindow);
+    if(csBoardBackup) cairo_surface_destroy(csBoardBackup);
+    csBoardWindow = csBoardBackup = NULL;
+}
+
 #define BoardSize int
 void
 InitDrawingSizes (BoardSize boardSize, int flags)
@@ -950,15 +959,16 @@ InitDrawingSizes (BoardSize boardSize, int flags)
 
     oldWidth = boardWidth; oldHeight = boardHeight;
     CreateGrid();
+    NewSurfaces();
 
     /*
      * Inhibit shell resizing.
      */
-    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW ;
+    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + 1; // [HGM] not sure why the +1 is (sometimes) needed...
     shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
-    XtSetValues(shellWidget, &shellArgs[0], 6);
+    XtSetValues(shellWidget, &shellArgs[0], cairoAnimate ? 2 : 6);
 
     XSync(xDisplay, False);
     DelayedDrag();
@@ -1045,7 +1055,7 @@ printf("Copy pieces\n");
     oldVariant = gameInfo.variant;
   }
 #if HAVE_LIBXPM
-  if(appData.monoMode != oldMono)
+  if(appData.monoMode != oldMono || cairoAnimate)
     CreateAnimVars();
 #endif
   oldMono = appData.monoMode;
@@ -1528,7 +1538,7 @@ XBoard square size (hint): %d\n\
     XtGetValues(shellWidget, shellArgs, 2);
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
-    XtSetValues(shellWidget, &shellArgs[2], 4);
+    if(!cairoAnimate) XtSetValues(shellWidget, &shellArgs[2], 4);
     marginW =  w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
     marginH =  h - boardHeight;
 
@@ -2244,14 +2254,13 @@ ScaleOnePiece (char *name, int color, int piece)
   cairo_t *cr;
   static cairo_surface_t *pngPieceImages[2][(int)BlackPawn+4];   // png 256 x 256 images
 
-  if(pngPieceImages[color][piece] == NULL) { // if PNG file for this piece was not yet read, read it now and store it
+  if((img = pngPieceImages[color][piece]) == NULL) { // if PNG file for this piece was not yet read, read it now and store it
     snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pngDirectory, color ? "Black" : "White", pngPieceNames[piece]);
     pngPieceImages[color][piece] = img = cairo_image_surface_create_from_png (buf);
     w = cairo_image_surface_get_width (img);
     h = cairo_image_surface_get_height (img);
     if(w != 64 || h != 64) { printf("Bad png size %dx%d in %s\n", w, h, buf); exit(1); }
   }
-
   // create new bitmap to hold scaled piece image (and remove any old)
   if(pngPieceBitmaps2[color][piece]) cairo_surface_destroy (pngPieceBitmaps2[color][piece]);
   pngPieceBitmaps2[color][piece] = cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
@@ -2262,7 +2271,6 @@ ScaleOnePiece (char *name, int color, int piece)
   cairo_set_source_surface (cr, img, 0, 0);
   cairo_paint (cr);
   cairo_destroy (cr);
-  cairo_surface_destroy (img);
 }
 
 void
@@ -2899,15 +2907,37 @@ CoDrag (Widget sh, WindowPlacement *wp)
     XtSetValues(sh, args, j);
 }
 
+void
+ReSize (WindowPlacement *wp)
+{
+       int sqx, sqy;
+       if(wp->width == wpMain.width && wp->height == wpMain.height) return; // not sized
+       sqx = (wp->width  - lineGap - marginW) / BOARD_WIDTH - lineGap;
+       sqy = (wp->height - lineGap - marginH) / BOARD_HEIGHT - lineGap;
+       if(sqy < sqx) sqx = sqy;
+       if(sqx != squareSize) {
+           squareSize = sqx; // adopt new square size
+           NewSurfaces();
+           CreatePNGPieces(); // make newly scaled pieces
+           InitDrawingSizes(0, 0); // creates grid etc.
+       }
+}
+
 static XtIntervalId delayedDragID = 0;
 
 void
 DragProc ()
 {
+       static int busy;
+       if(busy) return;
+
+       busy = 1;
        GetActualPlacement(shellWidget, &wpNew);
        if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved
-          wpNew.width == wpMain.width && wpNew.height == wpMain.height) // not sized
-           return; // false alarm
+          wpNew.width == wpMain.width && wpNew.height == wpMain.height) { // not sized
+           busy = 0; return; // false alarm
+       }
+       ReSize(&wpNew);
        if(shellUp[EngOutDlg]) CoDrag(shells[EngOutDlg], &wpEngineOutput);
        if(shellUp[HistoryDlg]) CoDrag(shells[HistoryDlg], &wpMoveHistory);
        if(shellUp[EvalGraphDlg]) CoDrag(shells[EvalGraphDlg], &wpEvalGraph);
@@ -2915,6 +2945,7 @@ DragProc ()
        wpMain = wpNew;
        DrawPosition(True, NULL);
        delayedDragID = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other)
+       busy = 0;
 }
 
 
@@ -2923,7 +2954,7 @@ DelayedDrag ()
 {
     if(delayedDragID) XtRemoveTimeOut(delayedDragID); // cancel pending
     delayedDragID =
-      XtAppAddTimeOut(appContext, 50, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later
+      XtAppAddTimeOut(appContext, 100, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later
 }
 
 void
@@ -3878,6 +3909,8 @@ InitAnimState (AnimNr anr, XWindowAttributes *info)
 
   if(cairoAnimate) {
     DrawSeekOpen(); // set cs to board widget
+    if(c_animBufs[anr]) cairo_surface_destroy (c_animBufs[anr]);
+    if(c_animBufs[anr+2]) cairo_surface_destroy (c_animBufs[anr+2]);
     c_animBufs[anr+4] = csBoardWindow;
     c_animBufs[anr+2] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
     c_animBufs[anr] = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
@@ -3913,7 +3946,7 @@ CreateAnimVars ()
 {
   XWindowAttributes info;
 
-  if (xpmDone && gameInfo.variant == oldVariant) return;
+  if (!cairoAnimate && xpmDone && gameInfo.variant == oldVariant) return;
   if(xpmDone) oldVariant = gameInfo.variant; // first time pieces might not be created yet
   XGetWindowAttributes(xDisplay, xBoardWindow, &info);
 
@@ -3921,7 +3954,7 @@ CreateAnimVars ()
   InitAnimState(Player, &info);
 
   /* For XPM pieces, we need bitmaps to use as masks. */
-  if (useImages)
+  if (useImages & !xpmDone)
     CreateAnimMasks(info.depth), xpmDone = 1;
 }
 
@@ -4043,12 +4076,13 @@ static void
 CairoOverlayPiece (ChessSquare piece, cairo_surface_t *dest)
 {
   static ChessSquare oldPiece = -1;
+  static int oldSize;
   static cairo_t *pieceSource;
-  if(piece != oldPiece) { // try make it faster by only changing cr if we need other piece
+  if(piece != oldPiece || squareSize != oldSize) { // try make it faster by only changing cr if we need other piece
     if(pieceSource) cairo_destroy (pieceSource);
     pieceSource = cairo_create (dest);
     cairo_set_source_surface (pieceSource, pngPieceBitmaps[!White(piece)][piece % BlackPawn], 0, 0);
-    oldPiece = piece;
+    oldPiece = piece; oldSize = squareSize;
   }
   cairo_paint(pieceSource);
 }
index b3c88c4..f80d09b 100644 (file)
@@ -409,7 +409,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