Skip to content

Commit

Permalink
implement blink/static/text cursor (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
eagleoflqj authored Mar 4, 2024
1 parent 453e865 commit d99f6ba
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 4 deletions.
3 changes: 3 additions & 0 deletions include/candidate_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ class CandidateWindow {
select_callback = callback;
}

void set_cursor_text(const std::string &text) { cursor_text_ = text; }

protected:
std::function<void()> init_callback = []() {};
std::function<void(size_t index)> select_callback = [](size_t) {};
std::string cursor_text_ = "";
};
} // namespace candidate_window
#endif
24 changes: 23 additions & 1 deletion page/customize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { setBlur } from './ux'
import {
setBlur,
setBlink
} from './ux'

type CONFIG_BOOL = 'False' | 'True'

Expand Down Expand Up @@ -36,6 +39,10 @@ type STYLE_JSON = {
PreeditFontFamily: FONT_FAMILY
PreeditFontSize: string
}
Cursor: {
Style: 'Blink' | 'Static' | 'Text'
Text: string
}
BorderWidth: string
BorderRadius: string
HorizontalDividerWidth: string
Expand All @@ -48,6 +55,7 @@ const CANDIDATES = `${PANEL} .candidates`
const LABEL = `${PANEL} .label`
const TEXT = `${PANEL} .text`
const PREEDIT = `${PANEL} .preedit`
const CURSOR_NO_TEXT = `${PANEL} .cursor.no-text`

const PANEL_LIGHT = `${PANEL}.light`
const PANEL_LIGHT_HIGHLIGHT = `${PANEL_LIGHT} .candidate.highlighted`
Expand All @@ -59,6 +67,7 @@ const PREEDIT_LIGHT = `${PANEL_LIGHT} .preedit`
const HEADER_LIGHT_BACKGROUND = `${PANEL_LIGHT} .header`
const CANDIDATE_LIGHT_BACKGROUND = `${PANEL_LIGHT} .candidate`
const PANEL_LIGHT_HORIZONTAL_DIVIDER = `${PANEL_LIGHT} ${HORIZONTAL_DIVIDER}`
const CURSOR_NO_TEXT_LIGHT = `${PANEL_LIGHT} .cursor.no-text`

const PANEL_DARK = `${PANEL}.dark`
const PANEL_DARK_HIGHLIGHT = `${PANEL_DARK} .candidate.highlighted`
Expand All @@ -70,6 +79,7 @@ const PREEDIT_DARK = `${PANEL_DARK} .preedit`
const HEADER_DARK_BACKGROUND = `${PANEL_DARK} .header`
const CANDIDATE_DARK_BACKGROUND = `${PANEL_DARK} .candidate`
const PANEL_DARK_HORIZONTAL_DIVIDER = `${PANEL_DARK} ${HORIZONTAL_DIVIDER}`
const CURSOR_NO_TEXT_DARK = `${PANEL_DARK} .cursor.no-text`

function px (n: string) {
return `${n}px`
Expand All @@ -91,6 +101,7 @@ export function setStyle (style: string) {
rules[TEXT] = {}
rules[LABEL] = {}
rules[PREEDIT] = {}
rules[CURSOR_NO_TEXT] = {}

if (j.LightMode.OverrideDefault === 'True') {
rules[PANEL_LIGHT_HIGHLIGHT] = {
Expand Down Expand Up @@ -118,6 +129,9 @@ export function setStyle (style: string) {
rules[PREEDIT_LIGHT] = {
color: j.LightMode.PreeditColor
}
rules[CURSOR_NO_TEXT_LIGHT] = {
'background-color': j.LightMode.PreeditColor
}
rules[PANEL_LIGHT] = {
'border-color': j.LightMode.BorderColor
}
Expand All @@ -136,6 +150,7 @@ export function setStyle (style: string) {
rules[TEXT_DARK] = rules[TEXT_LIGHT]
rules[LABEL_DARK] = rules[LABEL_LIGHT]
rules[PREEDIT_DARK] = rules[PREEDIT_LIGHT]
rules[CURSOR_NO_TEXT_DARK] = rules[CURSOR_NO_TEXT_LIGHT]
rules[PANEL_DARK] = rules[PANEL_LIGHT]
rules[PANEL_DARK_HORIZONTAL_DIVIDER] = rules[PANEL_LIGHT_HORIZONTAL_DIVIDER]
} else {
Expand Down Expand Up @@ -163,6 +178,9 @@ export function setStyle (style: string) {
rules[PREEDIT_DARK] = {
color: j.DarkMode.PreeditColor
}
rules[CURSOR_NO_TEXT_DARK] = {
'background-color': j.DarkMode.PreeditColor
}
rules[PANEL_DARK] = {
'border-color': j.DarkMode.BorderColor
}
Expand Down Expand Up @@ -199,6 +217,10 @@ export function setStyle (style: string) {

setFontFamily(rules[PREEDIT], j.Font.PreeditFontFamily)
rules[PREEDIT]['font-size'] = px(j.Font.PreeditFontSize)
// Cursor height should be the same with preedit
rules[CURSOR_NO_TEXT].height = px(j.Font.PreeditFontSize)

setBlink(j.Cursor.Style === 'Blink')

rules[PANEL]['border-width'] = px(j.BorderWidth)
rules[PANEL]['border-radius'] = px(j.BorderRadius)
Expand Down
1 change: 1 addition & 0 deletions page/generic.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ body {
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1em; /* align preedit and text cursor */

&.hidden {
display: none; /* needed because the above display has higher precedence than .hidden's */
Expand Down
15 changes: 15 additions & 0 deletions page/macos.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ $dark-graphite: rgb(105 105 105);
transform: translate(25px, 25px);
}

.cursor.no-text {
width: 1px;
height: 16px;
margin-left: 1px;
margin-right: 1px;
}

.candidate, .preedit, .aux-up, .aux-down {
min-height: 24px; /* compromise to 🀄's height */
min-width: 16px;
Expand All @@ -61,6 +68,10 @@ $dark-graphite: rgb(105 105 105);
border-color: $panel-border-color-light;
}

.cursor.no-text {
background-color: $text-color-light;
}

/* stylelint-disable-next-line no-descending-specificity */
.candidate, .header {
color: $text-color-light;
Expand Down Expand Up @@ -113,6 +124,10 @@ $dark-graphite: rgb(105 105 105);
border-color: $panel-border-color-dark;
}

.cursor.no-text {
background-color: $text-color-dark;
}

/* stylelint-disable-next-line no-descending-specificity */
.candidate, .header {
color: $text-color-dark;
Expand Down
24 changes: 24 additions & 0 deletions page/ux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,27 @@ function redrawBlur () {
blurSwitch = !blurSwitch
}
setInterval(redrawBlur, 40)

export function showCursor (show: boolean) {
const cursor = document.querySelector('.cursor')
if (cursor) {
(<HTMLElement>cursor).style.opacity = show ? '1' : '0'
}
}

let blinkEnabled = true
export function setBlink (enabled: boolean) {
blinkEnabled = enabled
if (!enabled) {
showCursor(true)
}
}

let blinkSwitch = false
setInterval(() => {
if (!blinkEnabled) {
return
}
showCursor(blinkSwitch)
blinkSwitch = !blinkSwitch
}, 500)
28 changes: 25 additions & 3 deletions src/webview_candidate_window.mm
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,32 @@ static void build_html_close_tags(std::stringstream &ss, int flags) {
ss << "</i>";
}

static std::string formatted_to_html(const formatted<std::string> &f) {
static std::string formatted_to_html(const formatted<std::string> &f,
const std::string &cursor_text = "",
int cursor = -1) {
std::stringstream ss;
int cursor_pos = 0;
for (const auto &slice : f) {
build_html_open_tags(ss, slice.second);
ss << escape_html(slice.first);
auto size =
(int)slice.first
.size(); // ensure signed comparison since cursor may be -1
if (cursor_pos <= cursor && cursor <= cursor_pos + size) {
ss << escape_html(slice.first.substr(0, cursor - cursor_pos));
if (cursor_text.empty()) {
ss << "<div class=\"cursor no-text\">";
} else {
ss << "<div class=\"cursor\">";
ss << escape_html(cursor_text);
}
ss << "</div>";
ss << escape_html(slice.first.substr(cursor - cursor_pos));
// Do not draw cursor again when it's at the end of current slice
cursor = -1;
} else {
ss << escape_html(slice.first);
cursor_pos += size;
}
build_html_close_tags(ss, slice.second);
}
return ss.str();
Expand All @@ -206,7 +227,8 @@ static void build_html_close_tags(std::stringstream &ss, int flags) {
const formatted<std::string> &preedit, int preedit_cursor,
const formatted<std::string> &auxUp,
const formatted<std::string> &auxDown) {
invoke_js("updateInputPanel", formatted_to_html(preedit),
invoke_js("updateInputPanel",
formatted_to_html(preedit, cursor_text_, preedit_cursor),
formatted_to_html(auxUp), formatted_to_html(auxDown));
}

Expand Down

0 comments on commit d99f6ba

Please sign in to comment.