DEC Private Modes
DEC Private Modes are terminal control sequences that enable or disable specific terminal behaviors like cursor visibility, mouse tracking, alternate screen buffers, and modern features like synchronized output.
The blessed library provides a clean API for working with these modes:
Query mode support with
get_dec_mode()Enable modes with
dec_modes_enabled()context managerDisable modes with
dec_modes_disabled()context manager
Each mode is identified by a constant from
Terminal.DecPrivateMode.
Our mode catalog is derived from https://wiki.tau.garden/dec-modes/
Overview
DEC Private Modes control a wide variety of terminal features. Some common examples include:
DECTCEM (25) - Cursor visibility
MOUSE_REPORT_CLICK (1000) - Basic mouse click reporting
MOUSE_EXTENDED_SGR (1006) - Extended mouse reporting with pixel coordinates
BRACKETED_PASTE (2004) - Receive clipboard paste as a single event
FOCUS_IN_OUT_EVENTS (1004) - Detect when terminal window gains/loses focus
SYNCHRONIZED_OUTPUT (2026) - Eliminate screen flicker during redraws
The context managers gracefully handle unsupported modes - your code works normally even on terminals that don’t support specific features.
Timeout Behavior
All DEC mode context managers use a default timeout of 1 second when querying
mode support. This timeout is designed to handle “dumb” terminals that don’t
support DEC mode queries and won’t respond.
The timeout delay only occurs on the first call to any mode query method, as subsequent calls use cached results. Unsupported modes are gracefully ignored - your code continues to work even when a terminal doesn’t support a specific feature.
You can verify mode support quickly using get_dec_mode()
(see Querying Mode Support below), which also benefits from caching after
the first query.
Getting Started
Here’s a simple example that temporarily hides the cursor:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5
6print("Watch the cursor disappear, ")
7with term.dec_modes_disabled(term.DecPrivateMode.DECTCEM):
8 print("Cursor is hidden - working...")
9 term.inkey(2)
10
11print()
12print("Cursor is back!")
The cursor automatically reappears when the context exits, even if an exception occurs.
This usually emits the same sequences recorded in the terminfo database of
modern terminals for the term.hide_cursor and term.normal_cursor
attributes and offered by our context manager method,
hidden_cursor().
The difference is that we can also make inquiries into the whether the mode is supported at all.
Querying Mode Support
You can check if a terminal supports a specific mode using
get_dec_mode(). This is useful for adapting your
application to different terminal capabilities:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5
6# Query mouse support
7mode = term.DecPrivateMode(term.DecPrivateMode.MOUSE_REPORT_CLICK)
8response = term.get_dec_mode(mode)
9
10print(f"Checking {mode.name} (mode {mode.value}) {mode.long_description}: ", end="")
11
12if response.supported:
13 status = "enabled" if response.enabled else "disabled"
14 state = "permanently" if response.permanent else "temporarily"
15 print(f"Supported and {status} {state}")
16elif response.failed:
17 print("Terminal does not support DEC mode queries")
18else:
19 print("Mode not supported by this terminal")
The timeout value is unspecified and defaults to 1 second. If a Terminal
fails to respond in this amount of time, the special property failed becomes
True.
The DecModeResponse object provides helper properties:
supported- Mode is recognizedenabled- Mode is currently activedisabled- Mode is currently inactivepermanent- Mode setting cannot be changedfailed- Query failed or timed out
Query results are automatically cached. Use force=True to bypass the cache:
Try the display-modes.py example program to detect and report all supported sequences for a given terminal.
Quick Boolean Detection
For the most commonly used modes, convenience methods return a simple boolean
without needing to inspect the full DecModeResponse:
does_bracketed_paste()– Bracketed Paste (mode 2004)does_synchronized_output()– Synchronized Output (mode 2026)does_grapheme_clustering()– Grapheme Clustering (mode 2027)does_focus_events()– Focus In/Out Events (mode 1004)
term = Terminal()
if term.does_synchronized_output():
print("Synchronized output supported")
if term.does_bracketed_paste():
print("Bracketed paste supported")
These methods accept the same timeout parameter as
get_dec_mode() and benefit from the same caching.
Context Managers
The recommended way to work with modes is through context managers:
dec_modes_enabled()- Temporarily enable one or more modesdec_modes_disabled()- Temporarily disable one or more modes
These context managers:
Query the Terminal’s support for a mode within given timeout
Change the mode if allowed by negotiation
Restore the original state on exit if changed
Handle unsupported modes gracefully
You can pass multiple modes to enable them simultaneously:
with term.dec_modes_enabled(
term.DecPrivateMode.DECTCEM,
term.DecPrivateMode.MOUSE_REPORT_CLICK,
):
# Both modes enabled here
pass
For commonly-used DEC modes, blessed provides convenient context managers on the
Terminal object that make accessing them easier.
These convenience wrappers all contain a default timeout argument of 1.
Given this, for terminals that do not support DEC Mode negotiation, the first
call will cause up to a 1 second delay while awaiting a possible terminal
response to confirm support.
All subsequent calls use a cache of the failed query result and incur no further delays.
Synchronized Output
Synchronized Output (mode 2026) eliminates screen flicker by buffering all output until the mode is exited. This is perfect for animations and full-screen redraws.
Without synchronized output, rapidly clearing and redrawing the screen creates a visible blink effect. With it, updates appear instantly:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5
6fill = "█" * term.height * term.width
7empty = " " * term.height * term.width
8
9print(term.bold_red("Warning! Screen may blink rapidly!"))
10print()
11print("Press return to continue, 'q' to stop test")
12term.inkey()
13
14with term.fullscreen():
15 for step in range(300):
16 with term.synchronized_output():
17 print(term.home + empty, flush=True)
18 print(term.home + fill, flush=True)
19 print(term.home + f'step={step}')
20 if term.inkey(0.01) == 'q':
21 break
22
23print(term.clear + "Test complete!")
On terminals that support this mode, you’ll just see screen of fill characters
with a counter in the top-left corner. On terminals that do not support it,
partial draws of empty spaces will cause the screen to occasionally blink or
flash.
Bracketed Paste
Bracketed Paste (mode 2004) allows your application to receive clipboard paste operations as a single event rather than a stream of individual characters. This makes it easy to distinguish between typed and pasted text:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5
6print("Paste some text (press 'q' to quit)...")
7
8with term.bracketed_paste():
9 with term.cbreak():
10 while True:
11 ks = term.inkey()
12
13 if ks.name == 'BRACKETED_PASTE':
14 print(f"Pasted: {term.reverse(repr(ks.text))}")
15 elif ks == 'q':
16 print("Goodbye!")
17 break
18 elif ks:
19 print(f"Regular key: {ks!r}")
When Keystroke.mode equals
BRACKETED_PASTE, the
mode_values() method returns a
BracketedPasteEvent with a text attribute
containing the pasted content.
Focus Events
Focus tracking (mode 1004) reports when the terminal window gains or loses focus. This is useful for pausing animations or updating status indicators:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5
6print("Switch focus to/from this terminal window, 'q' to stop.")
7
8with term.focus_events():
9 with term.cbreak():
10 while True:
11 inp = term.inkey()
12 if inp.name == 'FOCUS_IN':
13 print("Focus gained")
14 elif inp.name == 'FOCUS_OUT':
15 print("Focus lost")
16 elif inp == 'q':
17 break
When Keystroke.mode equals
FOCUS_IN_OUT_EVENTS, the
mode_values() method returns a
FocusEvent with a gained attribute indicating
whether focus was gained (True) or lost (False).