From 40e2b3bfc2ed7737e27e076639e581b2753ff5f9 Mon Sep 17 00:00:00 2001
From: Yuanle Song <sylecn@gmail.com>
Date: Thu, 23 May 2024 14:31:23 +0800
Subject: [PATCH] v2.9.1 make posframe panel frame standout from user's buffer.

- auto handle service already :exists case when running
  (zero-input-panel-posframe-init)
- add a function zero-input-panel-posframe-show-candidates-prepare-buffer,
  which user can redefine to style the posframe panel.
- add zero-input-panel-posframe.el in zero-input-reload-all.el
---
 operational                  | 32 +++++++++++++++++++++--
 zero-input-framework.el      |  2 +-
 zero-input-panel-posframe.el | 49 +++++++++++++++++++++++++-----------
 zero-input-reload-all.el     |  1 +
 zero-input.el                |  4 +--
 5 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/operational b/operational
index 60e30ae..2e6daad 100644
--- a/operational
+++ b/operational
@@ -1,6 +1,6 @@
 * COMMENT -*- mode: org -*-
 #+Date: 2019-10-08
-Time-stamp: <2024-05-22>
+Time-stamp: <2024-05-23>
 #+STARTUP: content
 * notes                                                               :entry:
 ** 2019-04-01 zero-el a Chinese IM framework in emacs; FSM              :doc:
@@ -96,11 +96,17 @@ cd ~/lisp/elisp/zero/
 
 - test zero-input.el in a fresh emacs -Q window.
 
-  (load-file "~/.emacs.d/elpa/s-1.11.0/s.elc")
+  (load-file "~/.emacs.d/elpa/s-20220902.1511/s.el")
+  (load-file "~/lisp/elisp/zero/byte-compile-flags.el")
   (byte-compile-file "~/lisp/elisp/zero/zero-input.el" t)
   (global-set-key (kbd "<f1>") 'zero-input-mode)
   (zero-input-set-default-im "pinyin")
 
+  ;; to test posframe panel
+  (load-file "~/.emacs.d/elpa/posframe-1.4.3/posframe.el")
+  (byte-compile-file "~/lisp/elisp/zero/zero-input-panel-posframe.el" t)
+  (zero-input-panel-posframe-init)
+
   now in some buffer,
   press F1 and start typing.
 
@@ -154,6 +160,28 @@ see https://blog.emacsos.com/zero-el.html#org8e45833
 * later                                                               :entry:
 * current                                                             :entry:
 ** 
+** 2024-05-22 issues when testing in emacs -Q.
+- DONE frame bg color and fg color doesn't stand out.
+  easy to confuse with user's buffer content.
+
+  to make it easier to customize the theme, create a function that user can
+  advice or redefine.
+
+- DONE should handle service already :exists case.
+  just run quit and retry.
+  if retry still fail, then fail.
+
+- when two standalone emacs are running.
+  only one posframe panel service can run.
+  which means I can not type in two standalone emacs.
+
+  currently when I start posframe panel service in one emacs, and type in the
+  other emacs, the panel will show at point in the first emacs instance.
+
+  can I fix this? can each emacs has its own posframe panel service?
+
+  well, get rid of dbus and this can work.
+
 ** 2021-08-08 create a panel for wayland display server.
 currently zero-panel doesn't position itself correctly in wayland on debian 11
 bullseye.
diff --git a/zero-input-framework.el b/zero-input-framework.el
index 0e73555..3d83d4e 100644
--- a/zero-input-framework.el
+++ b/zero-input-framework.el
@@ -133,7 +133,7 @@ If item is not in lst, return nil."
 
 ;; zero-input-el version
 (defvar zero-input-version nil "Zero package version.")
-(setq zero-input-version "2.9.0")
+(setq zero-input-version "2.9.1")
 
 ;; FSM state
 (defconst zero-input--state-im-off 'IM-OFF)
diff --git a/zero-input-panel-posframe.el b/zero-input-panel-posframe.el
index c4f981b..b1a1c26 100644
--- a/zero-input-panel-posframe.el
+++ b/zero-input-panel-posframe.el
@@ -43,10 +43,12 @@
 (defvar zero-input-panel-posframe-buffer " *zero-input-panel-posframe-buffer*"
   "The posframe buffer used to show candidates.")
 
-(defun zero-input-panel-posframe-show-candidates (preedit-str _candidate-count candidates hints)
-  "Show CANDIDATES using posframe package.
-Argument PREEDIT-STR user typed characters."
-  (interactive)
+(defun zero-input-panel-posframe-show-candidates-prepare-buffer (preedit-str _candidate-count candidates hints)
+  "Prepare posframe buffer for showing CANDIDATES.
+
+Argument PREEDIT-STR user typed characters.
+Argument CANDIDATES a list of candidates to show to user.
+Argument HINTS extra key value pairs from dbus method call."
   (when (posframe-workable-p)
     ;; example hints:
     ;; ((in_emacs (t)) (filename ()) (page_number (1)) (has_next_page (t)) (has_previous_page (nil)) (move_x (2951)) (move_y (93)))
@@ -55,7 +57,9 @@ Argument PREEDIT-STR user typed characters."
 	  (has-previous-page (caadr (assoc "has_previous_page" hints)))
 	  (page-number (caadr (assoc "page_number" hints)))
 	  (hr-half (propertize "\n" 'face '(:height 25)))
-	  (hr (propertize "\n" 'face '(:height 50))))
+	  (hr (propertize "\n" 'face '(:height 50)))
+	  (user-fg-color (frame-parameter nil 'foreground-color))
+	  (_user-bg-color (frame-parameter nil 'background-color)))
       (with-current-buffer (get-buffer-create zero-input-panel-posframe-buffer)
 	(font-lock-mode -1)
 	(erase-buffer)
@@ -69,20 +73,29 @@ Argument PREEDIT-STR user typed characters."
 	  ;; only using "\n", line height is different than when the line
 	  ;; containers Chinese characters.
 	  (dotimes (_ (max 0 (- 10 i)))
-	    (insert (propertize "占\n" 'face '(:foreground "#FFFFFF")))))
+	    (insert (propertize "占\n" 'face (list :foreground user-fg-color)))))
 	(insert hr)
 	(insert (format " %s  %s  %s "
 			(if has-previous-page "<" " ")
 			(or page-number " ")
-			(if has-next-page ">" " "))))
-      (posframe-show zero-input-panel-posframe-buffer
-                     :position (point)
-		     ;; min-width/min-height is character width and height of
-		     ;; posframe, not pixels.
-		     :min-width 10
-		     :min-height 10
-		     :background-color "#FFFFFF"
-		     :foreground-color "#000000")))
+			(if has-next-page ">" " ")))))))
+
+(defun zero-input-panel-posframe-show-candidates (preedit-str candidate-count candidates hints)
+  "Show CANDIDATES using posframe package.
+Argument PREEDIT-STR user typed characters.
+Argument CANDIDATE-COUNT how many candidates to show."
+  (interactive)
+  (when (posframe-workable-p)
+    (zero-input-panel-posframe-show-candidates-prepare-buffer
+     preedit-str candidate-count candidates hints)
+    (posframe-show zero-input-panel-posframe-buffer
+                   :position (point)
+		   ;; min-width/min-height is character width and height of
+		   ;; posframe, not pixels.
+		   :min-width 10
+		   :min-height 10
+		   :background-color (frame-parameter nil 'foreground-color)
+		   :foreground-color (frame-parameter nil 'background-color)))
   :ignore)
 
 (defun zero-input-panel-posframe-move (x y)
@@ -120,6 +133,12 @@ Argument PREEDIT-STR user typed characters."
   (let ((service-name zero-input-panel-dbus-service-known-name))
     (let ((res (dbus-register-service :session service-name
 				      :do-not-queue)))
+      (when (eq res :exists)
+	;; replace existing panel service with posframe based service.
+	(zero-input-panel-quit)
+	;; async dbus call will return before server handle it.
+	(sleep-for 0.1)
+	(setq res (dbus-register-service :session service-name :do-not-queue)))
       (if (not (member res '(:primary-owner :already-owner)))
 	  (error "Register dbus service failed: %s" res))
       (dolist (method (list
diff --git a/zero-input-reload-all.el b/zero-input-reload-all.el
index d0be1e3..3c0b429 100644
--- a/zero-input-reload-all.el
+++ b/zero-input-reload-all.el
@@ -34,6 +34,7 @@ SOURCE-DIR where to find the zero source dir."
 		 "zero-input-pinyin-service-test.el"
 		 "zero-input-pinyin.el"
 		 "zero-input-pinyin-test.el"
+		 "zero-input-panel-posframe.el"
 		 ))
       (byte-compile-disable-warning 'docstrings)
       (byte-compile-file (concat source-dir f) t))))
diff --git a/zero-input.el b/zero-input.el
index d3d57a0..bb2c380 100644
--- a/zero-input.el
+++ b/zero-input.el
@@ -12,7 +12,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 
-;; Version: 2.9.0
+;; Version: 2.9.1
 ;; URL: https://gitlab.emacsos.com/sylecn/zero-el
 ;; Package-Requires: ((emacs "24.3") (s "1.2.0"))
 
@@ -253,7 +253,7 @@ If item is not in lst, return nil."
 
 ;; zero-input-el version
 (defvar zero-input-version nil "Zero package version.")
-(setq zero-input-version "2.9.0")
+(setq zero-input-version "2.9.1")
 
 ;; FSM state
 (defconst zero-input--state-im-off 'IM-OFF)
-- 
GitLab