@@ -57,6 +57,7 @@ WeaselPanel::WeaselPanel(weasel::UI& ui)
5757 m_style(ui.style()),
5858 m_ostyle(ui.ostyle()),
5959 m_candidateCount(0 ),
60+ m_lastCandidateCount(0 ),
6061 m_current_zhung_icon(),
6162 m_inputPos(CRect()),
6263 m_sticky(false ),
@@ -133,6 +134,12 @@ void WeaselPanel::Refresh() {
133134 bool should_show_icon =
134135 (m_status.ascii_mode || !m_status.composing || !m_ctx.aux .empty ());
135136 m_candidateCount = (BYTE)m_ctx.cinfo .candies .size ();
137+ // When the candidate window changes from having content to having no content,
138+ // reset the sticky state
139+ if (m_lastCandidateCount > 0 && m_candidateCount == 0 ) {
140+ m_sticky = false ;
141+ }
142+ m_lastCandidateCount = m_candidateCount;
136143 // check if to hide candidates window
137144 // show tips status, two kind of situation: 1) only aux strings, don't care
138145 // icon status; 2)only icon(ascii mode switching)
@@ -1121,6 +1128,23 @@ void WeaselPanel::MoveTo(RECT const& rc) {
11211128 if (!m_layout)
11221129 return ; // avoid handling nullptr in _RepositionWindow
11231130 m_redraw_by_monitor_change = false ;
1131+ // The conditions for resetting the sticky state:
1132+ // 1. When the input session ends (ctx.empty() is true)
1133+ // 2. When the input position changes significantly (the position change
1134+ // exceeds the threshold)
1135+ // 3. When the content of the candidate window is empty
1136+ bool should_reset_sticky =
1137+ (m_ctx.empty () || (abs (rc.left - m_inputPos.left ) > 50 ) ||
1138+ (abs (rc.bottom - m_inputPos.bottom ) > 50 ));
1139+ if (should_reset_sticky && m_sticky) {
1140+ m_sticky = false ;
1141+ // Force reposition the window
1142+ m_inputPos = rc;
1143+ m_inputPos.OffsetRect (0 , 6 );
1144+ _RepositionWindow (true );
1145+ RedrawWindow ();
1146+ return ;
1147+ }
11241148 // if ascii_tip_follow_cursor set, move tip icon to mouse cursor
11251149 if (m_style.ascii_tip_follow_cursor && m_ctx.empty () &&
11261150 (!m_status.composing ) && m_layout->ShouldDisplayStatusIcon ()) {
0 commit comments