[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#25408: Remove Decorations Around Emacs Frame (Windows OS)

From: martin rudalics
Subject: bug#25408: Remove Decorations Around Emacs Frame (Windows OS)
Date: Sat, 11 Feb 2017 15:27:36 +0100

>>> Are your changes available in a branch of the repo?
>> No.  But I hope that I can post a patch by the end of this week.
> Great, thanks a lot!

If you are on GNU/Linux or Windows then please apply the attached patch
synch-frames.diff to your current version of master and rebuild.  If you
succeeded doing that, start emacs -Q and continue reading.

To remove a frame's decorations, use the frame parameter `undecorated'
as in

(set-frame-parameter nil 'undecorated t)

To give that frame back its decorations use

(set-frame-parameter nil 'undecorated nil)

To make a new frame undecorated use

(make-frame '((undecorated . t)))

To make frames undecorated by default add something like

 '(default-frame-alist '((undecorated . t))))

to your .emacs.  If everything works as intended and your only interest
was to make frames without decorations, you can finish reading here.

If you didn't succeed removing a frame's decorations and you are on
GNU/Linux, you're window manager probably doesn't honor the Motif window
manager hints.  Please post the types of your build and window manager.
At the very least we can provide a list of the window managers that
don't comply.  Windows users might experience problems on anything past
XP, I've only tested it there.

Usually, the position of a frame's native rectangle doesn't change when
adding/removing decorations.  If you want to change it, use the `left'
and `top' frame parameters.

If you think you need to remove/add individual parts of the decorations
(titlebar, buttons, external borders) post your wishes here.  Some
window managers might be able to do that.

The rest of this text is concerned with describing additional features.
If some of them don't work on your system, please tell me, usually they
need a compliant window manager as well.

A first group of parameters is concerned with focusing/switching to
certain frames.  To make a frame not show up on the taskbar use the
frame parameter `skip-taskbar' as in

(set-frame-parameter nil 'skip-taskbar t)

This should remove your frame's icon from the taskbar and also disable
the <Alt>-<Tab> functionality to switch to that frame.  On some systems
(notably Windows) iconifying such a frame may "roll in" its window at
the bottom of the desktop.

To make a new frame not receive focus initially or when deiconified, use
the frame parameter `no-focus-on-map' as in

(make-frame '((no-focus-on-map . t)))

Usually this works but if you are using a focus follows mouse policy you
might have to specify the `no-accept-focus' parameter as well as in

(make-frame '((no-focus-on-map . t) (no-accept-focus . t)))

The `no-accept-focus' parameter, if non-nil, tries to never give the
frame focus in a "soft" way.  Development might not be entirely complete
in this area.

If you want to avoid that C-x 5 o switches to a specific frame, set
that frame's `no-other-frame' parameter as in

(set-frame-parameter nil 'no-other-frame t)

Using a clever combination of the `skip-taskbar', `no-focus-on-map',
`no-accept-focus' and `no-other-frame' you might be able to make a
completely catatonic frame which you can kill only with your task

If you want to make sure that a specific frame is deleted whenever
another frame is deleted use the `delete-before' parameter.  This avoids
confusing Emacs as, for example, when putting `delete-frame' on

To make a frame as small as possible use the `min-width' and
`min-height' parameters.  Evaluating

(let ((frame (make-frame
              `((tool-bar-lines . 0)
                (menu-bar-lines . 0)
                (vertical-scroll-bars . nil)
                (horizontal-scroll-bars . nil)
                (minibuffer . ,(minibuffer-window (selected-frame)))
                (left-fringe . 0)
                (right-fringe . 0)
                (background-color . "yellow")
                (undecorated . t)
                (border-width . 0)
                (width . 1)
                (height . 1)
                (left . ,(frame-parameter nil 'left))
                (top . ,(frame-parameter nil 'top))
                (min-width . 0)
                (min-height . 0)
                (delete-before . ,(selected-frame)))))
      (buffer (get-buffer-create "*x*")))
  (set-window-buffer (frame-root-window frame) buffer)
  (with-current-buffer buffer
    (setq mode-line-format nil)))

should give you a blinking cursor at the top left corner of your
selected frame.

The `mouse-wheel-frame' allows to specify mouse wheel scroll
transparency wrt the frame below this one.  Use it as in

(make-frame `((undecorated . t)
              (no-accept-focus . t)
              (mouse-wheel-frame . ,(selected-frame))
              (left . ,(/ (frame-pixel-width) 4))
              (top . ,(/ (frame-pixel-height) 4))
              (width . ,(/ (frame-width) 2))
              (height . ,(/ (frame-height) 2))))

Mouse wheel scrolling the window in the new frame should now scroll the
underlying window of the initial frame instead.  I'm not sure whether I
will implement mouse click (aka "hit") transparency in a similar way.

A second group of parameters/functions is concerned with maintaining and
investigating the stacking order of frames.  The `z-group' parameter
allows to put a frame in a separate group above or (not on Windows)
below all other frames that are not in the same group.  For example

(set-frame-parameter nil 'z-group 'above)

will make your frame (semi-)permanently appear above all other windows
on your desktop (including the task bar).  The implementation of this
parameter is not entirely complete yet, it's easily possible that I will
replace it by a simple function.  My window manager apparently removes
this property when the frame is iconified so I cannot always rely on

Also a frame with this parameter equalling `above' currently appears
above dialogue windows (to select files or fonts).  This will be fixed
soon but I'm not yet sure how.

`frame-restack' already is a function.  To test it try to play around
with the following forms:

(setq sframe (selected-frame))
(setq nframe (make-frame))

(frame-restack nframe sframe)
(frame-restack sframe nframe)
(frame-restack nframe sframe t)
(frame-restack sframe nframe t)

The function `frame-list-z-order' returns a list of your frames in the
stacking order of your display - bottommost first.

A final group of parameters/functions is concerned with making child
frames.  To make a frame a child frame of an existing frame you can use
something like

(set-frame-parameter nil 'parent-frame frame)

where `frame' must be a live frame.  This should work as in the
following form

(make-frame `((parent-frame . ,(selected-frame))
              (undecorated . t)
              (no-accept-focus . t)
              (mouse-wheel-frame . ,(selected-frame))
              (left . ,(/ (frame-pixel-width) 4))
              (top . ,(/ (frame-pixel-height) 4))
              (width . ,(/ (frame-width) 2))
              (height . ,(/ (frame-height) 2))))

Note that child frames automatically move and (de-)iconify together with
their parent frame without any further intervention from Emacs.
Moreover they are clipped automatically at the borders of their parent.

For normal (non-child) frames there's a new hook `move-frame-functions'
called after a frame was moved so you can also synchronize the movements
of two top-level frames.

Child frames are not listed by `frame-list' but are listed by
`frame-list-z-order'.  `frame-child-frames' lists all child frames of a
specific frame.

On GTK neither child frames nor undecorated frames can get a border.  If
you want a unified-looking border on any system you can use the new face
`internal-border' and set the frame parameter ‘internal-border-width’ to
some non-zero value for any such frame.

If the functions/parameters described here work sufficiently well, I'll
post a number of toy algorithms that show how to synchronize two frames
in a way that always shows one frame at a specified position on top of
the other.

The current version comes without info and frameset support.  I hope
that Juanma can help me with the latter.


Attachment: synch-frames.diff
Description: Text document

reply via email to

[Prev in Thread] Current Thread [Next in Thread]