Import Tk 8.6.6 (as of svn r86089)
This commit is contained in:
166
generic/ttk/ttkBlink.c
Normal file
166
generic/ttk/ttkBlink.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2004, Joe English.
|
||||
*
|
||||
* Usage:
|
||||
* TtkBlinkCursor(corePtr), usually called in a widget's Init hook,
|
||||
* arranges to periodically toggle the corePtr->flags CURSOR_ON bit
|
||||
* on and off (and schedule a redisplay) whenever the widget has focus.
|
||||
*
|
||||
* Note: Widgets may have additional logic to decide whether
|
||||
* to display the cursor or not (e.g., readonly or disabled states);
|
||||
* TtkBlinkCursor() does not account for this.
|
||||
*
|
||||
* TODO:
|
||||
* Add script-level access to configure application-wide blink rate.
|
||||
*/
|
||||
|
||||
#include <tk.h>
|
||||
#include "ttkTheme.h"
|
||||
#include "ttkWidget.h"
|
||||
|
||||
#define DEF_CURSOR_ON_TIME 600 /* milliseconds */
|
||||
#define DEF_CURSOR_OFF_TIME 300 /* milliseconds */
|
||||
|
||||
/* Interp-specific data for tracking cursors:
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
WidgetCore *owner; /* Widget that currently has cursor */
|
||||
Tcl_TimerToken timer; /* Blink timer */
|
||||
int onTime; /* #milliseconds to blink cursor on */
|
||||
int offTime; /* #milliseconds to blink cursor off */
|
||||
} CursorManager;
|
||||
|
||||
/* CursorManagerDeleteProc --
|
||||
* InterpDeleteProc for cursor manager.
|
||||
*/
|
||||
static void CursorManagerDeleteProc(ClientData clientData, Tcl_Interp *interp)
|
||||
{
|
||||
CursorManager *cm = (CursorManager*)clientData;
|
||||
if (cm->timer) {
|
||||
Tcl_DeleteTimerHandler(cm->timer);
|
||||
}
|
||||
ckfree(clientData);
|
||||
}
|
||||
|
||||
/* GetCursorManager --
|
||||
* Look up and create if necessary the interp's cursor manager.
|
||||
*/
|
||||
static CursorManager *GetCursorManager(Tcl_Interp *interp)
|
||||
{
|
||||
static const char *cm_key = "ttk::CursorManager";
|
||||
CursorManager *cm = Tcl_GetAssocData(interp, cm_key,0);
|
||||
|
||||
if (!cm) {
|
||||
cm = ckalloc(sizeof(*cm));
|
||||
cm->timer = 0;
|
||||
cm->owner = 0;
|
||||
cm->onTime = DEF_CURSOR_ON_TIME;
|
||||
cm->offTime = DEF_CURSOR_OFF_TIME;
|
||||
Tcl_SetAssocData(interp,cm_key,CursorManagerDeleteProc,(ClientData)cm);
|
||||
}
|
||||
return cm;
|
||||
}
|
||||
|
||||
/* CursorBlinkProc --
|
||||
* Timer handler to blink the insert cursor on and off.
|
||||
*/
|
||||
static void
|
||||
CursorBlinkProc(ClientData clientData)
|
||||
{
|
||||
CursorManager *cm = (CursorManager*)clientData;
|
||||
int blinkTime;
|
||||
|
||||
if (cm->owner->flags & CURSOR_ON) {
|
||||
cm->owner->flags &= ~CURSOR_ON;
|
||||
blinkTime = cm->offTime;
|
||||
} else {
|
||||
cm->owner->flags |= CURSOR_ON;
|
||||
blinkTime = cm->onTime;
|
||||
}
|
||||
cm->timer = Tcl_CreateTimerHandler(blinkTime, CursorBlinkProc, clientData);
|
||||
TtkRedisplayWidget(cm->owner);
|
||||
}
|
||||
|
||||
/* LoseCursor --
|
||||
* Turn cursor off, disable blink timer.
|
||||
*/
|
||||
static void LoseCursor(CursorManager *cm, WidgetCore *corePtr)
|
||||
{
|
||||
if (corePtr->flags & CURSOR_ON) {
|
||||
corePtr->flags &= ~CURSOR_ON;
|
||||
TtkRedisplayWidget(corePtr);
|
||||
}
|
||||
if (cm->owner == corePtr) {
|
||||
cm->owner = NULL;
|
||||
}
|
||||
if (cm->timer) {
|
||||
Tcl_DeleteTimerHandler(cm->timer);
|
||||
cm->timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ClaimCursor --
|
||||
* Claim ownership of the insert cursor and blink on.
|
||||
*/
|
||||
static void ClaimCursor(CursorManager *cm, WidgetCore *corePtr)
|
||||
{
|
||||
if (cm->owner == corePtr)
|
||||
return;
|
||||
if (cm->owner)
|
||||
LoseCursor(cm, cm->owner);
|
||||
|
||||
corePtr->flags |= CURSOR_ON;
|
||||
TtkRedisplayWidget(corePtr);
|
||||
|
||||
cm->owner = corePtr;
|
||||
cm->timer = Tcl_CreateTimerHandler(cm->onTime, CursorBlinkProc, cm);
|
||||
}
|
||||
|
||||
/*
|
||||
* CursorEventProc --
|
||||
* Event handler for FocusIn and FocusOut events;
|
||||
* claim/lose ownership of the insert cursor when the widget
|
||||
* acquires/loses keyboard focus.
|
||||
*/
|
||||
|
||||
#define CursorEventMask (FocusChangeMask|StructureNotifyMask)
|
||||
#define RealFocusEvent(d) \
|
||||
(d == NotifyInferior || d == NotifyAncestor || d == NotifyNonlinear)
|
||||
|
||||
static void
|
||||
CursorEventProc(ClientData clientData, XEvent *eventPtr)
|
||||
{
|
||||
WidgetCore *corePtr = (WidgetCore *)clientData;
|
||||
CursorManager *cm = GetCursorManager(corePtr->interp);
|
||||
|
||||
switch (eventPtr->type) {
|
||||
case DestroyNotify:
|
||||
if (cm->owner == corePtr)
|
||||
LoseCursor(cm, corePtr);
|
||||
Tk_DeleteEventHandler(
|
||||
corePtr->tkwin, CursorEventMask, CursorEventProc, clientData);
|
||||
break;
|
||||
case FocusIn:
|
||||
if (RealFocusEvent(eventPtr->xfocus.detail))
|
||||
ClaimCursor(cm, corePtr);
|
||||
break;
|
||||
case FocusOut:
|
||||
if (RealFocusEvent(eventPtr->xfocus.detail))
|
||||
LoseCursor(cm, corePtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TtkBlinkCursor (main routine) --
|
||||
* Arrange to blink the cursor on and off whenever the
|
||||
* widget has focus.
|
||||
*/
|
||||
void TtkBlinkCursor(WidgetCore *corePtr)
|
||||
{
|
||||
Tk_CreateEventHandler(
|
||||
corePtr->tkwin, CursorEventMask, CursorEventProc, corePtr);
|
||||
}
|
||||
|
||||
/*EOF*/
|
||||
Reference in New Issue
Block a user