⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tkcanvas.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
DisplayCanvas(clientData)    ClientData clientData;	/* Information about widget. */{    TkCanvas *canvasPtr = (TkCanvas *) clientData;    Tk_Window tkwin = canvasPtr->tkwin;    Tk_Item *itemPtr;    Pixmap pixmap;    int screenX1, screenX2, screenY1, screenY2, width, height;    if (canvasPtr->tkwin == NULL) {	return;    }    if (!Tk_IsMapped(tkwin)) {	goto done;    }    /*     * Choose a new current item if that is needed (this could cause     * event handlers to be invoked).     */    while (canvasPtr->flags & REPICK_NEEDED) {	Tcl_Preserve((ClientData) canvasPtr);	canvasPtr->flags &= ~REPICK_NEEDED;	PickCurrentItem(canvasPtr, &canvasPtr->pickEvent);	tkwin = canvasPtr->tkwin;	Tcl_Release((ClientData) canvasPtr);	if (tkwin == NULL) {	    return;	}    }    /*     * Compute the intersection between the area that needs redrawing     * and the area that's visible on the screen.     */    if ((canvasPtr->redrawX1 < canvasPtr->redrawX2)	    && (canvasPtr->redrawY1 < canvasPtr->redrawY2)) {	screenX1 = canvasPtr->xOrigin + canvasPtr->inset;	screenY1 = canvasPtr->yOrigin + canvasPtr->inset;	screenX2 = canvasPtr->xOrigin + Tk_Width(tkwin) - canvasPtr->inset;	screenY2 = canvasPtr->yOrigin + Tk_Height(tkwin) - canvasPtr->inset;	if (canvasPtr->redrawX1 > screenX1) {	    screenX1 = canvasPtr->redrawX1;	}	if (canvasPtr->redrawY1 > screenY1) {	    screenY1 = canvasPtr->redrawY1;	}	if (canvasPtr->redrawX2 < screenX2) {	    screenX2 = canvasPtr->redrawX2;	}	if (canvasPtr->redrawY2 < screenY2) {	    screenY2 = canvasPtr->redrawY2;	}	if ((screenX1 >= screenX2) || (screenY1 >= screenY2)) {	    goto borders;	}    	/*	 * Redrawing is done in a temporary pixmap that is allocated	 * here and freed at the end of the procedure.  All drawing	 * is done to the pixmap, and the pixmap is copied to the	 * screen at the end of the procedure. The temporary pixmap	 * serves two purposes:	 *	 * 1. It provides a smoother visual effect (no clearing and	 *    gradual redraw will be visible to users).	 * 2. It allows us to redraw only the objects that overlap	 *    the redraw area.  Otherwise incorrect results could	 *	  occur from redrawing things that stick outside of	 *	  the redraw area (we'd have to redraw everything in	 *    order to make the overlaps look right).	 *	 * Some tricky points about the pixmap:	 *	 * 1. We only allocate a large enough pixmap to hold the	 *    area that has to be redisplayed.  This saves time in	 *    in the X server for large objects that cover much	 *    more than the area being redisplayed:  only the area	 *    of the pixmap will actually have to be redrawn.	 * 2. Some X servers (e.g. the one for DECstations) have troubles	 *    with characters that overlap an edge of the pixmap (on the	 *    DEC servers, as of 8/18/92, such characters are drawn one	 *    pixel too far to the right).  To handle this problem,	 *    make the pixmap a bit larger than is absolutely needed	 *    so that for normal-sized fonts the characters that overlap	 *    the edge of the pixmap will be outside the area we care	 *    about.	 */    	canvasPtr->drawableXOrigin = screenX1 - 30;	canvasPtr->drawableYOrigin = screenY1 - 30;	pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),	    (screenX2 + 30 - canvasPtr->drawableXOrigin),	    (screenY2 + 30 - canvasPtr->drawableYOrigin),	    Tk_Depth(tkwin));    	/*	 * Clear the area to be redrawn.	 */    	width = screenX2 - screenX1;	height = screenY2 - screenY1;    	XFillRectangle(Tk_Display(tkwin), pixmap, canvasPtr->pixmapGC,		screenX1 - canvasPtr->drawableXOrigin,		screenY1 - canvasPtr->drawableYOrigin, (unsigned int) width,		(unsigned int) height);    	/*	 * Scan through the item list, redrawing those items that need it.	 * An item must be redraw if either (a) it intersects the smaller	 * on-screen area or (b) it intersects the full canvas area and its	 * type requests that it be redrawn always (e.g. so subwindows can	 * be unmapped when they move off-screen).	 */    	for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;		itemPtr = itemPtr->nextPtr) {	    if ((itemPtr->x1 >= screenX2)		    || (itemPtr->y1 >= screenY2)		    || (itemPtr->x2 < screenX1)		    || (itemPtr->y2 < screenY1)) {		if (!itemPtr->typePtr->alwaysRedraw			|| (itemPtr->x1 >= canvasPtr->redrawX2)			|| (itemPtr->y1 >= canvasPtr->redrawY2)			|| (itemPtr->x2 < canvasPtr->redrawX1)			|| (itemPtr->y2 < canvasPtr->redrawY1)) {		    continue;		}	    }	    (*itemPtr->typePtr->displayProc)((Tk_Canvas) canvasPtr, itemPtr,		    canvasPtr->display, pixmap, screenX1, screenY1, width,		    height);	}    	/*	 * Copy from the temporary pixmap to the screen, then free up	 * the temporary pixmap.	 */    	XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin),		canvasPtr->pixmapGC,		screenX1 - canvasPtr->drawableXOrigin,		screenY1 - canvasPtr->drawableYOrigin,		(unsigned) (screenX2 - screenX1),		(unsigned) (screenY2 - screenY1),		screenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin);	Tk_FreePixmap(Tk_Display(tkwin), pixmap);    }    /*     * Draw the window borders, if needed.     */    borders:    if (canvasPtr->flags & REDRAW_BORDERS) {	canvasPtr->flags &= ~REDRAW_BORDERS;	if (canvasPtr->borderWidth > 0) {	    Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin),		    canvasPtr->bgBorder, canvasPtr->highlightWidth,		    canvasPtr->highlightWidth,		    Tk_Width(tkwin) - 2*canvasPtr->highlightWidth,		    Tk_Height(tkwin) - 2*canvasPtr->highlightWidth,		    canvasPtr->borderWidth, canvasPtr->relief);	}	if (canvasPtr->highlightWidth != 0) {	    GC gc;    	    if (canvasPtr->textInfo.gotFocus) {		gc = Tk_GCForColor(canvasPtr->highlightColorPtr,			Tk_WindowId(tkwin));	    } else {		gc = Tk_GCForColor(canvasPtr->highlightBgColorPtr,			Tk_WindowId(tkwin));	    }	    Tk_DrawFocusHighlight(tkwin, gc, canvasPtr->highlightWidth,		    Tk_WindowId(tkwin));	}    }    done:    canvasPtr->flags &= ~REDRAW_PENDING;    canvasPtr->redrawX1 = canvasPtr->redrawX2 = 0;    canvasPtr->redrawY1 = canvasPtr->redrawY2 = 0;    if (canvasPtr->flags & UPDATE_SCROLLBARS) {	CanvasUpdateScrollbars(canvasPtr);    }}/* *-------------------------------------------------------------- * * CanvasEventProc -- * *	This procedure is invoked by the Tk dispatcher for various *	events on canvases. * * Results: *	None. * * Side effects: *	When the window gets deleted, internal structures get *	cleaned up.  When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */static voidCanvasEventProc(clientData, eventPtr)    ClientData clientData;	/* Information about window. */    XEvent *eventPtr;		/* Information about event. */{    TkCanvas *canvasPtr = (TkCanvas *) clientData;    if (eventPtr->type == Expose) {	int x, y;	x = eventPtr->xexpose.x + canvasPtr->xOrigin;	y = eventPtr->xexpose.y + canvasPtr->yOrigin;	Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, x, y,		x + eventPtr->xexpose.width,		y + eventPtr->xexpose.height);	if ((eventPtr->xexpose.x < canvasPtr->inset)		|| (eventPtr->xexpose.y < canvasPtr->inset)		|| ((eventPtr->xexpose.x + eventPtr->xexpose.width)		    > (Tk_Width(canvasPtr->tkwin) - canvasPtr->inset))		|| ((eventPtr->xexpose.y + eventPtr->xexpose.height)		    > (Tk_Height(canvasPtr->tkwin) - canvasPtr->inset))) {	    canvasPtr->flags |= REDRAW_BORDERS;	}    } else if (eventPtr->type == DestroyNotify) {	if (canvasPtr->tkwin != NULL) {	    canvasPtr->tkwin = NULL;            Tcl_DeleteCommandFromToken(canvasPtr->interp,		    canvasPtr->widgetCmd);	}	if (canvasPtr->flags & REDRAW_PENDING) {	    Tcl_CancelIdleCall(DisplayCanvas, (ClientData) canvasPtr);	}	Tcl_EventuallyFree((ClientData) canvasPtr, DestroyCanvas);    } else if (eventPtr->type == ConfigureNotify) {	canvasPtr->flags |= UPDATE_SCROLLBARS;	/*	 * The call below is needed in order to recenter the canvas if	 * it's confined and its scroll region is smaller than the window.	 */	CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);	Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, canvasPtr->xOrigin,		canvasPtr->yOrigin,		canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),		canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));	canvasPtr->flags |= REDRAW_BORDERS;    } else if (eventPtr->type == FocusIn) {	if (eventPtr->xfocus.detail != NotifyInferior) {	    CanvasFocusProc(canvasPtr, 1);	}    } else if (eventPtr->type == FocusOut) {	if (eventPtr->xfocus.detail != NotifyInferior) {	    CanvasFocusProc(canvasPtr, 0);	}    } else if (eventPtr->type == UnmapNotify) {	Tk_Item *itemPtr;	/*	 * Special hack:  if the canvas is unmapped, then must notify	 * all items with "alwaysRedraw" set, so that they know that	 * they are no longer displayed.	 */	for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;		itemPtr = itemPtr->nextPtr) {	    if (itemPtr->typePtr->alwaysRedraw) {		(*itemPtr->typePtr->displayProc)((Tk_Canvas) canvasPtr,			itemPtr, canvasPtr->display, None, 0, 0, 0, 0);	    }	}    }}/* *---------------------------------------------------------------------- * * CanvasCmdDeletedProc -- * *	This procedure is invoked when a widget command is deleted.  If *	the widget isn't already in the process of being destroyed, *	this command destroys it. * * Results: *	None. * * Side effects: *	The widget is destroyed. * *---------------------------------------------------------------------- */static voidCanvasCmdDeletedProc(clientData)    ClientData clientData;	/* Pointer to widget record for widget. */{    TkCanvas *canvasPtr = (TkCanvas *) clientData;    Tk_Window tkwin = canvasPtr->tkwin;    /*     * This procedure could be invoked either because the window was     * destroyed and the command was then deleted (in which case tkwin     * is NULL) or because the command was deleted, and then this procedure     * destroys the widget.     */    if (tkwin != NULL) {	canvasPtr->tkwin = NULL;	Tk_DestroyWindow(tkwin);    }}/* *-------------------------------------------------------------- * * Tk_CanvasEventuallyRedraw -- * *	Arrange for part or all of a canvas widget to redrawn at *	some convenient time in the future. * * Results: *	None. * * Side effects: *	The screen will eventually be refreshed. * *-------------------------------------------------------------- */voidTk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2)    Tk_Canvas canvas;		/* Information about widget. */    int x1, y1;			/* Upper left corner of area to redraw.				 * Pixels on edge are redrawn. */    int x2, y2;			/* Lower right corner of area to redraw.				 * Pixels on edge are not redrawn. */{    TkCanvas *canvasPtr = (TkCanvas *) canvas;    if ((x1 == x2) || (y1 == y2)) {	return;    }    if (canvasPtr->flags & REDRAW_PENDING) {	if (x1 <= canvasPtr->redrawX1) {	    canvasPtr->redrawX1 = x1;	}	if (y1 <= canvasPtr->redrawY1) {	    canvasPtr->redrawY1 = y1;	}	if (x2 >= canvasPtr->redrawX2) {	    canvasPtr->redrawX2 = x2;	}	if (y2 >= canvasPtr->redrawY2) {	    canvasPtr->redrawY2 = y2;	}    } else {	canvasPtr->redrawX1 = x1;	canvasPtr->redrawY1 = y1;	canvasPtr->redrawX2 = x2;	canvasPtr->redrawY2 = y2;	Tcl_DoWhenIdle(DisplayCanvas, (ClientData) canvasPtr);	canvasPtr->flags |= REDRAW_PENDING;    }}/* *-------------------------------------------------------------- * * Tk_CreateItemType -- * *	This procedure may be invoked to add a new kind of canvas *	element to the core item types supported by Tk. * * Results: *	None. * * Side effects: *	From now on, the new item type will be useable in canvas *	widgets (e.g. typePtr->name can be used as the item type *	in "create" widget commands).  If there was already a *	type with the same name as in typePtr, it is replaced with *	the new type. * *-------------------------------------------------------------- */voidTk_CreateItemType(typePtr)    Tk_ItemType *typePtr;		/* Information about item type;					 * storage must be statically					 * allocated (must live forever). */{    Tk_ItemType *typePtr2, *prevPtr;    if (typeList == NULL) {	InitCanvas();    }    /*     * If there's already an item type with the given name, remove it.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -