--- generic/tkIntDecls.h	2020-12-11 09:48:53.000000000 -0800
+++ generic/tkIntDecls.h	2021-01-04 07:00:39.076603545 -0800
@@ -558,6 +558,9 @@
 /* 186 */
 EXTERN int		TkpWillDrawWidget(Tk_Window tkwin);
 #endif /* MACOSX */
+/* 187 */
+EXTERN void		TkpCursorBlinkFromSystem(Tcl_Interp *interp,
+				int *blinkon, int *blinkoff);

 typedef struct TkIntStubs {
     int magic;
@@ -793,6 +796,7 @@
 #ifdef MAC_OSX_TCL /* MACOSX */
     int (*tkpWillDrawWidget) (Tk_Window tkwin); /* 186 */
 #endif /* MACOSX */
+    void (*tkpCursorBlinkFromSystem) (Tcl_Interp *interp, int *blinkon, int *blinkoff); /* 187 */
 } TkIntStubs;

 extern const TkIntStubs *tkIntStubsPtr;
@@ -1173,6 +1177,8 @@
 #define TkpWillDrawWidget \
 	(tkIntStubsPtr->tkpWillDrawWidget) /* 186 */
 #endif /* MACOSX */
+#define TkpCursorBlinkFromSystem \
+	(tkIntStubsPtr->tkpCursorBlinkFromSystem) /* 187 */

 #endif /* defined(USE_TK_STUBS) */

--- generic/tkStubInit.c	2020-12-11 09:48:53.000000000 -0800
+++ generic/tkStubInit.c	2021-01-04 07:00:39.076603545 -0800
@@ -520,6 +520,7 @@
 #ifdef MAC_OSX_TCL /* MACOSX */
     TkpWillDrawWidget, /* 186 */
 #endif /* MACOSX */
+    TkpCursorBlinkFromSystem, /* 187 */
 };

 static const TkIntPlatStubs tkIntPlatStubs = {
--- generic/ttk/ttkBlink.c	2020-12-11 09:48:53.000000000 -0800
+++ generic/ttk/ttkBlink.c	2021-01-04 07:00:39.076603545 -0800
@@ -52,12 +52,24 @@
     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);
+      int   ontime;  /* temporary */
+      int   offtime;
+
+      cm = ckalloc(sizeof(*cm));
+      cm->timer = 0;
+      cm->owner = 0;
+      cm->onTime = DEF_CURSOR_ON_TIME;
+      cm->offTime = DEF_CURSOR_OFF_TIME;
+
+      TkpCursorBlinkFromSystem(interp, &ontime, &offtime);
+      if (ontime != -1) {
+        cm->onTime = ontime;
+      }
+      if (offtime != -1) {
+        cm->offTime = offtime;
+      }
+
+      Tcl_SetAssocData(interp, cm_key, CursorManagerDeleteProc, cm);
     }
     return cm;
 }
@@ -71,15 +83,17 @@
     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;
+    if (cm->offTime != 0) {
+      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);
     }
-    cm->timer = Tcl_CreateTimerHandler(blinkTime, CursorBlinkProc, clientData);
-    TtkRedisplayWidget(cm->owner);
 }

 /* LoseCursor --
--- macosx/tkMacOSXCursor.c	2021-01-04 05:52:23.224915159 -0800
+++ macosx/tkMacOSXCursor.c	2021-01-04 07:01:08.001039537 -0800
@@ -596,6 +596,22 @@
     gTkOwnsCursor = tkOwnsIt;
 }
 
+void
+TkpCursorBlinkFromSystem (
+    Tcl_Interp *interp,
+    int *blinkon,
+    int *blinkoff)
+{
+  NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
+  NSString *nsblinkon = [preferences stringForKey:@"NSTextInsertionPointBlinkPeriodOn"];
+  if (nsblinkon != NULL) {
+    *blinkon = atoi ([nsblinkon UTF8String]);
+  }
+  NSString *nsblinkoff = [preferences stringForKey:@"NSTextInsertionPointBlinkPeriodOff"];
+  if (nsblinkoff != NULL) {
+    *blinkoff = atoi ([nsblinkoff UTF8String]);
+  }
+}
 /*
  * Local Variables:
  * mode: objc
--- unix/tkUnixCursor.c	2020-12-11 09:48:53.000000000 -0800
+++ unix/tkUnixCursor.c	2021-01-04 07:00:39.076603545 -0800
@@ -641,6 +641,36 @@
     XFreeCursor(unixCursorPtr->display, (Cursor) unixCursorPtr->info.cursor);
 }
 
+
+void
+TkpCursorBlinkFromSystem (
+    Tcl_Interp *interp,
+    int *blinkon,
+    int *blinkoff)
+{
+  int     result;
+  Tcl_Obj *listObj;
+  Tcl_Obj *conObj;
+  Tcl_Obj *coffObj;
+
+  result = Tcl_EvalEx (interp, "source $tk_library/ttk/cursorblink.tcl",
+      -1, TCL_EVAL_GLOBAL);
+  if (result == TCL_OK) {
+    result = Tcl_EvalEx (interp, "::ttk::cursorblink::getFromSystem",
+        -1, TCL_EVAL_GLOBAL);
+    if (result == TCL_OK) {
+      listObj = Tcl_GetObjResult (interp);
+      result = Tcl_ListObjIndex (interp, listObj, 0, &conObj);
+      if (result == TCL_OK) {
+        result = Tcl_ListObjIndex (interp, listObj, 1, &coffObj);
+        result = Tcl_GetIntFromObj (interp, conObj, blinkon);
+        result = Tcl_GetIntFromObj (interp, coffObj, blinkoff);
+      }
+    }
+    Tcl_ResetResult (interp);
+  }
+}
+
 /*
  * Local Variables:
  * mode: c
--- win/tkWinCursor.c	2020-12-11 09:48:53.000000000 -0800
+++ win/tkWinCursor.c	2021-01-04 07:00:39.076603545 -0800
@@ -263,6 +263,37 @@
     }
 }
 
+
+void
+TkpCursorBlinkFromSystem (
+    Tcl_Interp *interp,
+    int *blinkon,
+    int *blinkoff)
+{
+    HKEY hKey;
+    LPCWSTR szSubKey = L"Control Panel\\Desktop";
+    LPCWSTR szCursorBlink = L"CursorBlinkRate";
+    DWORD dwSize = 40;
+    WCHAR lBuffer[40];
+    LSTATUS status;
+
+    status =  RegOpenKeyExW (HKEY_CURRENT_USER, szSubKey, 0L, KEY_READ, &hKey);
+    if (status == ERROR_SUCCESS) {
+      memset (lBuffer, '\0', (size_t) (dwSize * sizeof (WCHAR)));
+      status = RegQueryValueExW (hKey, szCursorBlink,
+          NULL, NULL, (LPBYTE) lBuffer, &dwSize);
+      if (status == ERROR_SUCCESS) {
+        if (wcscmp (lBuffer, L"-1") == 0) {
+           *blinkoff = 0;
+        } else {
+           *blinkon = _wtoi (lBuffer);
+           *blinkoff = _wtoi (lBuffer);
+        }
+      }
+      RegCloseKey (hKey);
+    }
+}
+
 /*
  * Local Variables:
  * mode: c
ADDED   library/ttk/cursorblink.tcl
Index: library/ttk/cursorblink.tcl
==================================================================
--- library/ttk/cursorblink.tcl
+++ library/ttk/cursorblink.tcl
@@ -0,0 +1,153 @@
+#!/usr/bin/tclsh
+
+namespace eval ::ttk::cursorblink {
+
+  proc getFromSystem { } {
+
+    set ds $::env(DESKTOP_SESSION)
+
+    # default is unknown
+    set cursoron -1
+    set cursoroff -1
+
+    switch -exact $ds {
+      xfce {
+        set cursortm -1
+        try {
+          set cursorenabled [exec -ignorestderr \
+              xfconf-query -c xsettings -p /Net/CursorBlink \
+              2>/dev/null ]
+          if { $cursorenabled } {
+            set cursortm [exec -ignorestderr \
+                xfconf-query -c xsettings -p /Net/CursorBlinkTime \
+                2>/dev/null ]
+          } else {
+            set cursortm 0
+          }
+        } on error {err res} {
+        }
+        # GTK 3 divides the blink time by 3.
+        # Two parts on-time and one part off-time.
+        if { $cursortm != -1 } {
+          set cursoron [expr {round(double($cursortm)*2.0/3.0)}]
+          set cursoroff [expr {round(double($cursortm)/3.0)}]
+        }
+      }
+      gnome -
+      ubuntu -
+      mate -
+      cinnamon {
+        # gnome also has an inactivity timeout for the cursor, but Tk
+        # does not support that.
+
+        set schema org.gnome.desktop.interface
+        # they all use gsettings, but somehow have the need to create
+        # their own schema for the same settings...
+        switch -exact $ds {
+          mate {
+            set schema org.mate.interface
+          }
+          cinnamon {
+            set schema org.cinnamon.desktop.interface
+          }
+          default {
+          }
+        }
+
+        set cursortm -1
+        try {
+          set cursorenabled [exec -ignorestderr \
+              gsettings get $schema cursor-blink \
+              2>/dev/null ]
+          if { $cursorenabled } {
+            set cursortm [exec -ignorestderr \
+                gsettings get $schema cursor-blink-time \
+                2>/dev/null ]
+          } else {
+            set cursortm 0
+          }
+        } on error {err res} {
+        }
+        # GTK 3 divides the blink time by 3.
+        # Two parts on-time and one part off-time.
+        if { $cursortm != -1 } {
+          set cursoron [expr {round(double($cursortm)*2.0/3.0)}]
+          set cursoroff [expr {round(double($cursortm)/3.0)}]
+        }
+      }
+      plasma -
+      lxqt {
+        set cursortm -1
+
+        set confsearch [list]
+
+        switch -exact $ds {
+          plasma {
+            # in KDE 5 the QT setting no longer works.
+            # it is a manual setting in .config/kdeglobals
+            if { ! [info exists ::env(KDE_SESSION_VERSION)] ||
+                $::env(KDE_SESSION_VERSION) eq "5" } {
+              lappend confsearch \
+                  [file join $::env(HOME) .config kdeglobals] \
+                  CursorBlinkRate
+            }
+            # KDE 4
+            # kde's cursor blink is controlled by qt.
+            # it has the same cursorFlashTime setting as lxqt, but
+            # in a different configuration file.
+            # qt4-qtconfig does not allow a setting of 0.  Presumably
+            # a manual update would be necessary.
+            if { ! [info exists ::env(KDE_SESSION_VERSION)] ||
+                $::env(KDE_SESSION_VERSION) eq "4" } {
+              lappend confsearch \
+                  [file join $::env(HOME) .config Trolltech.conf] \
+                  cursorFlashTime
+            }
+          }
+          lxqt {
+            lappend confsearch \
+                [file join $::env(HOME) .config lxqt lxqt.conf] \
+                cursorFlashTime
+          }
+        }
+
+        foreach {conffn conftag} $confsearch {
+          if { [file exists $conffn] } {
+            set found false
+            try {
+              # may not exist in the configuration file.
+              set cursortm [exec -ignorestderr \
+                egrep ^${conftag} $conffn | \
+                sed s,.*=,, \
+                2>/dev/null ]
+              if { $cursortm ne {} } {
+                set found true
+              }
+            } on error { err res } {
+            }
+            if { $found } {
+              break
+            }
+          }
+        }
+        if { $cursortm != -1 } {
+          # The QT source code seems to split the blink time into two.
+          # The timing is highly suspect based on empirical testing.
+          # Try dividing by 4.
+          set cursoron [expr {$cursortm/4}]
+          set cursoroff $cursoron
+        }
+      }
+      default {
+      }
+    }
+
+    return [list $cursoron $cursoroff]
+  }
+}
+
+# for testing
+if { 0 } {
+  lassign [::ttk::cursorblink::getFromSystem] cursoron cursoroff
+  puts [list $cursoron $cursoroff]
+}

