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
diff --git a/util/src/TclTk/tk8.6.12/generic/ttk/ttkBlink.c b/util/src/TclTk/tk8.6.12/generic/ttk/ttkBlink.c
new file mode 100644 (file)
index 0000000..a7d4a9a
--- /dev/null
@@ -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 "tkInt.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, 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*/