aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xA/xA.go148
-rw-r--r--xW/xW.cpp175
2 files changed, 182 insertions, 141 deletions
diff --git a/xA/xA.go b/xA/xA.go
index 2cf2796..17a0400 100644
--- a/xA/xA.go
+++ b/xA/xA.go
@@ -363,16 +363,18 @@ func bufferByName(name string) *buffer {
return nil
}
-func bufferActivate(name string) {
- relaySend(RelayCommandData{
- Variant: &RelayCommandDataBufferActivate{BufferName: name},
- }, nil)
+func bufferAtBottom() bool {
+ return wRichScroll.Offset.Y >=
+ wRichScroll.Content.Size().Height-wRichScroll.Size().Height
}
-func bufferToggleUnimportant(name string) {
- relaySend(RelayCommandData{
- Variant: &RelayCommandDataBufferToggleUnimportant{BufferName: name},
- }, nil)
+func bufferScrollToBottom() {
+ // XXX: Doing it once is not reliable, something's amiss.
+ // (In particular, nothing happens when we switch from an empty buffer
+ // to a buffer than needs scrolling.)
+ wRichScroll.ScrollToBottom()
+ wRichScroll.ScrollToBottom()
+ refreshStatus()
}
func bufferPushLine(b *buffer, line bufferLine) {
@@ -386,68 +388,20 @@ func bufferPushLine(b *buffer, line bufferLine) {
}
}
-// --- Current buffer ----------------------------------------------------------
-
-func bufferToggleLogFinish(err string, response *RelayResponseDataBufferLog) {
- if response == nil {
- showErrorMessage(err)
- return
- }
-
- wLog.SetText(string(response.Log))
- wLog.Show()
- wRichScroll.Hide()
-}
-
-func bufferToggleLog() {
- if wLog.Visible() {
- wRichScroll.Show()
- wLog.Hide()
- wLog.SetText("")
- return
- }
-
- name := bufferCurrent
- relaySend(RelayCommandData{Variant: &RelayCommandDataBufferLog{
- BufferName: name,
- }}, func(err string, response *RelayResponseData) {
- if bufferCurrent == name {
- bufferToggleLogFinish(
- err, response.Variant.(*RelayResponseDataBufferLog))
- }
- })
-}
-
-func bufferAtBottom() bool {
- return wRichScroll.Offset.Y >=
- wRichScroll.Content.Size().Height-wRichScroll.Size().Height
-}
-
-func bufferScrollToBottom() {
- // XXX: Doing it once is not reliable, something's amiss.
- // (In particular, nothing happens when we switch from an empty buffer
- // to a buffer than needs scrolling.)
- wRichScroll.ScrollToBottom()
- wRichScroll.ScrollToBottom()
- refreshStatus()
-}
-
// --- UI state refresh --------------------------------------------------------
func refreshIcon() {
- highlighted := false
+ resource := resourceIconNormal
for _, b := range buffers {
if b.highlighted {
- highlighted = true
+ resource = resourceIconHighlighted
break
}
}
- if highlighted {
- wWindow.SetIcon(resourceIconHighlighted)
- } else {
- wWindow.SetIcon(resourceIconNormal)
- }
+ // Prevent deadlocks (though it might have a race condition).
+ // https://github.com/fyne-io/fyne/issues/5266
+ go func() { wWindow.SetIcon(resource) }()
}
func refreshTopic(topic []bufferLineItem) {
@@ -515,6 +469,63 @@ func refreshStatus() {
wStatus.SetText(status)
}
+func recheckHighlighted() {
+ // Corresponds to the logic toggling the bool on.
+ if b := bufferByName(bufferCurrent); b != nil &&
+ b.highlighted && bufferAtBottom() &&
+ inForeground && !wLog.Visible() {
+ b.highlighted = false
+ refreshIcon()
+ refreshBufferList()
+ }
+}
+
+// --- Buffer actions ----------------------------------------------------------
+
+func bufferActivate(name string) {
+ relaySend(RelayCommandData{
+ Variant: &RelayCommandDataBufferActivate{BufferName: name},
+ }, nil)
+}
+
+func bufferToggleUnimportant(name string) {
+ relaySend(RelayCommandData{
+ Variant: &RelayCommandDataBufferToggleUnimportant{BufferName: name},
+ }, nil)
+}
+
+func bufferToggleLogFinish(err string, response *RelayResponseDataBufferLog) {
+ if response == nil {
+ showErrorMessage(err)
+ return
+ }
+
+ wLog.SetText(string(response.Log))
+ wLog.Show()
+ wRichScroll.Hide()
+}
+
+func bufferToggleLog() {
+ if wLog.Visible() {
+ wRichScroll.Show()
+ wLog.Hide()
+ wLog.SetText("")
+
+ recheckHighlighted()
+ return
+ }
+
+ name := bufferCurrent
+ relaySend(RelayCommandData{Variant: &RelayCommandDataBufferLog{
+ BufferName: name,
+ }}, func(err string, response *RelayResponseData) {
+ if bufferCurrent == name {
+ bufferToggleLogFinish(
+ err, response.Variant.(*RelayResponseDataBufferLog))
+ }
+ })
+}
+
// --- RichText formatting -----------------------------------------------------
func defaultBufferLineItem() bufferLineItem { return bufferLineItem{} }
@@ -756,6 +767,7 @@ func refreshBuffer(b *buffer) {
bufferPrintAndWatchTrailingDateChanges()
wRichText.Refresh()
bufferScrollToBottom()
+ recheckHighlighted()
}
// --- Event processing --------------------------------------------------------
@@ -1374,6 +1386,9 @@ func (l *customLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) {
}
if toBottom {
bufferScrollToBottom()
+ } else {
+ recheckHighlighted()
+ refreshStatus()
}
}
@@ -1497,11 +1512,7 @@ func main() {
a.Lifecycle().SetOnEnteredForeground(func() {
// TODO(p): Does this need locking?
inForeground = true
- if b := bufferByName(bufferCurrent); b != nil {
- b.highlighted = false
- refreshIcon()
- refreshBufferList()
- }
+ recheckHighlighted()
})
a.Lifecycle().SetOnExitedForeground(func() {
inForeground = false
@@ -1542,7 +1553,10 @@ func main() {
wRichText = widget.NewRichText()
wRichText.Wrapping = fyne.TextWrapWord
wRichScroll = container.NewVScroll(wRichText)
- wRichScroll.OnScrolled = func(position fyne.Position) { refreshStatus() }
+ wRichScroll.OnScrolled = func(position fyne.Position) {
+ recheckHighlighted()
+ refreshStatus()
+ }
wLog = newLogEntry()
wLog.Wrapping = fyne.TextWrapWord
wLog.Hide()
diff --git a/xW/xW.cpp b/xW/xW.cpp
index 20ae32e..7fd8950 100644
--- a/xW/xW.cpp
+++ b/xW/xW.cpp
@@ -255,73 +255,6 @@ buffer_by_name(const std::wstring &name)
return nullptr;
}
-static void
-buffer_activate(const std::wstring &name)
-{
- auto activate = new Relay::CommandData_BufferActivate();
- activate->buffer_name = name;
- relay_send(activate);
-}
-
-static void
-buffer_toggle_unimportant(const std::wstring &name)
-{
- auto toggle = new Relay::CommandData_BufferToggleUnimportant();
- toggle->buffer_name = name;
- relay_send(toggle);
-}
-
-// --- Current buffer ----------------------------------------------------------
-
-static void
-buffer_toggle_log(
- const std::wstring &error, const Relay::ResponseData_BufferLog *response)
-{
- if (!response) {
- show_error_message(error.c_str());
- return;
- }
-
- std::wstring log;
- if (!LibertyXDR::utf8_to_wstring(
- response->log.data(), response->log.size(), log)) {
- show_error_message(L"Invalid encoding.");
- return;
- }
-
- std::wstring filtered;
- for (auto wch : log) {
- if (wch == L'\n')
- filtered += L"\r\n";
- else
- filtered += wch;
- }
-
- SetWindowText(g.hwndBufferLog, filtered.c_str());
- ShowWindow(g.hwndBuffer, SW_HIDE);
- ShowWindow(g.hwndBufferLog, SW_SHOW);
-}
-
-static void
-buffer_toggle_log()
-{
- if (IsWindowVisible(g.hwndBufferLog)) {
- ShowWindow(g.hwndBufferLog, SW_HIDE);
- ShowWindow(g.hwndBuffer, SW_SHOW);
- SetWindowText(g.hwndBufferLog, L"");
- return;
- }
-
- auto log = new Relay::CommandData_BufferLog();
- log->buffer_name = g.buffer_current;
- relay_send(log, [name = g.buffer_current](auto error, auto response) {
- if (g.buffer_current != name)
- return;
- buffer_toggle_log(error,
- dynamic_cast<const Relay::ResponseData_BufferLog *>(response));
- });
-}
-
static bool
buffer_at_bottom()
{
@@ -354,6 +287,7 @@ refresh_icon()
if (b.highlighted)
icon = g.hiconHighlighted;
+ // XXX: This may not change the taskbar icon.
SendMessage(g.hwndMain, WM_SETICON, ICON_SMALL, (LPARAM) icon);
SendMessage(g.hwndMain, WM_SETICON, ICON_BIG, (LPARAM) icon);
}
@@ -430,6 +364,88 @@ refresh_status()
SetWindowText(g.hwndStatus, status.c_str());
}
+static void
+recheck_highlighted()
+{
+ // Corresponds to the logic toggling the bool on.
+ auto b = buffer_by_name(g.buffer_current);
+ if (b && b->highlighted && buffer_at_bottom() &&
+ !IsIconic(g.hwndMain) && !IsWindowVisible(g.hwndBufferLog)) {
+ b->highlighted = false;
+ refresh_icon();
+ refresh_buffer_list();
+ }
+}
+
+// --- Buffer actions ----------------------------------------------------------
+
+static void
+buffer_activate(const std::wstring &name)
+{
+ auto activate = new Relay::CommandData_BufferActivate();
+ activate->buffer_name = name;
+ relay_send(activate);
+}
+
+static void
+buffer_toggle_unimportant(const std::wstring &name)
+{
+ auto toggle = new Relay::CommandData_BufferToggleUnimportant();
+ toggle->buffer_name = name;
+ relay_send(toggle);
+}
+
+static void
+buffer_toggle_log(
+ const std::wstring &error, const Relay::ResponseData_BufferLog *response)
+{
+ if (!response) {
+ show_error_message(error.c_str());
+ return;
+ }
+
+ std::wstring log;
+ if (!LibertyXDR::utf8_to_wstring(
+ response->log.data(), response->log.size(), log)) {
+ show_error_message(L"Invalid encoding.");
+ return;
+ }
+
+ std::wstring filtered;
+ for (auto wch : log) {
+ if (wch == L'\n')
+ filtered += L"\r\n";
+ else
+ filtered += wch;
+ }
+
+ SetWindowText(g.hwndBufferLog, filtered.c_str());
+ ShowWindow(g.hwndBuffer, SW_HIDE);
+ ShowWindow(g.hwndBufferLog, SW_SHOW);
+}
+
+static void
+buffer_toggle_log()
+{
+ if (IsWindowVisible(g.hwndBufferLog)) {
+ ShowWindow(g.hwndBufferLog, SW_HIDE);
+ ShowWindow(g.hwndBuffer, SW_SHOW);
+ SetWindowText(g.hwndBufferLog, L"");
+
+ recheck_highlighted();
+ return;
+ }
+
+ auto log = new Relay::CommandData_BufferLog();
+ log->buffer_name = g.buffer_current;
+ relay_send(log, [name = g.buffer_current](auto error, auto response) {
+ if (g.buffer_current != name)
+ return;
+ buffer_toggle_log(error,
+ dynamic_cast<const Relay::ResponseData_BufferLog *>(response));
+ });
+}
+
// --- Rich Edit formatting ----------------------------------------------------
static COLORREF
@@ -728,6 +744,7 @@ refresh_buffer(const Buffer &b)
buffer_print_and_watch_trailing_date_changes();
buffer_scroll_to_bottom();
+ // We will get a scroll event, so no need to recheck_highlighted() here.
SendMessage(g.hwndBuffer, WM_SETREDRAW, (WPARAM) TRUE, 0);
InvalidateRect(g.hwndBuffer, NULL, TRUE);
@@ -749,8 +766,9 @@ relay_process_buffer_line(Buffer &b, Relay::EventData_BufferLine &m)
// Retained mode is complicated.
bool display = (!m.is_unimportant || !bc->hide_unimportant) &&
(b.buffer_name == g.buffer_current || m.leak_to_active);
+ // XXX: It would be great if it didn't autoscroll when focused.
bool to_bottom = display &&
- buffer_at_bottom();
+ (buffer_at_bottom() || GetFocus() == g.hwndBuffer);
bool visible = display &&
to_bottom &&
!IsIconic(g.hwndMain) &&
@@ -1465,6 +1483,7 @@ richedit_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
{
// Dragging the scrollbar doesn't result in EN_VSCROLL.
LRESULT lResult = DefSubclassProc(hWnd, uMsg, wParam, lParam);
+ recheck_highlighted();
refresh_status();
return lResult;
}
@@ -1522,8 +1541,12 @@ process_resize(UINT w, UINT h)
MoveWindow(g.hwndBufferList, 3, top, 150, h - top - bottom, FALSE);
MoveWindow(g.hwndBuffer, 156, top, w - 159, h - top - bottom, FALSE);
MoveWindow(g.hwndBufferLog, 156, top, w - 159, h - top - bottom, FALSE);
- if (to_bottom)
+ if (to_bottom) {
buffer_scroll_to_bottom();
+ } else {
+ recheck_highlighted();
+ refresh_status();
+ }
InvalidateRect(g.hwndMain, NULL, TRUE);
}
@@ -1685,8 +1708,10 @@ window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
case WM_SYSCOMMAND:
{
+ // We're not deiconified yet, so duplicate recheck_highlighted().
auto b = buffer_by_name(g.buffer_current);
- if (b && wParam == SC_RESTORE) {
+ if (wParam == SC_RESTORE && b && b->highlighted && buffer_at_bottom() &&
+ !IsWindowVisible(g.hwndBufferLog)) {
b->highlighted = false;
refresh_icon();
}
@@ -1694,13 +1719,15 @@ window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
}
case WM_COMMAND:
- if (!lParam)
+ if (!lParam) {
process_accelerator(LOWORD(wParam));
- else if (lParam == (LPARAM) g.hwndBufferList)
+ } else if (lParam == (LPARAM) g.hwndBufferList) {
process_bufferlist_notification(HIWORD(wParam));
- else if (lParam == (LPARAM) g.hwndBuffer &&
- HIWORD(wParam) == EN_VSCROLL)
+ } else if (lParam == (LPARAM) g.hwndBuffer &&
+ HIWORD(wParam) == EN_VSCROLL) {
+ recheck_highlighted();
refresh_status();
+ }
return 0;
case WM_NOTIFY:
switch (((LPNMHDR) lParam)->code) {