OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / generic / ttk / ttkBlink.c
1 /*
2  * Copyright 2004, Joe English.
3  *
4  * Usage:
5  *      TtkBlinkCursor(corePtr), usually called in a widget's Init hook,
6  *      arranges to periodically toggle the corePtr->flags CURSOR_ON bit
7  *      on and off (and schedule a redisplay) whenever the widget has focus.
8  *
9  *      Note: Widgets may have additional logic to decide whether
10  *      to display the cursor or not (e.g., readonly or disabled states);
11  *      TtkBlinkCursor() does not account for this.
12  *
13  * TODO:
14  *      Add script-level access to configure application-wide blink rate.
15  */
16
17 #include "tkInt.h"
18 #include "ttkTheme.h"
19 #include "ttkWidget.h"
20
21 #define DEF_CURSOR_ON_TIME      600             /* milliseconds */
22 #define DEF_CURSOR_OFF_TIME     300             /* milliseconds */
23
24 /* Interp-specific data for tracking cursors:
25  */
26 typedef struct
27 {
28     WidgetCore          *owner;         /* Widget that currently has cursor */
29     Tcl_TimerToken      timer;          /* Blink timer */
30     int                 onTime;         /* #milliseconds to blink cursor on */
31     int                 offTime;        /* #milliseconds to blink cursor off */
32 } CursorManager;
33
34 /* CursorManagerDeleteProc --
35  *      InterpDeleteProc for cursor manager.
36  */
37 static void CursorManagerDeleteProc(ClientData clientData, Tcl_Interp *interp)
38 {
39     CursorManager *cm = (CursorManager*)clientData;
40     if (cm->timer) {
41         Tcl_DeleteTimerHandler(cm->timer);
42     }
43     ckfree(clientData);
44 }
45
46 /* GetCursorManager --
47  *      Look up and create if necessary the interp's cursor manager.
48  */
49 static CursorManager *GetCursorManager(Tcl_Interp *interp)
50 {
51     static const char *cm_key = "ttk::CursorManager";
52     CursorManager *cm = Tcl_GetAssocData(interp, cm_key,0);
53
54     if (!cm) {
55         cm = ckalloc(sizeof(*cm));
56         cm->timer = 0;
57         cm->owner = 0;
58         cm->onTime = DEF_CURSOR_ON_TIME;
59         cm->offTime = DEF_CURSOR_OFF_TIME;
60         Tcl_SetAssocData(interp, cm_key, CursorManagerDeleteProc, cm);
61     }
62     return cm;
63 }
64
65 /* CursorBlinkProc --
66  *      Timer handler to blink the insert cursor on and off.
67  */
68 static void
69 CursorBlinkProc(ClientData clientData)
70 {
71     CursorManager *cm = (CursorManager*)clientData;
72     int blinkTime;
73
74     if (cm->owner->flags & CURSOR_ON) {
75         cm->owner->flags &= ~CURSOR_ON;
76         blinkTime = cm->offTime;
77     } else {
78         cm->owner->flags |= CURSOR_ON;
79         blinkTime = cm->onTime;
80     }
81     cm->timer = Tcl_CreateTimerHandler(blinkTime, CursorBlinkProc, clientData);
82     TtkRedisplayWidget(cm->owner);
83 }
84
85 /* LoseCursor --
86  *      Turn cursor off, disable blink timer.
87  */
88 static void LoseCursor(CursorManager *cm, WidgetCore *corePtr)
89 {
90     if (corePtr->flags & CURSOR_ON) {
91         corePtr->flags &= ~CURSOR_ON;
92         TtkRedisplayWidget(corePtr);
93     }
94     if (cm->owner == corePtr) {
95         cm->owner = NULL;
96     }
97     if (cm->timer) {
98         Tcl_DeleteTimerHandler(cm->timer);
99         cm->timer = 0;
100     }
101 }
102
103 /* ClaimCursor --
104  *      Claim ownership of the insert cursor and blink on.
105  */
106 static void ClaimCursor(CursorManager *cm, WidgetCore *corePtr)
107 {
108     if (cm->owner == corePtr)
109         return;
110     if (cm->owner)
111         LoseCursor(cm, cm->owner);
112
113     corePtr->flags |= CURSOR_ON;
114     TtkRedisplayWidget(corePtr);
115
116     cm->owner = corePtr;
117     cm->timer = Tcl_CreateTimerHandler(cm->onTime, CursorBlinkProc, cm);
118 }
119
120 /*
121  * CursorEventProc --
122  *      Event handler for FocusIn and FocusOut events;
123  *      claim/lose ownership of the insert cursor when the widget
124  *      acquires/loses keyboard focus.
125  */
126
127 #define CursorEventMask (FocusChangeMask|StructureNotifyMask)
128 #define RealFocusEvent(d) \
129     (d == NotifyInferior || d == NotifyAncestor || d == NotifyNonlinear)
130
131 static void
132 CursorEventProc(ClientData clientData, XEvent *eventPtr)
133 {
134     WidgetCore *corePtr = (WidgetCore *)clientData;
135     CursorManager *cm = GetCursorManager(corePtr->interp);
136
137     switch (eventPtr->type) {
138         case DestroyNotify:
139             if (cm->owner == corePtr)
140                 LoseCursor(cm, corePtr);
141             Tk_DeleteEventHandler(
142                 corePtr->tkwin, CursorEventMask, CursorEventProc, clientData);
143             break;
144         case FocusIn:
145             if (RealFocusEvent(eventPtr->xfocus.detail))
146                 ClaimCursor(cm, corePtr);
147             break;
148         case FocusOut:
149             if (RealFocusEvent(eventPtr->xfocus.detail))
150                 LoseCursor(cm, corePtr);
151             break;
152     }
153 }
154
155 /*
156  * TtkBlinkCursor (main routine) --
157  *      Arrange to blink the cursor on and off whenever the
158  *      widget has focus.
159  */
160 void TtkBlinkCursor(WidgetCore *corePtr)
161 {
162     Tk_CreateEventHandler(
163         corePtr->tkwin, CursorEventMask, CursorEventProc, corePtr);
164 }
165
166 /*EOF*/