Skip to content

Commit

Permalink
hover behavior: none (macOS), move (Linux), add (Windows) (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
eagleoflqj authored Mar 11, 2024
1 parent 986896b commit 863221f
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 16 deletions.
53 changes: 46 additions & 7 deletions page/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
auxUp,
auxDown
} from './selector'
import { resize } from './ux'
import {
getHoverBehavior,
resize
} from './ux'
import {
setTheme,
setAccentColor
Expand All @@ -23,14 +26,40 @@ function setLayout (layout : 0 | 1) {
}
}

function moveHighlight (from: Element | null, to: Element | null) {
from?.classList.remove('highlighted')
to?.classList.add('highlighted')
const fromMark = from?.querySelector('.mark')
const toMark = to?.querySelector('.mark')
if (fromMark && !toMark) {
to?.querySelector('.candidate-inner')?.prepend(fromMark)
}
}

function clearAdditionalHighlight () {
candidates.querySelector('.highlighted:not(.highlighted-original)')?.classList.remove('highlighted')
}

function setCandidates (cands: string[], labels: string[], highlighted: number, markText: string) {
candidates.innerHTML = ''
for (let i = 0; i < cands.length; ++i) {
const candidate = document.createElement('div')
candidate.classList.add('candidate')
if (i === highlighted) {
candidate.classList.add('highlighted')
candidate.classList.add('highlighted', 'highlighted-original')
}

candidate.addEventListener('mouseenter', () => {
const hoverBehavior = getHoverBehavior()
if (hoverBehavior === 'Move') {
const lastHighlighted = candidates.querySelector('.highlighted')
moveHighlight(lastHighlighted, candidate)
} else if (hoverBehavior === 'Add') {
clearAdditionalHighlight()
candidate.classList.add('highlighted')
}
})

const label = document.createElement('div')
label.classList.add('label')
label.innerHTML = labels[i]
Expand All @@ -48,12 +77,11 @@ function setCandidates (cands: string[], labels: string[], highlighted: number,
} else {
mark.innerHTML = markText
}
candidateInner.appendChild(mark)
candidateInner.append(mark)
}
candidateInner.appendChild(label)
candidateInner.appendChild(text)
candidate.appendChild(candidateInner)
candidates.appendChild(candidate)
candidateInner.append(label, text)
candidate.append(candidateInner)
candidates.append(candidate)
}
}

Expand All @@ -72,6 +100,17 @@ function updateInputPanel (preeditHTML: string, auxUpHTML: string, auxDownHTML:
updateElement(auxDown, auxDownHTML)
}

candidates.addEventListener('mouseleave', () => {
const hoverBehavior = getHoverBehavior()
if (hoverBehavior === 'Move') {
const lastHighlighted = candidates.querySelector('.highlighted')
const originalHighlighted = candidates.querySelector('.highlighted-original')
moveHighlight(lastHighlighted, originalHighlighted)
} else if (hoverBehavior === 'Add') {
clearAdditionalHighlight()
}
})

setTheme(0)

// JavaScript APIs that webview_candidate_window.mm calls
Expand Down
14 changes: 10 additions & 4 deletions page/customize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
HOVER_BEHAVIOR,
setHoverBehavior,
setBlur,
setBlink
} from './ux'
Expand Down Expand Up @@ -43,8 +45,9 @@ type STYLE_JSON = {
Cursor: {
Style: 'Blink' | 'Static' | 'Text'
}
HighlightMark: {
Style: 'None' | 'Bar' | 'Text'
Highlight: {
MarkStyle: 'None' | 'Bar' | 'Text'
HoverBehavior: HOVER_BEHAVIOR
}
Size: {
BorderWidth: string
Expand All @@ -70,6 +73,7 @@ const PREEDIT = `${PANEL} .preedit`
const CURSOR_NO_TEXT = `${PANEL} .cursor.no-text`
const CANDIDATE_INNER = `${PANEL} .candidate-inner`
const HIGHLIGHT_MARK = `${PANEL} .highlighted .mark`
const HIGHLIGHT_ORIGINAL_MARK = `${PANEL} .highlighted-original .mark`

const PANEL_LIGHT = `${PANEL}.light`
const PANEL_LIGHT_HIGHLIGHT = `${PANEL_LIGHT} .candidate.highlighted .candidate-inner`
Expand Down Expand Up @@ -112,14 +116,15 @@ export function setStyle (style: string) {
const j = JSON.parse(style) as STYLE_JSON
const rules: {[key: string]: {[key: string]: string}} = {}
const hasBackgroundImage = j.Background.ImageUrl.trim() !== ''
const markKey = j.HighlightMark.Style === 'Text' ? 'color' : 'background-color'
const markKey = j.Highlight.MarkStyle === 'Text' ? 'color' : 'background-color'
rules[PANEL] = {}
rules[CANDIDATES] = {}
rules[TEXT] = {}
rules[LABEL] = {}
rules[PREEDIT] = {}
rules[CURSOR_NO_TEXT] = {}
rules[HIGHLIGHT_MARK] = {}
rules[HIGHLIGHT_ORIGINAL_MARK] = {}
rules[CANDIDATE_INNER] = {}

if (j.LightMode.OverrideDefault === 'True') {
Expand Down Expand Up @@ -248,7 +253,8 @@ export function setStyle (style: string) {

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

rules[HIGHLIGHT_MARK].opacity = j.HighlightMark.Style === 'None' ? '0' : '1'
rules[j.Highlight.HoverBehavior === 'Add' ? HIGHLIGHT_ORIGINAL_MARK : HIGHLIGHT_MARK].opacity = j.Highlight.MarkStyle === 'None' ? '0' : '1'
setHoverBehavior(j.Highlight.HoverBehavior)

rules[PANEL]['border-width'] = px(j.Size.BorderWidth)
rules[PANEL]['border-radius'] = px(j.Size.BorderRadius)
Expand Down
9 changes: 9 additions & 0 deletions page/ux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,12 @@ setInterval(() => {
showCursor(blinkSwitch)
blinkSwitch = !blinkSwitch
}, 500)

export type HOVER_BEHAVIOR = 'None' | 'Move' | 'Add'
let hoverBehavior: HOVER_BEHAVIOR = 'None'
export function setHoverBehavior (behavior: HOVER_BEHAVIOR) {
hoverBehavior = behavior
}
export function getHoverBehavior () {
return hoverBehavior
}
21 changes: 17 additions & 4 deletions src/webview_candidate_window.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,26 @@ - (void)accentColorChanged:(NSNotification *)notification {

@end

@interface HoverableWindow : NSWindow

@end

@implementation HoverableWindow

- (BOOL)isKeyWindow {
return YES;
}

@end

namespace candidate_window {

WebviewCandidateWindow::WebviewCandidateWindow()
: w_(1, [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 300)
styleMask:NSWindowStyleMaskBorderless
backing:NSBackingStoreBuffered
defer:NO]),
: w_(1, [[HoverableWindow alloc]
initWithContentRect:NSMakeRect(0, 0, 400, 300)
styleMask:NSWindowStyleMaskBorderless
backing:NSBackingStoreBuffered
defer:NO]),
listener_([[NotificationListener alloc] init]) {
[static_cast<NSWindow *>(w_.window()) setLevel:NSPopUpMenuWindowLevel];
set_transparent_background();
Expand Down
2 changes: 1 addition & 1 deletion tests/test-generic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test('HTML structure', async ({ page }) => {
</div>
<div class="aux-down hidden"></div>
<div class="candidates">
<div class="candidate highlighted">
<div class="candidate highlighted highlighted-original">
<div class="candidate-inner">
<div class="mark no-text"></div>
<div class="label">1</div>
Expand Down

0 comments on commit 863221f

Please sign in to comment.