How to create a small child-frame which only show two lines

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

How to create a small child-frame which only show two lines

tumashu
Hello,
      Emacs26's child-frame feature is very useful. I have created a candadite menu of
chinese input method with its help, and find that it is much fast than popup-el's menu
and comparable with minibuffer.

the only problem I faced it that:  I only need show 2 lines with child-frame while its mini
size is show 4 lines,  anyone suggest how to deal with this problem?

---------------
(setq my-child-frame
      (let ((after-make-frame-functions nil))
        (make-frame
         `((parent-frame . ,(window-frame))
           (no-accept-focus . t)
           (min-width  . t)
           (min-height . t)
           (border-width . 0)
           (internal-border-width . 0)
           (vertical-scroll-bars . nil)
           (horizontal-scroll-bars . nil)
           (left-fringe . 10)
           (right-fringe . 0)
           (menu-bar-lines . 0)
           (tool-bar-lines . 0)
           (line-spacing . 0)
           (unsplittable . t)
           (no-other-frame . t)
           ;;(undecorated . t)
           (undecorated . nil)
           (visibility . t)
           (cursor-type . nil)
           (minibuffer . nil)
           (width . 50)
           (height . 1)
           (no-special-glyphs . t)))))

(let ((window (frame-root-window my-child-frame)))
  (set-window-parameter window 'mode-line-format 'none)
  (set-window-parameter window 'header-line-format 'none))
--------------

child-frame-usage.png (12K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re:How to create a small child-frame which only show two lines

zhanghj
Maybe you can bind the variable window-min-height to 2.




At 2017-12-07 08:04:12, "tumashu" <[hidden email]> wrote:
Hello,
      Emacs26's child-frame feature is very useful. I have created a candadite menu of
chinese input method with its help, and find that it is much fast than popup-el's menu
and comparable with minibuffer.

the only problem I faced it that:  I only need show 2 lines with child-frame while its mini
size is show 4 lines,  anyone suggest how to deal with this problem?

---------------
(setq my-child-frame
      (let ((after-make-frame-functions nil))
        (make-frame
         `((parent-frame . ,(window-frame))
           (no-accept-focus . t)
           (min-width  . t)
           (min-height . t)
           (border-width . 0)
           (internal-border-width . 0)
           (vertical-scroll-bars . nil)
           (horizontal-scroll-bars . nil)
           (left-fringe . 10)
           (right-fringe . 0)
           (menu-bar-lines . 0)
           (tool-bar-lines . 0)
           (line-spacing . 0)
           (unsplittable . t)
           (no-other-frame . t)
           ;;(undecorated . t)
           (undecorated . nil)
           (visibility . t)
           (cursor-type . nil)
           (minibuffer . nil)
           (width . 50)
           (height . 1)
           (no-special-glyphs . t)))))

(let ((window (frame-root-window my-child-frame)))
  (set-window-parameter window 'mode-line-format 'none)
  (set-window-parameter window 'header-line-format 'none))
--------------


Reply | Threaded
Open this post in threaded view
|

Re:Re:How to create a small child-frame which only show two lines

tumashu
I have try this variable, It can make a smaller frame, but when I use this frame to show a buffer
and use fit-frame-to-buffer to adjust frame's size. the adjusted frame will show two blank line's space.
I have try set mini-height to 2, but no effect,  can mode-line's space not be removed?





在 2017-12-07 10:35:50,"jun" <[hidden email]> 写道:
Maybe you can bind the variable window-min-height to 2.




At 2017-12-07 08:04:12, "tumashu" <[hidden email]> wrote:
Hello,
      Emacs26's child-frame feature is very useful. I have created a candadite menu of
chinese input method with its help, and find that it is much fast than popup-el's menu
and comparable with minibuffer.

the only problem I faced it that:  I only need show 2 lines with child-frame while its mini
size is show 4 lines,  anyone suggest how to deal with this problem?

---------------
(setq my-child-frame
      (let ((after-make-frame-functions nil))
        (make-frame
         `((parent-frame . ,(window-frame))
           (no-accept-focus . t)
           (min-width  . t)
           (min-height . t)
           (border-width . 0)
           (internal-border-width . 0)
           (vertical-scroll-bars . nil)
           (horizontal-scroll-bars . nil)
           (left-fringe . 10)
           (right-fringe . 0)
           (menu-bar-lines . 0)
           (tool-bar-lines . 0)
           (line-spacing . 0)
           (unsplittable . t)
           (no-other-frame . t)
           ;;(undecorated . t)
           (undecorated . nil)
           (visibility . t)
           (cursor-type . nil)
           (minibuffer . nil)
           (width . 50)
           (height . 1)
           (no-special-glyphs . t)))))

(let ((window (frame-root-window my-child-frame)))
  (set-window-parameter window 'mode-line-format 'none)
  (set-window-parameter window 'header-line-format 'none))
--------------


Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

martin rudalics
In reply to this post by tumashu
 > I only need show 2 lines with child-frame while its mini
 > size is show 4 lines,  anyone suggest how to deal with this problem?
[...]
 > (let ((window (frame-root-window my-child-frame)))
 >    (set-window-parameter window 'mode-line-format 'none)
 >    (set-window-parameter window 'header-line-format 'none))

Looks like a stupid bug in the implementation of these parameters.  I'll
hopefully come up with a fix soon.

Thank you very much for reporting this, martin

Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

martin rudalics
 >  > I only need show 2 lines with child-frame while its mini
 >  > size is show 4 lines,  anyone suggest how to deal with this problem?
 > [...]
 >  > (let ((window (frame-root-window my-child-frame)))
 >  >    (set-window-parameter window 'mode-line-format 'none)
 >  >    (set-window-parameter window 'header-line-format 'none))
 >
 > Looks like a stupid bug in the implementation of these parameters.  I'll
 > hopefully come up with a fix soon.

Sorry.  Trying again with the current release version the following form
makes a frame with a two lines root window.  What does it make for you?

(let ((window-min-height 1)
       (window-min-width 1))
   (setq my-child-frame
        (let ((after-make-frame-functions nil))
           (make-frame
            `((parent-frame . ,(window-frame))
              (no-accept-focus . t)
              (min-width  . t)
              (min-height . t)
              (border-width . 0)
              (internal-border-width . 0)
              (vertical-scroll-bars . nil)
              (horizontal-scroll-bars . nil)
              (left-fringe . 10)
              (right-fringe . 0)
              (menu-bar-lines . 0)
              (tool-bar-lines . 0)
              (line-spacing . 0)
              (unsplittable . t)
              (no-other-frame . t)
              ;;(undecorated . t)
              (undecorated . nil)
              (visibility . t)
              (cursor-type . nil)
              (minibuffer . nil)
              (width . 50)
              (height . 1)
              (no-special-glyphs . t)))))

   (let ((window (frame-root-window my-child-frame)))
     (set-window-parameter window 'mode-line-format 'none)
     (set-window-parameter window 'header-line-format 'none))

   (set-window-buffer
    (frame-root-window my-child-frame) (get-buffer-create "*foo*"))

   (with-current-buffer "*foo*" (insert "line 1\nline 2\n"))
   (fit-frame-to-buffer my-child-frame))

If it gives you more than two lines, then please tell me what the
following two forms evaluate to.

(window-mode-line-height (frame-root-window my-child-frame))
(window-header-line-height (frame-root-window my-child-frame))

Thank you, martin

Reply | Threaded
Open this post in threaded view
|

Re:Re: How to create a small child-frame which only show two lines

tumashu
Thank your for your help, I have solved the problem: I add (window-min-height 1) and (window-min-width 1))
to my code and let my English main font is taller than my Chinese fonts.






At 2017-12-08 18:12:02, "martin rudalics" <[hidden email]> wrote: > > > I only need show 2 lines with child-frame while its mini > > > size is show 4 lines, anyone suggest how to deal with this problem? > > [...] > > > (let ((window (frame-root-window my-child-frame))) > > > (set-window-parameter window 'mode-line-format 'none) > > > (set-window-parameter window 'header-line-format 'none)) > > > > Looks like a stupid bug in the implementation of these parameters. I'll > > hopefully come up with a fix soon. > >Sorry. Trying again with the current release version the following form >makes a frame with a two lines root window. What does it make for you? > >(let ((window-min-height 1) > (window-min-width 1)) > (setq my-child-frame > (let ((after-make-frame-functions nil)) > (make-frame > `((parent-frame . ,(window-frame)) > (no-accept-focus . t) > (min-width . t) > (min-height . t) > (border-width . 0) > (internal-border-width . 0) > (vertical-scroll-bars . nil) > (horizontal-scroll-bars . nil) > (left-fringe . 10) > (right-fringe . 0) > (menu-bar-lines . 0) > (tool-bar-lines . 0) > (line-spacing . 0) > (unsplittable . t) > (no-other-frame . t) > ;;(undecorated . t) > (undecorated . nil) > (visibility . t) > (cursor-type . nil) > (minibuffer . nil) > (width . 50) > (height . 1) > (no-special-glyphs . t))))) > > (let ((window (frame-root-window my-child-frame))) > (set-window-parameter window 'mode-line-format 'none) > (set-window-parameter window 'header-line-format 'none)) > > (set-window-buffer > (frame-root-window my-child-frame) (get-buffer-create "*foo*")) > > (with-current-buffer "*foo*" (insert "line 1\nline 2\n")) > (fit-frame-to-buffer my-child-frame)) > >If it gives you more than two lines, then please tell me what the >following two forms evaluate to. > >(window-mode-line-height (frame-root-window my-child-frame)) >(window-header-line-height (frame-root-window my-child-frame)) > >Thank you, martin
Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

martin rudalics
 > Thank your for your help, I have solved the problem: I add (window-min-height 1) and (window-min-width 1))
 > to my code and let my English main font is taller than my Chinese fonts.

Would setting `set-frame-font' for that child frame help then?  Provided
you can say in advance which of your fonts should be the dominant one
for the frame in question.

BTW, note that setting these parameters

     (set-window-parameter window 'mode-line-format 'none)
     (set-window-parameter window 'header-line-format 'none))

is generally only needed when you show the corresponding buffer in a
"normal" window and in a child frame window.  If you show the buffer in
a child frame only, setting the buffer-local values of
`mode-line-format' and `header-line-format' to nil usually suffices.

martin

Reply | Threaded
Open this post in threaded view
|

Re:Re: How to create a small child-frame which only show two lines

tumashu
Font's align problem is not a big problem :-), Chinese emacs user's fonts setup is complicate, so
it is not easily to use set-frame-font.  so I decide just ignore this small problem :-)

I have use `mode-line-format' and `header-line-format' , they are more simple. thanks for this good tip.





At 2017-12-09 18:35:42, "martin rudalics" <[hidden email]> wrote: > > Thank your for your help, I have solved the problem: I add (window-min-height 1) and (window-min-width 1)) > > to my code and let my English main font is taller than my Chinese fonts. > >Would setting `set-frame-font' for that child frame help then? Provided >you can say in advance which of your fonts should be the dominant one >for the frame in question. > >BTW, note that setting these parameters > > (set-window-parameter window 'mode-line-format 'none) > (set-window-parameter window 'header-line-format 'none)) > >is generally only needed when you show the corresponding buffer in a >"normal" window and in a child frame window. If you show the buffer in >a child frame only, setting the buffer-local values of >`mode-line-format' and `header-line-format' to nil usually suffices. > >martin
Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

martin rudalics
 > Font's align problem is not a big problem :-), Chinese emacs user's fonts setup is complicate, so
 > it is not easily to use set-frame-font.  so I decide just ignore this small problem :-)

BTW, have you set `frame-resize-pixelwise' to non-nil?  Because only in
that case the result of fitting a frame will be always exact.

martin

Reply | Threaded
Open this post in threaded view
|

Re:Re: How to create a small child-frame which only show two lines

tumashu
Thanks for this infomation,

by the way, does emacs has a function, which can get the point's left-bottom pixel position,  if not,
is it possible to add it to emacs?

The below is an example I current use:
-------------
(defun pyim-tooltip-compute-pixel-position
    (&optional pos window pixel-width pixel-height dx dy)
  "Return pixel position of POS in WINDOW, which indicates relative
coordinates of bottom left corner of the object, its returned value is
like (X . Y)

Omitting POS and WINDOW means use current position and selected window,
respectively.

If PIXEL-WIDTH and PIXEL-HEIGHT are given, this function regard these
values as the size of a small window located around the POS, for example:
tooltip. These values are used to adjust the small window's location and
let it not disappear by sticking out of the display.

DX specifies horizontal offset in pixel.

DY specifies vertical offset in pixel. This makes the calculations done
without considering the height of object at POS, so the object might be
hidden by the tooltip.

This function is shameless steal from pos-tip."
  (let* ((frame (window-frame (or window (selected-window))))
         (posn (posn-at-point (or pos (window-point window)) window))
         (line (cdr (posn-actual-col-row posn)))
         (line-height (and line
                           (or (window-line-height line window)
                               (and (redisplay t)
                                    (window-line-height line window)))))
         (x-y (or (posn-x-y posn)
                  (let ((geom (pos-visible-in-window-p
                               (or pos (window-point window)) window t)))
                    (and geom (cons (car geom) (cadr geom))))
                  '(0 . 0)))
         (x (+ (car (window-inside-pixel-edges window))
               (car x-y)
               (or dx 0)))
         (y0 (+ (cadr (window-pixel-edges window))
                (or (nth 2 line-height) (cdr x-y))))
         (y (+ y0
               (or dy
                   (car line-height)
                   (with-current-buffer (window-buffer window)
                     (cond
                      ;; `posn-object-width-height' returns an incorrect value
                      ;; when the header line is displayed (Emacs bug #4426).
                      ((and posn
                            (null header-line-format))
                       (cdr (posn-object-width-height posn)))
                      ((and (bound-and-true-p text-scale-mode)
                            (not (zerop (with-no-warnings
                                          text-scale-mode-amount))))
                       (round (* (frame-char-height frame)
                                 (with-no-warnings
                                   (expt text-scale-mode-step
                                         text-scale-mode-amount)))))
                      (t (frame-char-height frame)))))))
         (xmax (frame-pixel-width frame))
         (ymax (frame-pixel-height frame))
         (upperside-p (> (+ y (or pixel-height 0))
                         ymax)))
    (cons (max 0 (min x (- xmax (or pixel-width 0))))
          (max 0 (if upperside-p
                     (- (if dy ymax y0) (or pixel-height 0))
                   y)))))


-----------






At 2017-12-11 14:42:23, "martin rudalics" <[hidden email]> wrote: > > Font's align problem is not a big problem :-), Chinese emacs user's fonts setup is complicate, so > > it is not easily to use set-frame-font. so I decide just ignore this small problem :-) > >BTW, have you set `frame-resize-pixelwise' to non-nil? Because only in >that case the result of fitting a frame will be always exact. > >martin
Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

Eli Zaretskii
> Date: Mon, 11 Dec 2017 16:29:16 +0800 (CST)
> From: tumashu  <[hidden email]>
> Cc: "[hidden email]" <[hidden email]>
>
> by the way, does emacs has a function, which can get the point's left-bottom pixel position,  if not,
> is it possible to add it to emacs?

Doesn't vertical-motion fit the bill?  If not, why not?

Reply | Threaded
Open this post in threaded view
|

Re:Re: How to create a small child-frame which only show two lines

tumashu

I need this function to get the pixel position, so I can put a tooltip in this position to show
some information.  vertical-motion seem to not have the feature.





At 2017-12-11 23:29:28, "Eli Zaretskii" <[hidden email]> wrote: >> Date: Mon, 11 Dec 2017 16:29:16 +0800 (CST) >> From: tumashu <[hidden email]> >> Cc: "[hidden email]" <[hidden email]> >> >> by the way, does emacs has a function, which can get the point's left-bottom pixel position, if not, >> is it possible to add it to emacs? > >Doesn't vertical-motion fit the bill? If not, why not?
Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

Stefan Monnier
> I need this function to get the pixel position, so I can put a tooltip
> in this position to show some information.  vertical-motion seem to
> not have the feature.

Maybe you're looking for posn-at-point?


        Stefan


Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

martin rudalics
In reply to this post by tumashu
 > (defun pyim-tooltip-compute-pixel-position
 >      (&optional pos window pixel-width pixel-height dx dy)
 >    "Return pixel position of POS in WINDOW, which indicates relative
 > coordinates of bottom left corner of the object, its returned value is
 > like (X . Y)

For mouse positions we return the upper left corner and in addition the
width and height of the object at point (where the height value would
inherently use the height of the entire line the object is part of).  I
think we should do the same here.  If the object is on top of the window
and partially off-screen, we'd probably have to return a negative
vertical position value.

 > If PIXEL-WIDTH and PIXEL-HEIGHT are given, this function regard these
 > values as the size of a small window located around the POS, for example:
 > tooltip. These values are used to adjust the small window's location and
 > let it not disappear by sticking out of the display.

IIUC your code avoids tooltips "sticking out of the frame".  Right?  In
either case you'd narrow the semantics and maybe something more general
should be used.

 > DX specifies horizontal offset in pixel.
 >
 > DY specifies vertical offset in pixel. This makes the calculations done
 > without considering the height of object at POS, so the object might be
 > hidden by the tooltip.

IIUC these are needed for the "sticking out of the frame" avoidance.
Right?  Because otherwise they should not be part of such a function.

A more general solution would allow to position the tooltip at either of
the four corners of the object at POS (for example, I'd prefer to put
them on an empty line that might happen to be above or below the glyph
at POS).

 >                                 (and (redisplay t)
 >                                      (window-line-height line window)))))

I'm never sure whether this is sufficient or `force-window-update' would
be needed too.  These days, `redisplay' has a quite confusing doc-string
wrt `redisplay-dont-pause' which makes me doubt even more.

 >                        ;; `posn-object-width-height' returns an incorrect value
 >                        ;; when the header line is displayed (Emacs bug #4426).

FWIW this bug should have been fixed more than six years ago.

martin

Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

martin rudalics
In reply to this post by Stefan Monnier
 > Maybe you're looking for posn-at-point?

His code is using that already.

martin

Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

tumashu
In reply to this post by martin rudalics
martin rudalics <[hidden email]> writes:

>> (defun pyim-tooltip-compute-pixel-position
>>      (&optional pos window pixel-width pixel-height dx dy)
>>    "Return pixel position of POS in WINDOW, which indicates relative
>> coordinates of bottom left corner of the object, its returned value is
>> like (X . Y)
>
> For mouse positions we return the upper left corner and in addition the
> width and height of the object at point (where the height value would
> inherently use the height of the entire line the object is part of).  I
> think we should do the same here.  If the object is on top of the window
> and partially off-screen, we'd probably have to return a negative
> vertical position value.
>
>> If PIXEL-WIDTH and PIXEL-HEIGHT are given, this function regard these
>> values as the size of a small window located around the POS, for example:
>> tooltip. These values are used to adjust the small window's location and
>> let it not disappear by sticking out of the display.
>
> IIUC your code avoids tooltips "sticking out of the frame".  Right?  In
> either case you'd narrow the semantics and maybe something more general
> should be used.
>
>> DX specifies horizontal offset in pixel.
>>
>> DY specifies vertical offset in pixel. This makes the calculations done
>> without considering the height of object at POS, so the object might be
>> hidden by the tooltip.
>
> IIUC these are needed for the "sticking out of the frame" avoidance.
> Right?  Because otherwise they should not be part of such a function.
>
> A more general solution would allow to position the tooltip at either of
> the four corners of the object at POS (for example, I'd prefer to put
> them on an empty line that might happen to be above or below the glyph
> at POS).
>
>>                                 (and (redisplay t)
>>                                      (window-line-height line window)))))
>
> I'm never sure whether this is sufficient or `force-window-update' would
> be needed too.  These days, `redisplay' has a quite confusing doc-string
> wrt `redisplay-dont-pause' which makes me doubt even more.
>
>>                        ;; `posn-object-width-height' returns an incorrect value
>>                        ;; when the header line is displayed (Emacs bug #4426).
>
> FWIW this bug should have been fixed more than six years ago.
>

To be honest, I do not understand the function very much, I only know it
just work :-), for this function is copied from pos-tip.el five years
ago's version, maybe many code of it just dead code.

pos-tip is a package which has similar job with popup-el, the different
is that pos-tip use tooltip while popup-el use overlay.  popup-el is
very popular but it does not run well with No-English language,
pos-tip has not this problem but it run too slow and unmaintaned
five years ago.

I find we can use child-frame to create a popup-el like package, which
is fast, easy understand and works well with No-English language.



> martin
>

--


Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

Eli Zaretskii
In reply to this post by tumashu
> Date: Tue, 12 Dec 2017 08:43:34 +0800 (CST)
> From: tumashu  <[hidden email]>
> Cc: "martin rudalics" <[hidden email]>,
> "[hidden email]" <[hidden email]>
>
> I need this function to get the pixel position, so I can put a tooltip in this position to show
> some information.  vertical-motion seem to not have the feature.

Perhaps there is a misunderstanding.  AFAIU, you can determine the
left-top pixel position at point, but you wanted the left-bottom
position instead, is that right?  If so, my suggestion was to call
vertical-motion to move down one line, then take the left-top position
at that place.  Doesn't that give you what you want?

Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

Stefan Monnier
> Perhaps there is a misunderstanding.  AFAIU, you can determine the
> left-top pixel position at point, but you wanted the left-bottom
> position instead, is that right?  If so, my suggestion was to call
> vertical-motion to move down one line, then take the left-top position
> at that place.

What if there's no position "down one line" (e.g. the next line is too
short or there's no next line)?


        Stefan



Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

Eli Zaretskii
In reply to this post by martin rudalics
> Date: Tue, 12 Dec 2017 09:56:19 +0100
> From: martin rudalics <[hidden email]>
> Cc: "[hidden email]" <[hidden email]>
>
>  >                        ;; `posn-object-width-height' returns an incorrect value
>  >                        ;; when the header line is displayed (Emacs bug #4426).
>
> FWIW this bug should have been fixed more than six years ago.

AFAIU you are saying that it _is_ fixed, so you wonder why the OP
seems to see it.  If so, I concur.  E.g., I couldn't reproduce the
original problem in an Info buffer (which does have a header-line).

Or am I missing something?

Reply | Threaded
Open this post in threaded view
|

Re: How to create a small child-frame which only show two lines

Eli Zaretskii
In reply to this post by Stefan Monnier
> From: Stefan Monnier <[hidden email]>
> Date: Tue, 12 Dec 2017 11:48:17 -0500
>
> > Perhaps there is a misunderstanding.  AFAIU, you can determine the
> > left-top pixel position at point, but you wanted the left-bottom
> > position instead, is that right?  If so, my suggestion was to call
> > vertical-motion to move down one line, then take the left-top position
> > at that place.
>
> What if there's no position "down one line" (e.g. the next line is too
> short or there's no next line)?

Does this mean that my suggestion works in all the other cases?  If
so, the above is easy.  But I'm not yet sure I understand the problem,
because the presented solution was so complex I'm probably missing
something much more important than the situation you describe.

12