Compare commits

..

1 Commits
v0.42.1 ... cli

Author SHA1 Message Date
Kovid Goyal
2f8c392571 Cleanup reading of argv from files 2025-04-28 09:52:26 +05:30
247 changed files with 1513 additions and 3050 deletions

View File

@@ -302,9 +302,9 @@
"name": "wayland",
"os": "linux",
"unix": {
"filename": "wayland-1.23.1.tar.xz",
"hash": "sha256:864fb2a8399e2d0ec39d56e9d9b753c093775beadc6022ce81f441929a81e5ed",
"urls": ["https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.23.1/downloads/{filename}"]
"filename": "wayland-1.23.0.tar.xz",
"hash": "sha256:05b3e1574d3e67626b5974f862f36b5b427c7ceeb965cb36a4e6c2d342e45ab2",
"urls": ["https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.23.0/downloads/{filename}"]
}
},
@@ -312,9 +312,9 @@
"name": "wayland-protocols",
"os": "linux",
"unix": {
"filename": "wayland-protocols-1.44.tar.xz",
"hash": "sha256:3df1107ecf8bfd6ee878aeca5d3b7afd81248a48031e14caf6ae01f14eebb50e",
"urls": ["https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.44/downloads/{filename}"]
"filename": "wayland-protocols-1.41.tar.xz",
"hash": "sha256:2786b6b1b79965e313f2c289c12075b9ed700d41844810c51afda10ee329576b",
"urls": ["https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.41/downloads/{filename}"]
}
}

View File

@@ -9,18 +9,6 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
Recent major new features
---------------------------
Access kitty with a single keypress [0.42]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. include:: quake-screenshots.rst
kitty now has a Quake like floating, translucent terminal window, so you can access
all that kitty goodness instantly with a single keypress.
See the screenshots on the side and head over to the :doc:`kitten page for details
on how to set it up </kittens/quick-access-terminal>`.
Multiple sized text [0.40]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -106,58 +94,29 @@ consumption to do the same tasks.
Detailed list of changes
-------------------------------------
0.42.1 [2025-05-17]
0.42.0 [future]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fix ambiguous width and private use characters not being rendered when used with variable width text-sizing protocol escape codes
- The :doc:`panel kitten </kittens/panel>` can now be used to :ref:`quake`
- Quick access terminal: Restore focus to previously active window when hiding the quick access terminal window on macOS (:iss:`8627`)
- Wayland: Fix an abort if the terminal program sets a window title longer than 2KB that contains CSI escape sequences and multibyte UTF-8 (:iss:`8619`)
- Quick access terminal: Allow toggling the window to full screen using the standard kitty :sc:`toggle_fullscreen` shortcut (:iss:`8626`)
- Quick access terminal: Allow configuring the monitor to display the panel on in Wayland/X11 (:iss:`8630`)
- A new setting :opt:`remember_window_position` to optionally use the position of the last closed kitty OS Window as the position of the first kitty OS Window when running a new kitty instance (:pull:`8601`)
- Panel kitten: A new ``center-sized`` value for :option:`--edge <kitty +kitten panel --edge>` to allow easily creating sized and centered panels
- Wayland: The `kitty --name` flag now sets the XDG *window tag* on compositors
that support the `xdg-toplevel-tag <https://wayland.app/protocols/xdg-toplevel-tag-v1>`__ protocol.
0.42.0 [2025-05-11]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- A new kitten: :doc:`quick-access-terminal </kittens/quick-access-terminal>` to :ref:`quake`
- The :doc:`panel kitten </kittens/panel>` works on macOS and X11 as well as Wayland (:iss:`2590`)
- The :doc:`panel kitten </kittens/panel>` now works on macOS as well as Wayland (:iss:`2590`)
- **Behavior change**: Now kitty does full grapheme segmentation following the
Unicode 16 spec when splitting text into cells (:iss:`8533`)
- **Behavior change**: The :ref:`automatic color switching functionality <auto_color_scheme>` now also controls background image settings (:iss:`8603`)
- panel kitten: Allow using :option:`kitty +kitten panel --single-instance` to create multiple panels in one process (:iss:`8549`)
- launch: Allow creating desktop panels such as those created by the :doc:`panel kitten </kittens/panel>` (:iss:`8549`)
- Remote control: Allow modifying desktop panels and showing/hiding OS Windows
using the ``kitten @ resize-os-window`` command (:iss:`8550`)
using the `kitten @ resize-os-window` command (:iss:`8550`)
- Remote control launch: Allow waiting for a program launched in a new window
to exit and get the exit code via the `kitty +launch
--wait-for-child-to-exit` command line flag (:disc:`8573`)
- Allow starting kitty with the OS window hidden via :option:`kitty --start-as=hidden <kitty --start-as>`, useful for single instance mode (:iss:`3466`)
- Allow starting kitty with the OS window hidden via :option:`kitty --start-as`\=hidden useful for single instance mode (:iss:`3466`)
- Allow configuring the mouse unhide behavior when using :opt:`mouse_hide_wait` (:pull:`8508`)
- diff kitten: Add half page and full page scroll vim-like bindings (:pull:`8514`)
- diff kitten: Allow diffing named pipes (:iss:`8597`)
- Fix a regression that caused automatic color themes to not be re-applied after config file reload (:iss:`8530`)
- Wayland: When the compositor supports the `xdg-system-bell
@@ -166,8 +125,8 @@ Detailed list of changes
- panel kitten: Allow specifying panel size in pixels in addition to cells
- Fix a regression in 0.36.0 that caused using = with single letter command
line flags to no longer work correctly (:iss:`8556`)
- Fix a regression in 0.36.0 that caused using = with single letter options to
no longer work correctly (:iss:`8556`)
- Single instance: Preserve environment variables from invoking environment in
newly created window (:disc:`8567`)
@@ -177,12 +136,6 @@ Detailed list of changes
- macOS: Fix text color in visual window select ignoring the color theme (:iss:`8579`)
- Launch action: Allow using an env var that resolves to a full command-line as the program to launch (:pull:`8613`)
- :ac:`change_font_size` allow multiplying/dividing the current font size in addition to incrementing it (:iss:`8616`)
- Box drawing: Improve appearance of rounder corners, giving them a uniform line width (:iss:`8299`)
0.41.1 [2025-04-03]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -12,6 +12,7 @@ import os
import re
import subprocess
import sys
import textwrap
import time
from functools import lru_cache, partial
from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple
@@ -30,6 +31,7 @@ if kitty_src not in sys.path:
from kitty.conf.types import Definition, expand_opt_references # noqa
from kitty.constants import str_version, website_url # noqa
from kitty.fast_data_types import Shlex, TEXT_SIZE_CODE # noqa
from kittens.panel.main import default_quake_cmdline # noqa
# config {{{
# -- Project information -----------------------------------------------------
@@ -62,7 +64,7 @@ extensions = [
'sphinx.ext.extlinks',
'sphinx_copybutton',
'sphinx_inline_tabs',
'sphinxext.opengraph',
"sphinxext.opengraph",
]
# URL for OpenGraph tags
@@ -120,6 +122,9 @@ string_replacements = {
'_kitty_install_cmd': 'curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin',
'_build_go_version': go_version('../go.mod'),
'_text_size_code': str(TEXT_SIZE_CODE),
'_default_quake_cmdline': textwrap.fill(
default_quake_cmdline, break_on_hyphens=False, break_long_words=False, initial_indent=' ' * 4, subsequent_indent=' ' * 8, width=77,
).replace('\n', ' \\\n'),
}

View File

@@ -470,8 +470,7 @@ You need to make sure that the environment variables you define in your shell's
rc files are either also defined system wide or via the :opt:`env` directive in
:file:`kitty.conf`. Common environment variables that cause issues are those
related to localization, such as :envvar:`LANG`, ``LC_*`` and loading of
configuration files such as ``XDG_*``, :envvar:`KITTY_CONFIG_DIRECTORY` and,
most importantly, ``PATH`` to locate binaries.
configuration files such as ``XDG_*``, :envvar:`KITTY_CONFIG_DIRECTORY`.
To see the environment variables that kitty sees, you can add the following
mapping to :file:`kitty.conf`::

View File

@@ -1003,8 +1003,8 @@ take, and the default value they take when missing. All integers are 32-bit.
Key Value Default Description
======= ==================== ========= =================
``a`` Single character. ``t`` The overall action this graphics command is performing.
``(a, c, d, f, ``t`` - transmit data, ``T`` - transmit data and display image,
p, q, t, T)`` ``q`` - query terminal, ``p`` - put (display) previous transmitted image,
``(a, c, d, f, `` ``t`` - transmit data, ``T`` - transmit data and display image,
``p, q, t, T)`` ``q`` - query terminal, ``p`` - put (display) previous transmitted image,
``d`` - delete image, ``f`` - transmit data for animation frames,
``a`` - control animation, ``c`` - compose animation frames

View File

@@ -149,14 +149,14 @@ user presses, for example, :kbd:`ctrl+shift+a` the escape code would be ``CSI
97;modifiers u``. It *must not* be ``CSI 65; modifiers u``.
If *alternate key reporting* is requested by the program running in the
terminal, the terminal can send two additional Unicode codepoints, the *shifted
key* and *base layout key*, separated by colons. The shifted key is simply the
upper-case version of ``unicode-codepoint``, or more technically, the shifted
version, in the currently active keyboard layout. So `a` becomes `A` and so on,
based on the current keyboard layout. This is needed to be able to match
against a shortcut such as :kbd:`ctrl+plus` which depending on the type of
keyboard could be either :kbd:`ctrl+shift+equal` or :kbd:`ctrl+plus`. Note that
the shifted key must be present only if shift is also present in the modifiers.
terminal, the terminal can send two additional Unicode codepoints, the
*shifted key* and *base layout key*, separated by colons.
The shifted key is simply the upper-case version of ``unicode-codepoint``, or
more technically, the shifted version. So `a` becomes `A` and so on, based on
the current keyboard layout. This is needed to be able to match against a
shortcut such as :kbd:`ctrl+plus` which depending on the type of keyboard could
be either :kbd:`ctrl+shift+equal` or :kbd:`ctrl+plus`. Note that the shifted
key must be present only if shift is also present in the modifiers.
The *base layout key* is the key corresponding to the physical key in the
standard PC-101 key layout. So for example, if the user is using a Cyrillic

View File

@@ -124,5 +124,5 @@ that is, they are used to set the variable value for some font characteristic.
In addition to these keys, any four letter key is treated as the name of a
variable characteristic of the font. Its value is used to set the value for
variable characteristic of the font. It's value is used to set the value for
the name.

View File

@@ -8,43 +8,52 @@ Draw a GPU accelerated dock panel on your desktop
Overview
--------------
.. include:: ../quake-screenshots.rst
Draw the desktop wallpaper or docks and panels using arbitrary
terminal programs, For example, have `btop
<https://github.com/aristocratos/btop>`__ or `cava
<https://github.com/karlstav/cava/>`__ be your desktop wallpaper.
You can use this kitten to draw a GPU accelerated panel on the edge of your
screen or as the desktop wallpaper, that shows the output from an arbitrary
terminal program.
It is useful for showing status information or notifications on your desktop
using terminal programs instead of GUI toolkits.
using terminal programs instead of GUI toolkits. It can also be used for a
:ref:`Quake like quick access terminal <quake>`.
.. figure:: ../screenshots/panel.png
:alt: Screenshot, showing a sample panel
:align: center
:width: 100%
Screenshot, showing a sample panel
The screenshot to the side shows some uses of the panel kitten to draw various
desktop components such as the background, a quick access floating terminal and
a dock panel showing system information (Linux only).
The screenshot above shows a sample panel that displays the current desktop and
window title as well as miscellaneous system information such as network
activity, CPU load, date/time, etc.
.. versionadded:: 0.42.0
Support for macOS and support for Wayland was added in 0.34.0
Support for macOS, see :ref:`compatibility matrix <panel_compat>` for details.
and X11 (background and overlay).
.. note::
.. versionadded:: 0.34.0
Support for Wayland. See :ref:`below <panel_compat>` for which
Wayland compositors work.
This kitten currently only works on macOS and Wayland compositors
that support the `wlr layer shell protocol
<https://wayland.app/protocols/wlr-layer-shell-unstable-v1#compositor-support>`__
(which is almost all of them except GNOME). On macOS the panels do not
prevent other windows from floating over them because of limitations in
Cocoa. On X11, only the ``top`` and ``bottom`` panels are widely supported,
the other types depend on the window manager used.
Using this kitten is simple, for example::
kitten panel sh -c 'printf "\n\n\nHello, world."; sleep 5s'
kitty +kitten panel sh -c 'printf "\n\n\nHello, world."; sleep 5s'
This will show ``Hello, world.`` at the top edge of your screen for five
seconds. Here, the terminal program we are running is :program:`sh` with a script
to print out ``Hello, world!``. You can make the terminal program as complex as
you like, as demonstrated in the screenshots.
you like, as demonstrated in the screenshot above.
If you are on Wayland or macOS, you can, for instance, run::
If you are on Wayland or macOS, you can, for instance run::
kitten panel --edge=background htop
kitty +kitten panel --edge=background htop
to display ``htop`` as your desktop background. Remember this works in everything
but GNOME and also, in sway, you have to disable the background wallpaper as
@@ -53,13 +62,40 @@ sway renders that over the panel kitten surface.
There are projects that make use of this facility to implement generalised
panels and desktop components:
.. _panel_projects:
* `kitty panel <https://github.com/5hubham5ingh/kitty-panel>`__
* `pawbar <https://github.com/codelif/pawbar>`__
.. _remote_control_panel:
.. _quake:
Make a Quake like quick access terminal
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. versionadded:: 0.42.0
Support for quake mode, works only on macOS and Wayland, except for GNOME.
This kitten can be used to make a quick access terminal, that appears and
disappears at a key press. To do so use the following command:
.. code-block:: sh
_default_quake_cmdline
Run this command in a terminal, and a quick access kitty panel will show up at
the top of your screen. Run it again, and the panel will be hidden.
Simply bind this command to some key press in your window manager or desktop
environment settings and then you have a quick access terminal at a single key press.
You can use the various panel options to configure the size, appearance and
position of the quick access panel. In particular, the :option:`kitty +kitten panel --config` and
:option:`kitty +kitten panel --override` options can be used to theme the terminal appropriately,
making it look different from regular kitty terminal instances.
.. note::
If you want to start the quake terminal hidden, use
:option:`kitty +kitten panel --start-as-hidden`, useful if you are starting it in the background
during computer startup.
Controlling panels via remote control
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -67,7 +103,7 @@ Controlling panels via remote control
You can control panels via the kitty :doc:`remote control </remote-control>` facility. Create a panel
with remote control enabled::
kitten panel -o allow_remote_control=socket-only --lines=2 \
kitty +kitten panel -o allow_remote_control=socket-only --lines=2 \
--listen-on=unix:/tmp/panel kitten run-shell
@@ -89,138 +125,3 @@ To create a new panel running the program top, in the same instance
.. include:: ../generated/cli-kitten-panel.rst
.. _quake_ss:
How the screenshots were generated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The system statistics in the background were created using::
kitten panel --edge=background -o background_opacity=0.2 -o background=black btop
This creates a kitty background window and inside it runs the `btop
<https://github.com/aristocratos/btop>`__ program to display the statistics.
The floating quick access window was created by running::
kitten quick-access-terminal kitten run-shell \
zsh -c 'printf "\e]66;s=4;Quick access kitty in Hyprland\a\n\n\n\nAlso uses kitty to draw desktop background\n"'
This starts the quick access window and inside it runs ``kitten run-shell``, which
in turn first runs ``zsh`` to print out the message and then starts the users login
shell.
The Linux dock panel was::
kitten panel kitty +launch my-panel.py
This creates the panel window and runs the ``my-panel.py`` script inside it
using the Python interpreter that comes bundled with kitty. Unfortunately the
actual script is not public, but there are :ref:`public projects implementing
general purpose panels using kitty <panel_projects>`.
.. _panel_compat:
Compatibility with various platforms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. only:: man
See the HTML documentation for the compatibility matrix.
.. only:: not man
Generated with the help of the :file:`panels.py` test script.
.. tab:: Wayland
Below is a list of the status of various Wayland compositors. The panel kitten
relies of the `wlr layer shell protocol
<https://wayland.app/protocols/wlr-layer-shell-unstable-v1#compositor-support>`__,
which is technically supported by almost all Wayland compositors, but the
implementation in some of them is quite buggy.
🟢 **Hyprland**
Fully working, no known issues
🟢 **KDE** (kwin)
Fully working, no known issues. KDE uses an `undocumented mapping <https://invent.kde.org/plasma/kwin/-/blob/3dc5cee6b34792486b343098e55e7f2b90dfcd00/src/layershellv1window.cpp#L24>`__ under Wayland to set the window type from the :code:`kitten panel --app-id` flag. You might want to use :code:`--app-id=dock` so that KDE treats the window as a dock panel, and disables window
appearing/disappearing animations for it.
🟠 **Sway**
Partially working. Issues include:
* Renders its configured background over the background window instead of
under it. This is likely because it uses the wlr protocol for
backgrounds itself.
* Hiding a dock panel (unmapping the window) does not release the space
used by the dock.
🟠 **niri**
Breaks when hiding (unmapping) layer shell windows. This means the quick
access terminal is non-functional, but background and dock panels work.
More technically, keyboard focus gets stuck in the hidden window and when trying
to remap the hidden window niri never sends configure events for the remapped surface.
🟠 **labwc**
Breaks when hiding (unmapping) layer shell windows. This means the quick
access terminal is non-functional, but background and dock panels work.
More technically, when unmapping the surface (attaching a NULL buffer to
it) labwc continues to send configure events to the unmapped surface,
leading to Wayland protocol errors and a crash of labwc.
🔴 **GNOME** (mutter)
Does not implement the wlr protocol at all, nothing works.
.. tab:: macOS
Mostly everything works, with the notable exception that dock panels do not
prevent other windows from covering them. This is because Apple does not
provide and way to do this in their APIs.
.. tab:: X11
Support is highly dependent on the quirks of individual window
managers. See the matrix below:
.. list-table:: Compatibility matrix
:header-rows: 1
:stub-columns: 1
* - WM
- Desktop
- Dock
- Quick
- Notes
* - KDE
- 🟠
- 🟢
- 🟢
- transparency does not work for :option:`--edge=background <--edge>`
* - GNOME
- 🟢
- 🟢
- 🟢
-
* - XFCE
- 🟢
- 🟢
- 🟢
-
* - i3
- 🔴
- 🟠
- 🔴
- only top and bottom dock panels, without transparency
* - xmonad
- 🔴
- 🔴
- 🔴
- doesn't support the needed NET_WM protocols

View File

@@ -1,84 +0,0 @@
.. _quake:
Make a Quake like quick access terminal
====================================================================================================
.. highlight:: sh
.. only:: man
Overview
--------------
.. include:: ../quake-screenshots.rst
.. versionadded:: 0.42.0
See :ref:`here for what platforms it works on <panel_compat>`.
This kitten can be used to make a quick access terminal, that appears and
disappears at a key press. To do so use the following command:
.. code-block:: sh
kitten quick-access-terminal
Run this command in a terminal, and a quick access kitty window will show up at
the top of your screen. Run it again, and the window will be hidden.
To make the terminal appear and disappear at a key press:
.. |macOs| replace:: :guilabel:`System Preferences->Keyboard->Keyboard Shortcuts->Services->General`
.. only:: not man
.. tab:: Linux
Simply bind the above command to some key press in your window manager or desktop
environment settings and then you have a quick access terminal at a single key press.
.. tab:: macOS
In kitty, run the above command to show the quick access window, then close
it by running the command again or pressing :kbd:`ctrl+d`. Now go to |macOS| and set a shortcut for
the :guilabel:`Quick access to kitty` entry.
.. only:: man
In Linux, simply assign the above command to a global shortcut in your
window manager. In macOS, go to |macOS| and set a shortcut
for the :guilabel:`Quick access to kitty` entry.
Configuration
------------------------
You can configure the appearance and behavior of the quick access window
by creating a :file:`quick-access-terminal.conf` file in your
:ref:`kitty config folder <confloc>`. In particular, you can use the
:opt:`kitty_conf <kitten-quick_access_terminal.kitty_conf>` option to change
various kitty settings, just for the quick access window.
.. note::
This kitten uses the :doc:`panel kitten </kittens/panel>` under the
hood. You can use the :ref:`techniques described there <remote_control_panel>`
for remote controlling the quick access window, remember to add
``kitty_override allow_remote_control=socket-only`` and ``kitty_override
listen_on=unix:/tmp/whatever`` to
:file:`quick-access-terminal.conf`.
See below for the supported configuration directives:
.. include:: /generated/conf-kitten-quick_access_terminal.rst
.. include:: /generated/cli-kitten-quick_access_terminal.rst
Sample quick-access-terminal.conf
---------------------------------------
You can download a sample :file:`quick-access-terminal.conf` file with all default settings and
comments describing each setting by clicking: :download:`sample quick-access-terminal.conf
</generated/conf/quick_access_terminal.conf>`.

View File

@@ -70,8 +70,7 @@ This works by creating three files: :file:`dark-theme.auto.conf`,
:file:`light-theme.auto.conf` and :file:`no-preference-theme.auto.conf` in the
kitty config directory. When these files exist, kitty queries the OS for its color scheme
and uses the appropriate file. Note that the colors in these files override all other
colors, and also all background image settings,
even those specified using the :option:`kitty --override` command line flag.
colors, even those specified using the :option:`kitty --override` command line flag.
kitty will also automatically change colors when the OS color scheme changes,
for example, during night/day transitions.

View File

@@ -13,8 +13,6 @@ Extend with kittens
kittens/themes
kittens/choose-fonts
kittens/hints
kittens/quick-access-terminal
kittens/panel
kittens/remote_file
kittens/hyperlinked_grep
kittens/transfer
@@ -53,16 +51,6 @@ Some prominent kittens:
filenames, words, lines, etc. from the terminal screen.
:doc:`Quick access terminal <kittens/quick-access-terminal>`
Get access to a quick access floating, semi-transparent kitty window
with a single keypress.
:doc:`Panel <kittens/panel>`
Draw the desktop wallpaper or docks and panels using arbitrary
terminal programs.
:doc:`Remote file <kittens/remote_file>`
Edit, open, or download remote files over SSH easily, by simply clicking on
the filename.

View File

@@ -1,29 +0,0 @@
.. only:: not man
.. sidebar::
**Screenshots**
.. figure:: /screenshots/quake-macos.webp
:alt: Screenshot, showing the kitty floating quick access terminal above the background which is the program btop, running inside kitty, on macOS
:align: center
:width: 100%
macOS
.. figure:: /screenshots/quake-hypr.webp
:alt: Screenshot, showing the kitty floating quick access terminal above the background which is the program btop, running inside kitty, on Hyprland in Linux
:align: center
:width: 100%
Linux
.. figure:: /screenshots/panel.png
:alt: Screenshot, showing a sample panel
:align: center
:width: 100%
A sample panel on Linux
How the screenshots :ref:`were generated <quake_ss>`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

View File

@@ -259,9 +259,9 @@ def completion_for_launch_wrappers(*names: str) -> None:
def generate_completions_for_kitty() -> None:
print('package completion\n')
print('import "github.com/kovidgoyal/kitty/tools/cli"')
print('import "github.com/kovidgoyal/kitty/tools/cmd/tool"')
print('import "github.com/kovidgoyal/kitty/tools/cmd/at"')
print('import "kitty/tools/cli"')
print('import "kitty/tools/cmd/tool"')
print('import "kitty/tools/cmd/at"')
print('func kitty(root *cli.Command) {')
@@ -450,6 +450,15 @@ def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) ->
# kittens {{{
@lru_cache
def wrapped_kittens() -> tuple[str, ...]:
with open('shell-integration/ssh/kitty') as f:
for line in f:
if line.startswith(' wrapped_kittens="'):
val = line.strip().partition('"')[2][:-1]
return tuple(sorted(filter(None, val.split())))
raise Exception('Failed to read wrapped kittens from kitty wrapper script')
def generate_conf_parser(kitten: str, defn: Definition) -> None:
with replace_if_needed(f'kittens/{kitten}/conf_generated.go'):
@@ -458,7 +467,7 @@ def generate_conf_parser(kitten: str, defn: Definition) -> None:
def generate_extra_cli_parser(name: str, spec: str) -> None:
print('import "github.com/kovidgoyal/kitty/tools/cli"')
print('import "kitty/tools/cli"')
go_opts = tuple(go_options_for_seq(parse_option_spec(spec)[0]))
print(f'type {name}_options struct ''{')
for opt in go_opts:
@@ -508,7 +517,7 @@ def kitten_clis() -> None:
has_underscore = '_' in kitten
print(f'package {kitten}')
print('import "fmt"')
print('import "github.com/kovidgoyal/kitty/tools/cli"')
print('import "kitty/tools/cli"')
print('var _ = fmt.Sprintf')
print('func create_cmd(root *cli.Command, run_func func(*cli.Command, *Options, []string)(int, error)) {')
print('ans := root.AddSubCommand(&cli.Command{')
@@ -530,7 +539,7 @@ def kitten_clis() -> None:
for opt in gopts:
print(opt.as_option('ans'))
od.append(opt.struct_declaration())
ser.append('\n'.join(opt.as_string_for_commandline()))
ser.append(opt.as_string_for_commandline())
if ac is not None:
print(''.join(ac.as_go_code('ans.ArgCompleter', ' = ')))
if not kcd:
@@ -544,11 +553,8 @@ def kitten_clis() -> None:
print('\n'.join(od))
print('}')
print('func (opts Options) AsCommandLine() (ans []string) {')
if ser:
print('\t sval := ""')
print('\t _ = sval')
for x in ser:
print('\t' + x)
for x in ser:
print('\t' + x)
print('return')
print('}')
@@ -723,7 +729,7 @@ def update_at_commands() -> None:
odef = '\n'.join(opt_def)
code = f'''
package at
import "github.com/kovidgoyal/kitty/tools/cli"
import "kitty/tools/cli"
type rc_global_options struct {{
{sdef}
}}
@@ -751,7 +757,7 @@ def update_completion() -> None:
with replace_if_needed('tools/cmd/edit_in_kitty/launch_generated.go'):
print('package edit_in_kitty')
print('import "github.com/kovidgoyal/kitty/tools/cli"')
print('import "kitty/tools/cli"')
print('func AddCloneSafeOpts(cmd *cli.Command) {')
completion_for_launch_wrappers('cmd')
print(''.join(CompletionSpec.from_string('type:file mime:text/* group:"Text files"').as_go_code('cmd.ArgCompleter', ' = ')))

View File

@@ -125,7 +125,6 @@ typedef struct _GLFWwindowNS
id delegate;
id view;
id layer;
pid_t previous_front_most_application;
bool maximized;
bool retina;

View File

@@ -1621,12 +1621,6 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
@implementation GLFWWindow
static void
handle_screen_size_change(_GLFWwindow *window, NSNotification *notification UNUSED) {
if (!window || !window->ns.layer_shell.is_active) return;
_glfwPlatformSetLayerShellConfig(window, NULL);
}
- (instancetype)initWithGlfwWindow:(NSRect)contentRect
styleMask:(NSWindowStyleMask)style
backing:(NSBackingStoreType)backingStoreType
@@ -1636,13 +1630,6 @@ handle_screen_size_change(_GLFWwindow *window, NSNotification *notification UNUS
if (self != nil) {
glfw_window = initWindow;
self.tabbingMode = NSWindowTabbingModeDisallowed;
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserverForName:NSApplicationDidChangeScreenParametersNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification * _Nonnull notification) {
handle_screen_size_change(glfw_window, notification);
}];
}
return self;
}
@@ -1650,7 +1637,6 @@ handle_screen_size_change(_GLFWwindow *window, NSNotification *notification UNUS
- (void) removeGLFWWindow
{
glfw_window = NULL;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (BOOL)validateMenuItem:(NSMenuItem *)item {
@@ -1940,22 +1926,6 @@ screen_for_window_center(_GLFWwindow *window) {
return NSScreen.mainScreen;
}
const GLFWLayerShellConfig*
_glfwPlatformGetLayerShellConfig(_GLFWwindow *window) {
return &window->ns.layer_shell.config;
}
static NSScreen*
screen_for_name(const char *name) {
int count = 0;
GLFWmonitor **monitors = glfwGetMonitors(&count);
for (int i = 0; i < count; i++) {
const char *q = glfwGetMonitorName(monitors[i]);
if (q && strcmp(q, name) == 0) return ((_GLFWmonitor*)monitors[i])->ns.screen;
}
return NULL;
}
bool
_glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig *value) {
#define config window->ns.layer_shell.config
@@ -1986,10 +1956,6 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
// HACK: Changing the style mask can cause the first responder to be cleared
[nswindow makeFirstResponder:window->ns.view];
NSScreen *screen = screen_for_window_center(window);
if (config.output_name[0]) {
NSScreen *q = screen_for_name(config.output_name);
if (q) screen = q;
}
unsigned cell_width, cell_height; double left_edge_spacing, top_edge_spacing, right_edge_spacing, bottom_edge_spacing;
float xscale = (float)config.expected.xscale, yscale = (float)config.expected.yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
@@ -2031,11 +1997,6 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
x += width - panel_width + 1.;
width = panel_width;
break;
case GLFW_EDGE_CENTER_SIZED:
x += (width - panel_width) / 2;
y += (height - panel_height) / 2;
width = panel_width; height = panel_height;
break;
default: // top left
y += height - panel_height + 1.;
height = panel_height; width = panel_width;
@@ -2045,10 +2006,8 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
if (height < 1.) height = NSWidth(screen.visibleFrame);
}
if (config.edge != GLFW_EDGE_CENTER_SIZED) {
x += config.requested_left_margin; width -= config.requested_left_margin + config.requested_right_margin;
y += config.requested_bottom_margin; height -= config.requested_top_margin + config.requested_bottom_margin;
}
x += config.requested_left_margin; width -= config.requested_left_margin + config.requested_right_margin;
y += config.requested_bottom_margin; height -= config.requested_top_margin + config.requested_bottom_margin;
[nswindow setAnimationBehavior:animation_behavior];
[nswindow setLevel:level];
@@ -2228,39 +2187,14 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
NSRunningApplication *app = [[NSWorkspace sharedWorkspace] frontmostApplication];
window->ns.previous_front_most_application = 0;
if (app && app.processIdentifier != getpid()) window->ns.previous_front_most_application = app.processIdentifier;
if (window->ns.layer_shell.is_active && window->ns.layer_shell.config.type == GLFW_LAYER_SHELL_BACKGROUND) {
[window->ns.object orderBack:nil];
} else [window->ns.object orderFront:nil];
debug("Previously active application pid: %d bundle identifier: %s\n",
window->ns.previous_front_most_application, app ? app.bundleIdentifier.UTF8String : "");
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
[window->ns.object orderOut:nil];
pid_t prev_app_pid = window->ns.previous_front_most_application; window->ns.previous_front_most_application = 0;
NSRunningApplication *app;
if (window->ns.layer_shell.is_active && prev_app_pid > 0 && (app = [NSRunningApplication runningApplicationWithProcessIdentifier:prev_app_pid])) {
unsigned num_visible = 0;
for (_GLFWwindow *w = _glfw.windowListHead; w; w = w->next) {
if (_glfwPlatformWindowVisible(w)) num_visible++;
}
if (!num_visible) {
// yieldActivationToApplication was introduced in macOS 14 (Sonoma)
SEL selector = NSSelectorFromString(@"yieldActivationToApplication:");
if ([NSApp respondsToSelector:selector]) {
[NSApp performSelector:selector withObject:app];
[app activateWithOptions:0];
} else {
#define NSApplicationActivateIgnoringOtherApps 2
[app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
#undef NSApplicationActivateIgnoringOtherApps
}
}
}
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
@@ -3304,7 +3238,6 @@ glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int *cocoa_mods) {
return _glfwPlatformGetNativeKeyForKey(glfw_key);
}
GLFWAPI bool glfwIsLayerShellSupported(void) { return true; }
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////

11
glfw/dbus_glfw.c vendored
View File

@@ -214,6 +214,13 @@ typedef struct {
void *user_data;
} MethodResponse;
static const char*
format_message_error(DBusError *err) {
static char buf[1024];
snprintf(buf, sizeof(buf), "[%s] %s", err->name ? err->name : "", err->message);
return buf;
}
static void
method_reply_received(DBusPendingCall *pending, void *user_data) {
MethodResponse *res = (MethodResponse*)user_data;
@@ -221,7 +228,7 @@ method_reply_received(DBusPendingCall *pending, void *user_data) {
if (msg) {
DBusError err;
dbus_error_init(&err);
if (dbus_set_error_from_message(&err, msg)) res->callback(NULL, &err, res->user_data);
if (dbus_set_error_from_message(&err, msg)) res->callback(NULL, format_message_error(&err), res->user_data);
else res->callback(msg, NULL, res->user_data);
}
}
@@ -236,7 +243,7 @@ call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_p
DBusError error; dbus_error_init(&error);
RAII_MSG(reply, dbus_connection_send_with_reply_and_block(session_bus, msg, timeout, &error));
if (dbus_error_is_set(&error)) {
callback(reply, &error, user_data);
callback(reply, error.message, user_data);
return false;
} else if (reply) {
callback(reply, NULL, user_data);

2
glfw/dbus_glfw.h vendored
View File

@@ -33,7 +33,7 @@
static inline void cleanup_msg(void *p) { DBusMessage *m = *(DBusMessage**)p; if (m) dbus_message_unref(m); m = NULL; }
#define RAII_MSG(name, initializer) __attribute__((cleanup(cleanup_msg))) DBusMessage *name = initializer
typedef void(*dbus_pending_callback)(DBusMessage *msg, const DBusError *err, void* data);
typedef void(*dbus_pending_callback)(DBusMessage *msg, const char* err, void* data);
typedef struct {
EventLoopData* eld;

View File

@@ -323,12 +323,16 @@ def generate_wrappers(glfw_header: str) -> None:
void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data)
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
bool glfwWaylandIsLayerShellSupported(void)
bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle)
bool glfwWaylandBeep(GLFWwindow *handle)
GLFWLayerShellConfig* glfwWaylandLayerShellConfig(GLFWwindow *handle)
pid_t glfwWaylandCompositorPID(void)
unsigned long long glfwDBusUserNotify(const GLFWDBUSNotificationData *n, GLFWDBusnotificationcreatedfun callback, void *data)
void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler)
int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc)
void glfwSetX11WindowAsDock(int32_t x11_window_id)
void glfwSetX11WindowStrut(int32_t x11_window_id, uint32_t dimensions[12])
'''.splitlines():
if line:
functions.append(Function(line.strip(), check_fail=False))

15
glfw/glfw3.h vendored
View File

@@ -1056,7 +1056,6 @@ typedef enum {
#define GLFW_WAYLAND_APP_ID 0x00025001
#define GLFW_WAYLAND_BGCOLOR 0x00025002
#define GLFW_WAYLAND_WINDOW_TAG 0x00025003
/*! @} */
#define GLFW_NO_API 0
@@ -1303,24 +1302,19 @@ typedef struct GLFWkeyevent
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_CENTER, GLFW_EDGE_NONE, GLFW_EDGE_CENTER_SIZED } GLFWEdge;
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_CENTER, GLFW_EDGE_NONE } GLFWEdge;
typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAND} GLFWFocusPolicy;
typedef struct GLFWLayerShellConfig {
GLFWLayerShellType type;
GLFWEdge edge;
struct {
GLFWEdge edge;
int requested_top_margin, requested_left_margin, requested_bottom_margin, requested_right_margin;
} previous;
bool was_toggled_to_fullscreen;
char output_name[128];
char output_name[64];
GLFWFocusPolicy focus_policy;
unsigned x_size_in_cells, x_size_in_pixels;
unsigned y_size_in_cells, y_size_in_pixels;
int requested_top_margin, requested_left_margin, requested_bottom_margin, requested_right_margin;
int requested_exclusive_zone, hide_on_focus_loss;
int requested_exclusive_zone;
unsigned override_exclusive_zone;
void (*size_callback)(GLFWwindow *window, float xscale, float yscale, unsigned *cell_width, unsigned *cell_height, double *left_edge_spacing, double *top_edge_spacing, double *right_edge_spacing, double *bottom_edge_spacing);
struct { float xscale, yscale; } expected;
@@ -1983,7 +1977,6 @@ GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun function);
GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselectionfun callback);
GLFWAPI GLFWhascurrentselectionfun glfwSetHasCurrentSelectionCallback(GLFWhascurrentselectionfun callback);
GLFWAPI GLFWimecursorpositionfun glfwSetIMECursorPositionCallback(GLFWimecursorpositionfun callback);
GLFWAPI bool glfwIsLayerShellSupported(void);
/*! @brief Terminates the GLFW library.
*
@@ -2386,7 +2379,6 @@ GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, flo
* @ingroup monitor
*/
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
GLFWAPI const char* glfwGetMonitorDescription(GLFWmonitor* monitor);
/*! @brief Sets the user pointer of the specified monitor.
*
@@ -2881,7 +2873,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, G
GLFWAPI bool glfwToggleFullscreen(GLFWwindow *window, unsigned int flags);
GLFWAPI bool glfwIsFullscreen(GLFWwindow *window, unsigned int flags);
GLFWAPI bool glfwAreSwapsAllowed(const GLFWwindow* window);
GLFWAPI const GLFWLayerShellConfig* glfwGetLayerShellConfig(GLFWwindow* handle);
GLFWAPI bool glfwSetLayerShellConfig(GLFWwindow* handle, const GLFWLayerShellConfig *value);
/*! @brief Destroys the specified window and its context.

12
glfw/ibus_glfw.c vendored
View File

@@ -373,9 +373,9 @@ read_ibus_address(_GLFWIBUSData *ibus) {
}
void
input_context_created(DBusMessage *msg, const DBusError *err, void *data) {
if (err) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to create input context with error: %s: %s", err->name, err->message);
input_context_created(DBusMessage *msg, const char* errmsg, void *data) {
if (errmsg) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to create input context with error: %s", errmsg);
return;
}
const char *path = NULL;
@@ -488,15 +488,15 @@ glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h) {
}
void
key_event_processed(DBusMessage *msg, const DBusError *err, void *data) {
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
uint32_t handled = 0;
_GLFWIBUSKeyEvent *ev = (_GLFWIBUSKeyEvent*)data;
// Restore key's text from the text embedded in the structure.
ev->glfw_ev.text = ev->__embedded_text;
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
bool failed = false;
if (err) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s: %s", err->name, err->message);
if (errmsg) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
failed = true;
} else {
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);

10
glfw/internal.h vendored
View File

@@ -331,7 +331,7 @@ struct _GLFWwndconfig
char instanceName[256];
} x11;
struct {
char appId[256], windowTag[256];
char appId[256];
uint32_t bgcolor;
} wl;
};
@@ -490,7 +490,7 @@ struct _GLFWwindow
//
struct _GLFWmonitor
{
const char *name, *description;
char* name;
void* userPointer;
// Physical dimensions in millimeters.
@@ -668,10 +668,6 @@ struct _GLFWlibrary
//
extern _GLFWlibrary _glfw;
typedef struct GeometryRect { int x, y, width, height; } GeometryRect;
typedef struct MonitorGeometry {
GeometryRect full, workarea;
} MonitorGeometry;
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@@ -719,7 +715,6 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images);
bool _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig *value);
const GLFWLayerShellConfig* _glfwPlatformGetLayerShellConfig(_GLFWwindow* window);
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
@@ -883,7 +878,6 @@ unsigned long long _glfwPlatformAddTimer(monotonic_t interval, bool repeats, GLF
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled);
void _glfwPlatformRemoveTimer(unsigned long long timer_id);
int _glfwPlatformSetWindowBlur(_GLFWwindow* handle, int value);
MonitorGeometry _glfwPlatformGetMonitorGeometry(_GLFWmonitor* monitor);
char* _glfw_strdup(const char* source);

View File

@@ -24,47 +24,15 @@ static int theme_size = -1;
static GLFWColorScheme appearance = GLFW_COLOR_SCHEME_NO_PREFERENCE;
static bool cursor_theme_changed = false, appearance_initialized = false;
#define HANDLER(name_) static void name_(DBusMessage *msg, const DBusError* err, void *data) { \
#define HANDLER(name) static void name(DBusMessage *msg, const char* errmsg, void *data) { \
(void)data; \
if (err) { \
_glfwInputError(GLFW_PLATFORM_ERROR, "%s: failed with error: %s: %s", #name_, err->name, err->message); \
if (errmsg) { \
_glfwInputError(GLFW_PLATFORM_ERROR, "%s: failed with error: %s", #name, errmsg); \
return; \
}
HANDLER(get_color_scheme_legacy)
DBusMessageIter iter, variant_iter, variant_iter2;
if (!dbus_message_iter_init(msg, &iter)) return;
dbus_message_iter_recurse(&iter, &variant_iter);
int type = dbus_message_iter_get_arg_type(&variant_iter);
if (type != DBUS_TYPE_VARIANT) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Read for color-scheme did not return a variant"); return;
}
dbus_message_iter_recurse(&variant_iter, &variant_iter2);
if (type != DBUS_TYPE_VARIANT) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Read for color-scheme did not return a nested variant"); return;
}
uint32_t val;
dbus_message_iter_get_basic(&variant_iter2, &val);
if (val < 3) appearance = val;
}
static void
get_color_scheme(DBusMessage *msg, const DBusError* err, void *data) {
(void) data;
if (err) {
if (strcmp("org.freedesktop.DBus.Error.UnknownMethod", err->name) == 0) {
DBusConnection *session_bus = glfw_dbus_session_bus();
if (session_bus) {
const char *namespace = FDO_DESKTOP_NAMESPACE, *key = FDO_APPEARANCE_KEY;
glfw_dbus_call_blocking_method(session_bus, DESKTOP_SERVICE, DESKTOP_PATH, DESKTOP_INTERFACE, "Read", DBUS_TIMEOUT_USE_DEFAULT,
get_color_scheme_legacy, NULL, DBUS_TYPE_STRING, &namespace, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID);
}
return;
} else {
_glfwInputError(GLFW_PLATFORM_ERROR, "%s: failed with error: %s: %s", "get_color_scheme", err->name, err->message);
return;
}
}
HANDLER(get_color_scheme)
uint32_t val;
DBusMessageIter iter, variant_iter;
if (!dbus_message_iter_init(msg, &iter)) return;

10
glfw/linux_notify.c vendored
View File

@@ -32,9 +32,9 @@ glfw_dbus_set_user_notification_activated_handler(GLFWDBusnotificationactivatedf
}
void
notification_created(DBusMessage *msg, const DBusError* err, void *data) {
if (err) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Notify: Failed to create notification error: %s: %s", err->name, err->message);
notification_created(DBusMessage *msg, const char* errmsg, void *data) {
if (errmsg) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Notify: Failed to create notification error: %s", errmsg);
if (data) free(data);
return;
}
@@ -95,9 +95,9 @@ cancel_user_notification(DBusConnection *session_bus, uint32_t *id) {
}
static void
got_capabilities(DBusMessage *msg, const DBusError* err, void* data UNUSED) {
got_capabilities(DBusMessage *msg, const char* err, void* data UNUSED) {
if (err) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Notify: Failed to get server capabilities error: %s: %s", err->name, err->message);
_glfwInputError(GLFW_PLATFORM_ERROR, "Notify: Failed to get server capabilities error: %s", err);
return;
}
#define check_call(func, err, ...) if (!func(__VA_ARGS__)) { _glfwInputError(GLFW_PLATFORM_ERROR, "Notify: GetCapabilities: %s", err); return; }

15
glfw/monitor.c vendored
View File

@@ -186,8 +186,7 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor)
_glfwFreeGammaArrays(&monitor->currentRamp);
free(monitor->modes);
free((void*)monitor->name);
free((void*)monitor->description);
free(monitor->name);
free(monitor);
}
@@ -394,19 +393,9 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->name ? monitor->name : "";
return monitor->name;
}
GLFWAPI const char* glfwGetMonitorDescription(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->description ? monitor->description : "";
}
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;

View File

@@ -86,7 +86,6 @@
"unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
"staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml",
"staging/xdg-system-bell/xdg-system-bell-v1.xml",
"staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml",
"kwin-blur-v1.xml",
"wlr-layer-shell-unstable-v1.xml"

13
glfw/window.c vendored
View File

@@ -495,10 +495,6 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value)
strncpy(_glfw.hints.window.wl.appId, value,
sizeof(_glfw.hints.window.wl.appId) - 1);
return;
case GLFW_WAYLAND_WINDOW_TAG:
strncpy(_glfw.hints.window.wl.windowTag, value,
sizeof(_glfw.hints.window.wl.windowTag) - 1);
return;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
@@ -555,15 +551,6 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
window->shouldClose = value;
}
GLFWAPI const GLFWLayerShellConfig* glfwGetLayerShellConfig(GLFWwindow* handle) {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(false);
return _glfwPlatformGetLayerShellConfig(window);
}
GLFWAPI bool glfwSetLayerShellConfig(GLFWwindow* handle, const GLFWLayerShellConfig *value) {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);

5
glfw/wl_init.c vendored
View File

@@ -605,8 +605,6 @@ static void registryHandleGlobal(void* data UNUSED,
}
else if (is(xdg_system_bell_v1)) {
_glfw.wl.xdg_system_bell_v1 = wl_registry_bind(registry, name, &xdg_system_bell_v1_interface, 1);
} else if (is(xdg_toplevel_tag_manager_v1)) {
_glfw.wl.xdg_toplevel_tag_manager_v1 = wl_registry_bind(registry, name, &xdg_toplevel_tag_manager_v1_interface, 1);
}
#undef is
}
@@ -718,7 +716,6 @@ get_compositor_missing_capabilities(void) {
C(cursor_shape, wp_cursor_shape_manager_v1); C(layer_shell, zwlr_layer_shell_v1);
C(single_pixel_buffer, wp_single_pixel_buffer_manager_v1); C(preferred_scale, has_preferred_buffer_scale);
C(idle_inhibit, idle_inhibit_manager); C(icon, xdg_toplevel_icon_manager_v1); C(bell, xdg_system_bell_v1);
C(window-tag, xdg_toplevel_tag_manager_v1);
if (_glfw.wl.xdg_wm_base_version < 6) p += snprintf(p, sizeof(buf) - (p - buf), "%s ", "window-state-suspended");
if (_glfw.wl.xdg_wm_base_version < 5) p += snprintf(p, sizeof(buf) - (p - buf), "%s ", "window-capabilities");
#undef C
@@ -897,8 +894,6 @@ void _glfwPlatformTerminate(void)
xdg_toplevel_icon_manager_v1_destroy(_glfw.wl.xdg_toplevel_icon_manager_v1);
if (_glfw.wl.xdg_system_bell_v1)
xdg_system_bell_v1_destroy(_glfw.wl.xdg_system_bell_v1);
if (_glfw.wl.xdg_toplevel_tag_manager_v1)
xdg_toplevel_tag_manager_v1_destroy(_glfw.wl.xdg_toplevel_tag_manager_v1);
if (_glfw.wl.wp_single_pixel_buffer_manager_v1)
wp_single_pixel_buffer_manager_v1_destroy(_glfw.wl.wp_single_pixel_buffer_manager_v1);
if (_glfw.wl.wp_cursor_shape_manager_v1)

24
glfw/wl_monitor.c vendored
View File

@@ -41,15 +41,20 @@ static void outputHandleGeometry(void* data,
int32_t physicalWidth,
int32_t physicalHeight,
int32_t subpixel UNUSED,
const char* make UNUSED,
const char* model UNUSED,
const char* make,
const char* model,
int32_t transform UNUSED)
{
struct _GLFWmonitor *monitor = data;
char name[1024];
monitor->wl.x = x;
monitor->wl.y = y;
monitor->widthMM = physicalWidth;
monitor->heightMM = physicalHeight;
snprintf(name, sizeof(name), "%s %s", make, model);
monitor->name = _glfw_strdup(name);
}
static void outputHandleMode(void* data,
@@ -100,20 +105,15 @@ static void outputHandleName(void* data,
struct wl_output* output UNUSED,
const char* name) {
struct _GLFWmonitor *monitor = data;
if (name) {
if (monitor->name) free((void*)monitor->name);
monitor->name = _glfw_strdup(name);
}
if (name) strncpy(monitor->wl.friendly_name, name, sizeof(monitor->wl.friendly_name)-1);
}
static void outputHandleDescription(void* data,
struct wl_output* output UNUSED,
const char* description) {
struct _GLFWmonitor *monitor = data;
if (description) {
if (monitor->description) free((void*)monitor->description);
monitor->description = _glfw_strdup(description);
}
if (description) strncpy(monitor->wl.description, description, sizeof(monitor->wl.description)-1);
}
static const struct wl_output_listener outputListener = {
@@ -142,8 +142,8 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
return;
}
// The actual name of this output will be set in the handlers.
monitor = _glfwAllocMonitor("unnamed", 0, 0);
// The actual name of this output will be set in the geometry handler.
monitor = _glfwAllocMonitor(NULL, 0, 0);
output = wl_registry_bind(_glfw.wl.registry,
name,

5
glfw/wl_platform.h vendored
View File

@@ -68,7 +68,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
#include "wayland-xdg-toplevel-icon-v1-client-protocol.h"
#include "wayland-xdg-system-bell-v1-client-protocol.h"
#include "wayland-xdg-toplevel-tag-v1-client-protocol.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
@@ -211,7 +210,7 @@ typedef struct _GLFWwindowWayland
double cursorPosX, cursorPosY, allCursorPosX, allCursorPosY;
char* title;
char appId[256], windowTag[256];
char appId[256];
// We need to track the monitors the window spans on to calculate the
// optimal scaling factor.
@@ -341,7 +340,6 @@ typedef struct _GLFWlibraryWayland
struct xdg_activation_v1* xdg_activation_v1;
struct xdg_toplevel_icon_manager_v1* xdg_toplevel_icon_manager_v1;
struct xdg_system_bell_v1* xdg_system_bell_v1;
struct xdg_toplevel_tag_manager_v1* xdg_toplevel_tag_manager_v1;
struct wp_cursor_shape_manager_v1* wp_cursor_shape_manager_v1;
struct wp_cursor_shape_device_v1* wp_cursor_shape_device_v1;
struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1;
@@ -408,6 +406,7 @@ typedef struct _GLFWmonitorWayland
{
struct wl_output* output;
uint32_t name;
char friendly_name[64], description[64];
int currentMode;
int x;

61
glfw/wl_window.c vendored
View File

@@ -971,25 +971,13 @@ find_output_by_name(const char* name) {
if (!name || !name[0]) return NULL;
for (int i = 0; i < _glfw.monitorCount; i++) {
_GLFWmonitor *m = _glfw.monitors[i];
if (strcmp(m->name, name) == 0) return m->wl.output;
if (strcmp(m->wl.friendly_name, name) == 0) return m->wl.output;
}
return NULL;
}
static enum zwlr_layer_shell_v1_layer
get_layer_shell_layer(const _GLFWwindow *window) {
enum zwlr_layer_shell_v1_layer which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; // Default to background
switch (window->wl.layer_shell.config.type) {
case GLFW_LAYER_SHELL_BACKGROUND: case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_PANEL: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; break;
case GLFW_LAYER_SHELL_TOP: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; break;
case GLFW_LAYER_SHELL_OVERLAY: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; break;
}
return which_layer;
}
static void
layer_set_properties(const _GLFWwindow *window, bool during_creation, uint32_t width, uint32_t height) {
layer_set_properties(const _GLFWwindow *window, uint32_t width, uint32_t height) {
#define config window->wl.layer_shell.config
enum zwlr_layer_surface_v1_anchor which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
int exclusive_zone = config.requested_exclusive_zone;
@@ -1028,13 +1016,12 @@ layer_set_properties(const _GLFWwindow *window, bool during_creation, uint32_t w
if (!config.override_exclusive_zone) exclusive_zone = width;
break;
case GLFW_EDGE_CENTER:
break;
case GLFW_EDGE_CENTER_SIZED:
panel_width = width; panel_height = height;
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
break;
case GLFW_EDGE_NONE:
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
panel_width = width; panel_height = height;
panel_width = width;
panel_height = height;
break;
}
}
@@ -1044,7 +1031,6 @@ layer_set_properties(const _GLFWwindow *window, bool during_creation, uint32_t w
zwlr_layer_surface_v1_set_anchor(surface, which_anchor);
zwlr_layer_surface_v1_set_exclusive_zone(surface, exclusive_zone);
zwlr_layer_surface_v1_set_margin(surface, config.requested_top_margin, config.requested_right_margin, config.requested_bottom_margin, config.requested_left_margin);
if (!during_creation) zwlr_layer_surface_v1_set_layer(surface, get_layer_shell_layer(window));
zwlr_layer_surface_v1_set_keyboard_interactivity(surface, focus_policy);
#undef surface
#undef config
@@ -1055,10 +1041,8 @@ calculate_layer_size(_GLFWwindow *window, uint32_t *width, uint32_t *height) {
const GLFWLayerShellConfig *config = &window->wl.layer_shell.config;
GLFWvidmode m = {0};
if (window->wl.monitorsCount) _glfwPlatformGetVideoMode(window->wl.monitors[0], &m);
int monitor_width = m.width, monitor_height = m.height;
const int y_margin = config->requested_bottom_margin + config->requested_top_margin, x_margin = config->requested_left_margin + config->requested_right_margin;
monitor_width = monitor_width > x_margin ? monitor_width - x_margin : 0;
monitor_height = monitor_height > y_margin ? monitor_height - y_margin : 0;
const int monitor_width = MAX(0, m.width - x_margin), monitor_height = MAX(0, m.height - y_margin);
float xscale = (float)config->expected.xscale, yscale = (float)config->expected.yscale;
if (window->wl.window_fully_created) _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
unsigned cell_width, cell_height; double left_edge_spacing, top_edge_spacing, right_edge_spacing, bottom_edge_spacing;
@@ -1070,9 +1054,9 @@ calculate_layer_size(_GLFWwindow *window, uint32_t *width, uint32_t *height) {
if (!*height) *height = monitor_height;
return;
}
debug("Calculating layer shell window size at scale: %f\n", xscale);
const unsigned xsz = config->x_size_in_pixels ? (unsigned)(config->x_size_in_pixels * xscale) : (cell_width * config->x_size_in_cells);
const unsigned ysz = config->y_size_in_pixels ? (unsigned)(config->y_size_in_pixels * yscale) : (cell_height * config->y_size_in_cells);
debug("Calculating layer shell window size at scale: %f cell_size: %u %u sz: %u %u\n", xscale, cell_width, cell_height, xsz, ysz);
if (config->edge == GLFW_EDGE_LEFT || config->edge == GLFW_EDGE_RIGHT) {
if (!*height) *height = monitor_height;
double spacing = spacing_x;
@@ -1092,7 +1076,6 @@ calculate_layer_size(_GLFWwindow *window, uint32_t *width, uint32_t *height) {
*width = (uint32_t)(1. + spacing_x);
*height = (uint32_t)(1. + spacing_y);
}
}
static void
@@ -1105,6 +1088,8 @@ layer_surface_handle_configure(void* data, struct zwlr_layer_surface_v1* surface
window->wl.once.surface_configured = true;
update_fully_created_on_configure(window);
}
GLFWvidmode m = {0};
if (window->wl.monitorsCount) _glfwPlatformGetVideoMode(window->wl.monitors[0], &m);
calculate_layer_size(window, &width, &height);
zwlr_layer_surface_v1_ack_configure(surface, serial);
if ((int)width != window->wl.width || (int)height != window->wl.height) {
@@ -1113,7 +1098,7 @@ layer_surface_handle_configure(void* data, struct zwlr_layer_surface_v1* surface
window->wl.width = width; window->wl.height = height;
resizeFramebuffer(window);
_glfwInputWindowDamage(window);
layer_set_properties(window, false, window->wl.width, window->wl.height);
layer_set_properties(window, window->wl.width, window->wl.height);
if (window->wl.wp_viewport) wp_viewport_set_destination(window->wl.wp_viewport, window->wl.width, window->wl.height);
}
commit_window_surface_if_safe(window);
@@ -1142,15 +1127,22 @@ create_layer_shell_surface(_GLFWwindow *window) {
}
window->decorated = false; // shell windows must not have decorations
struct wl_output *wl_output = find_output_by_name(window->wl.layer_shell.config.output_name);
enum zwlr_layer_shell_v1_layer which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; // Default to background
switch (window->wl.layer_shell.config.type) {
case GLFW_LAYER_SHELL_BACKGROUND: break; case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_PANEL: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; break;
case GLFW_LAYER_SHELL_TOP: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; break;
case GLFW_LAYER_SHELL_OVERLAY: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; break;
}
#define ls window->wl.layer_shell.zwlr_layer_surface_v1
ls = zwlr_layer_shell_v1_get_layer_surface(
_glfw.wl.zwlr_layer_shell_v1, window->wl.surface, wl_output, get_layer_shell_layer(window), window->wl.appId[0] ? window->wl.appId : "kitty");
_glfw.wl.zwlr_layer_shell_v1, window->wl.surface, wl_output, which_layer, "kitty");
if (!ls) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: layer-surface creation failed");
return false;
}
zwlr_layer_surface_v1_add_listener(ls, &zwlr_layer_surface_v1_listener, window);
layer_set_properties(window, true, window->wl.width, window->wl.height);
layer_set_properties(window, window->wl.width, window->wl.height);
if (window->wl.wp_viewport) wp_viewport_set_destination(window->wl.wp_viewport, window->wl.width, window->wl.height);
commit_window_surface(window);
wl_display_roundtrip(_glfw.wl.display);
@@ -1198,10 +1190,8 @@ create_window_desktop_surface(_GLFWwindow* window)
zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration, &xdgDecorationListener, window);
}
if (window->wl.appId[0])
if (strlen(window->wl.appId))
xdg_toplevel_set_app_id(window->wl.xdg.toplevel, window->wl.appId);
if (window->wl.windowTag[0] && _glfw.wl.xdg_toplevel_tag_manager_v1)
xdg_toplevel_tag_manager_v1_set_toplevel_tag(_glfw.wl.xdg_toplevel_tag_manager_v1, window->wl.xdg.toplevel, window->wl.windowTag);
if (window->wl.title)
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
@@ -1737,7 +1727,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
window->wl.visible = true;
} else {
// workaround for kwin layer shell bug: https://bugs.kde.org/show_bug.cgi?id=503121
if (is_layer_shell(window)) layer_set_properties(window, false, window->wl.width, window->wl.height);
if (is_layer_shell(window)) layer_set_properties(window, window->wl.width, window->wl.height);
window->wl.visible = true;
commit_window_surface(window);
}
@@ -1762,7 +1752,7 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
if (value) window->wl.layer_shell.config = *value;
uint32_t width, height;
calculate_layer_size(window, &width, &height);
layer_set_properties(window, false, width, height);
layer_set_properties(window, width, height);
commit_window_surface(window);
return true;
}
@@ -2895,12 +2885,11 @@ GLFWAPI void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) {
if (csd_change_title(window)) commit_window_surface_if_safe(window);
}
const GLFWLayerShellConfig*
_glfwPlatformGetLayerShellConfig(_GLFWwindow *window) {
return &window->wl.layer_shell.config;
GLFWAPI GLFWLayerShellConfig* glfwWaylandLayerShellConfig(GLFWwindow *handle) {
return &((_GLFWwindow*)handle)->wl.layer_shell.config;
}
GLFWAPI bool glfwIsLayerShellSupported(void) { return _glfw.wl.zwlr_layer_shell_v1 != NULL; }
GLFWAPI bool glfwWaylandIsLayerShellSupported(void) { return _glfw.wl.zwlr_layer_shell_v1 != NULL; }
GLFWAPI bool glfwWaylandIsWindowFullyCreated(GLFWwindow *handle) { return handle != NULL && ((_GLFWwindow*)handle)->wl.window_fully_created; }

72
glfw/x11_init.c vendored
View File

@@ -47,11 +47,16 @@
//
static Atom getAtomIfSupported(Atom* supportedAtoms,
unsigned long atomCount,
const Atom atom)
const char* atomName)
{
for (unsigned long i = 0; i < atomCount; i++) {
if (supportedAtoms[i] == atom) return atom;
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
for (unsigned long i = 0; i < atomCount; i++)
{
if (supportedAtoms[i] == atom)
return atom;
}
return None;
}
@@ -115,36 +120,39 @@ static void detectEWMH(void)
// See which of the atoms we support that are supported by the WM
#define ALL_ATOMS \
S(NET_WM_STATE) S(NET_WM_STATE_ABOVE) S(NET_WM_STATE_BELOW) S(NET_WM_STATE_FULLSCREEN) \
S(NET_WM_STATE_MAXIMIZED_VERT) S(NET_WM_STATE_MAXIMIZED_HORZ) S(NET_WM_STATE_DEMANDS_ATTENTION) \
S(NET_WM_STATE_SKIP_TASKBAR) S(NET_WM_STATE_SKIP_PAGER) S(NET_WM_STATE_STICKY) \
\
S(NET_WM_FULLSCREEN_MONITORS) S(NET_WM_STRUT_PARTIAL) \
\
S(NET_WM_WINDOW_TYPE) S(NET_WM_WINDOW_TYPE_NORMAL) S(NET_WM_WINDOW_TYPE_DOCK) S(NET_WM_WINDOW_TYPE_DESKTOP) \
S(NET_WM_WINDOW_TYPE_UTILITY) S(NET_WM_WINDOW_TYPE_SPLASH) S(NET_WM_WINDOW_TYPE_DIALOG) S(NET_WM_WINDOW_TYPE_MENU) \
S(NET_WM_WINDOW_TYPE_NOTIFICATION) \
\
S(NET_WORKAREA) S(NET_CURRENT_DESKTOP) S(NET_ACTIVE_WINDOW) S(NET_FRAME_EXTENTS) S(NET_REQUEST_FRAME_EXTENTS) \
\
S(NET_WM_ALLOWED_ACTIONS) S(NET_WM_ACTION_MOVE) S(NET_WM_ACTION_RESIZE) S(NET_WM_ACTION_MINIMIZE) \
S(NET_WM_ACTION_SHADE) S(NET_WM_ACTION_STICK) S(NET_WM_ACTION_MAXIMIZE_HORZ) S(NET_WM_ACTION_MAXIMIZE_VERT) \
S(NET_WM_ACTION_FULLSCREEN) S(NET_WM_ACTION_CHANGE_DESKTOP) S(NET_WM_ACTION_CLOSE) S(NET_WM_ACTION_ABOVE) \
S(NET_WM_ACTION_BELOW) S(NET_WM_ACTION_ABOVE_BELOW)
_glfw.x11.NET_WM_STATE =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE");
_glfw.x11.NET_WM_STATE_ABOVE =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
_glfw.x11.NET_WM_STATE_FULLSCREEN =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
_glfw.x11.NET_WM_FULLSCREEN_MONITORS =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
_glfw.x11.NET_WM_WINDOW_TYPE =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
_glfw.x11.NET_WM_WINDOW_TYPE_DOCK =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_DOCK");
_glfw.x11.NET_WORKAREA =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WORKAREA");
_glfw.x11.NET_CURRENT_DESKTOP =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
_glfw.x11.NET_ACTIVE_WINDOW =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
_glfw.x11.NET_FRAME_EXTENTS =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
_glfw.x11.NET_WM_STRUT_PARTIAL =
getAtomIfSupported(supportedAtoms, atomCount, "_NET_WM_STRUT_PARTIAL");
static const char* atom_names[40] = {
#define S(x) "_" #x,
ALL_ATOMS
};
#undef S
Atom atoms[arraysz(atom_names)];
XInternAtoms(_glfw.x11.display, (char**)atom_names, arraysz(atom_names), False, atoms);
unsigned i = 0;
#define S(name) _glfw.x11.name = getAtomIfSupported(supportedAtoms, atomCount, atoms[i++]);
ALL_ATOMS
#undef S
#undef ALL_ATOMS
XFree(supportedAtoms);
}

103
glfw/x11_monitor.c vendored
View File

@@ -350,79 +350,96 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor UNUSED,
*yscale = _glfw.x11.contentScaleY;
}
MonitorGeometry
_glfwPlatformGetMonitorGeometry(_GLFWmonitor *monitor) {
MonitorGeometry ans = {0};
if (!monitor) return ans;
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) {
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
{
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{
XRRScreenResources* sr =
XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
ans.full.x = ci->x;
ans.full.y = ci->y;
areaX = ci->x;
areaY = ci->y;
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) {
ans.full.width = mi->height;
ans.full.height = mi->width;
} else {
ans.full.width = mi->width;
ans.full.height = mi->height;
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
{
areaWidth = mi->height;
areaHeight = mi->width;
}
else
{
areaWidth = mi->width;
areaHeight = mi->height;
}
XRRFreeCrtcInfo(ci);
XRRFreeScreenResources(sr);
} else {
ans.full.width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
ans.full.height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
}
ans.workarea = *(&ans.full);
else
{
areaWidth = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
}
if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP) {
if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
{
Atom* extents = NULL;
Atom* desktop = NULL;
const unsigned long extentCount = _glfwGetWindowPropertyX11(
_glfw.x11.root, _glfw.x11.NET_WORKAREA, XA_CARDINAL, (unsigned char**) &extents);
const unsigned long extentCount =
_glfwGetWindowPropertyX11(_glfw.x11.root,
_glfw.x11.NET_WORKAREA,
XA_CARDINAL,
(unsigned char**) &extents);
if (_glfwGetWindowPropertyX11(_glfw.x11.root, _glfw.x11.NET_CURRENT_DESKTOP, XA_CARDINAL, (unsigned char**) &desktop) > 0) {
if (extentCount >= 4 && *desktop < extentCount / 4) {
if (_glfwGetWindowPropertyX11(_glfw.x11.root,
_glfw.x11.NET_CURRENT_DESKTOP,
XA_CARDINAL,
(unsigned char**) &desktop) > 0)
{
if (extentCount >= 4 && *desktop < extentCount / 4)
{
const int globalX = extents[*desktop * 4 + 0];
const int globalY = extents[*desktop * 4 + 1];
const int globalWidth = extents[*desktop * 4 + 2];
const int globalHeight = extents[*desktop * 4 + 3];
if (ans.workarea.x < globalX) {
ans.workarea.width -= globalX - ans.workarea.x;
ans.workarea.x = globalX;
if (areaX < globalX)
{
areaWidth -= globalX - areaX;
areaX = globalX;
}
if (ans.workarea.y < globalY) {
ans.workarea.height -= globalY - ans.workarea.y;
ans.workarea.y = globalY;
if (areaY < globalY)
{
areaHeight -= globalY - areaY;
areaY = globalY;
}
if (ans.workarea.x + ans.workarea.width > globalX + globalWidth)
ans.workarea.width = globalX - ans.workarea.x + globalWidth;
if (ans.workarea.y + ans.workarea.height > globalY + globalHeight)
ans.workarea.height = globalY - ans.workarea.y + globalHeight;
if (areaX + areaWidth > globalX + globalWidth)
areaWidth = globalX - areaX + globalWidth;
if (areaY + areaHeight > globalY + globalHeight)
areaHeight = globalY - areaY + globalHeight;
}
}
if (extents) XFree(extents);
if (desktop) XFree(desktop);
}
return ans;
}
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height) {
MonitorGeometry ans = _glfwPlatformGetMonitorGeometry(monitor);
if (extents)
XFree(extents);
if (desktop)
XFree(desktop);
}
if (xpos)
*xpos = ans.workarea.x;
*xpos = areaX;
if (ypos)
*ypos = ans.workarea.y;
*ypos = areaY;
if (width)
*width = ans.workarea.width;
*width = areaWidth;
if (height)
*height = ans.workarea.height;
*height = areaHeight;
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)

13
glfw/x11_platform.h vendored
View File

@@ -205,10 +205,6 @@ typedef struct _GLFWwindowX11
// The last position the cursor was warped to by GLFW
int warpCursorPosX, warpCursorPosY;
struct {
bool is_active;
GLFWLayerShellConfig config;
} layer_shell;
} _GLFWwindowX11;
typedef struct MimeAtom {
@@ -251,22 +247,19 @@ typedef struct _GLFWlibraryX11
Atom WM_STATE;
Atom WM_DELETE_WINDOW;
Atom NET_WM_NAME;
Atom NET_WM_ALLOWED_ACTIONS, NET_WM_ACTION_MOVE, NET_WM_ACTION_RESIZE, NET_WM_ACTION_MINIMIZE, NET_WM_ACTION_SHADE, NET_WM_ACTION_STICK, NET_WM_ACTION_MAXIMIZE_HORZ, NET_WM_ACTION_MAXIMIZE_VERT, NET_WM_ACTION_FULLSCREEN, NET_WM_ACTION_CHANGE_DESKTOP, NET_WM_ACTION_CLOSE, NET_WM_ACTION_ABOVE, NET_WM_ACTION_BELOW, NET_WM_ACTION_ABOVE_BELOW;
Atom NET_WM_ICON_NAME;
Atom NET_WM_ICON;
Atom NET_WM_PID;
Atom NET_WM_PING;
Atom NET_WM_WINDOW_TYPE, NET_WM_WINDOW_TYPE_NORMAL, NET_WM_WINDOW_TYPE_DOCK, NET_WM_WINDOW_TYPE_DESKTOP, NET_WM_WINDOW_TYPE_UTILITY, NET_WM_WINDOW_TYPE_SPLASH, NET_WM_WINDOW_TYPE_DIALOG, NET_WM_WINDOW_TYPE_MENU, NET_WM_WINDOW_TYPE_NOTIFICATION;
Atom NET_WM_WINDOW_TYPE;
Atom NET_WM_WINDOW_TYPE_NORMAL;
Atom NET_WM_WINDOW_TYPE_DOCK;
Atom NET_WM_STATE;
Atom NET_WM_STATE_ABOVE;
Atom NET_WM_STATE_BELOW;
Atom NET_WM_STATE_FULLSCREEN;
Atom NET_WM_STATE_MAXIMIZED_VERT;
Atom NET_WM_STATE_MAXIMIZED_HORZ;
Atom NET_WM_STATE_DEMANDS_ATTENTION;
Atom NET_WM_STATE_SKIP_TASKBAR;
Atom NET_WM_STATE_SKIP_PAGER;
Atom NET_WM_STATE_STICKY;
Atom NET_WM_BYPASS_COMPOSITOR;
Atom NET_WM_FULLSCREEN_MONITORS;
Atom NET_WM_WINDOW_OPACITY;

305
glfw/x11_window.c vendored
View File

@@ -530,204 +530,19 @@ static void enableCursor(_GLFWwindow* window)
updateCursorImage(window);
}
typedef unsigned long strut_type;
typedef struct WindowGeometry {
int x, y, width, height;
bool needs_strut;
strut_type struts[12];
} WindowGeometry;
#define config (window->x11.layer_shell.config)
static _GLFWmonitor*
find_monitor_by_name(const char* name) {
if (!name || !name[0]) return (_GLFWmonitor*)glfwGetPrimaryMonitor();;
for (int i = 0; i < _glfw.monitorCount; i++) {
_GLFWmonitor *m = _glfw.monitors[i];
if (strcmp(m->name, name) == 0) return m;
}
return (_GLFWmonitor*)glfwGetPrimaryMonitor();;
}
static WindowGeometry
calculate_layer_geometry(_GLFWwindow *window) {
_GLFWmonitor *monitor = find_monitor_by_name(config.output_name);
MonitorGeometry mg = _glfwPlatformGetMonitorGeometry((_GLFWmonitor*)glfwGetPrimaryMonitor());
WindowGeometry ans = {0};
debug_rendering("Monitor: %s full: %dx%d@%dx%d workarea: %dx%d@%dx%d\n", monitor->name,
mg.full.width, mg.full.height, mg.full.x, mg.full.y, mg.workarea.width, mg.workarea.height, mg.workarea.x, mg.workarea.y);
ans.width = mg.full.width; ans.height = mg.full.height;
ans.x = mg.full.x; ans.y = mg.full.y;
ans.needs_strut = config.type == GLFW_LAYER_SHELL_PANEL;
if (config.type == GLFW_LAYER_SHELL_BACKGROUND) {
ans.x += config.requested_left_margin; ans.y += config.requested_top_margin;
ans.width -= config.requested_left_margin + config.requested_right_margin;
ans.height -= config.requested_top_margin + config.requested_bottom_margin;
return ans;
}
float xscale = (float)config.expected.xscale, yscale = (float)config.expected.yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
unsigned cell_width, cell_height; double left_edge_spacing, top_edge_spacing, right_edge_spacing, bottom_edge_spacing;
config.size_callback((GLFWwindow*)window, xscale, yscale, &cell_width, &cell_height, &left_edge_spacing, &top_edge_spacing, &right_edge_spacing, &bottom_edge_spacing);
double spacing_x = left_edge_spacing + right_edge_spacing;
double spacing_y = top_edge_spacing + bottom_edge_spacing;
double xsz = config.x_size_in_pixels ? (unsigned)(config.x_size_in_pixels * xscale) : (cell_width * config.x_size_in_cells);
double ysz = config.y_size_in_pixels ? (unsigned)(config.y_size_in_pixels * yscale) : (cell_height * config.y_size_in_cells);
ans.width = (int)(1. + spacing_x + xsz); ans.height = (int)(1. + spacing_y + ysz);
GeometryRect m = config.type == GLFW_LAYER_SHELL_TOP || config.type == GLFW_LAYER_SHELL_OVERLAY ? mg.workarea : mg.full;
static const struct {
unsigned left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x;
} s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
switch (config.edge) {
case GLFW_EDGE_LEFT:
ans.x = m.x + config.requested_left_margin;
ans.y = m.y + config.requested_top_margin;
ans.height = m.height - config.requested_bottom_margin - config.requested_top_margin;
ans.struts[s.left] = ans.width; ans.struts[s.left_end_y] = ans.height;
break;
case GLFW_EDGE_RIGHT:
ans.x = m.x + m.width - config.requested_right_margin - ans.width;
ans.y = m.y + config.requested_top_margin;
ans.height = m.height - config.requested_bottom_margin - config.requested_top_margin;
ans.struts[s.right] = ans.width; ans.struts[s.right_end_y] = ans.height;
break;
case GLFW_EDGE_TOP:
ans.x = m.x + config.requested_left_margin;
ans.y = m.y + config.requested_top_margin;
ans.width = m.width - config.requested_right_margin - config.requested_left_margin;
ans.struts[s.top] = ans.height; ans.struts[s.top_end_x] = ans.width;
break;
case GLFW_EDGE_BOTTOM:
ans.x = m.x + config.requested_left_margin;
ans.y = m.height - config.requested_bottom_margin - ans.height;
ans.width = m.width - config.requested_right_margin - config.requested_left_margin;
ans.struts[s.bottom] = ans.height; ans.struts[s.bottom_end_x] = ans.width;
break;
case GLFW_EDGE_CENTER_SIZED:
ans.needs_strut = false;
ans.x = (m.width - ans.width) / 2;
ans.y = (m.height - ans.height) / 2;
break;
default:
ans.needs_strut = false;
ans.x = m.x + config.requested_left_margin;
ans.y = m.y + config.requested_top_margin;
ans.height = m.height - config.requested_bottom_margin - config.requested_top_margin;
ans.width = m.width - config.requested_right_margin - config.requested_left_margin;
break;
}
debug_rendering("Calculating layer geometry at scale: %f cell size: (%u, %u) -> %dx%d@%dx%d needs_strut: %d\n",
xscale, cell_width, cell_height, ans.width, ans.height, ans.x, ans.y, ans.needs_strut)
return ans;
}
GLFWAPI bool glfwIsLayerShellSupported(void) { return _glfw.x11.NET_WM_WINDOW_TYPE != 0 && _glfw.x11.NET_WM_STATE != 0; }
static bool
update_wm_hints(_GLFWwindow *window, const WindowGeometry *wg, const _GLFWwndconfig *wndconfig) {
XWMHints* hints = XAllocWMHints();
bool is_layer_shell = window->x11.layer_shell.is_active;
bool ok = false;
if (hints) {
ok = true;
hints->flags = StateHint | InputHint;
hints->initial_state = NormalState;
hints->input = true;
if (is_layer_shell && config.focus_policy == GLFW_FOCUS_NOT_ALLOWED) hints->input = false;
XSetWMHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
} else _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate WM hints");
if (_glfw.x11.NET_WM_WINDOW_TYPE) {
Atom type = 0;
if (is_layer_shell) {
const char *name = NULL;
#define S(which) type = _glfw.x11.which; name = #which
switch (config.type) {
case GLFW_LAYER_SHELL_BACKGROUND: S(NET_WM_WINDOW_TYPE_DESKTOP); break;
case GLFW_LAYER_SHELL_PANEL: S(NET_WM_WINDOW_TYPE_DOCK); break;
default: S(NET_WM_WINDOW_TYPE_NORMAL); break;
}
#undef S
if (!type) {
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Window manager does not support _%s", name);
ok = false;
}
} else if (_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL) type = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL;
if (type) XChangeProperty(
_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char*) &type, 1);
} else if (is_layer_shell) {
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Window manager does not support _NET_WM_WINDOW_TYPE");
ok = false;
}
if (is_layer_shell) {
if (_glfw.x11.NET_WM_STRUT_PARTIAL) {
XChangeProperty(
_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_STRUT_PARTIAL, XA_CARDINAL, 32, PropModeReplace,
(unsigned char*)(wg->needs_strut ? wg->struts : (strut_type[12]){0}), 12);
} else if (wg->needs_strut) {
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Window manager does not support _NET_WM_STRUT_PARTIAL");
ok = false;
}
}
if (ok) {
updateNormalHints(window, wg->width, wg->height);
Atom states[8]; unsigned count = 0;
if (is_layer_shell) {
_glfwPlatformSetWindowDecorated(window, false);
if (_glfw.x11.NET_WM_STATE_STICKY) states[count++] = _glfw.x11.NET_WM_STATE_STICKY;
if (_glfw.x11.NET_WM_STATE_SKIP_PAGER) states[count++] = _glfw.x11.NET_WM_STATE_SKIP_PAGER;
if (_glfw.x11.NET_WM_STATE_SKIP_TASKBAR) states[count++] = _glfw.x11.NET_WM_STATE_SKIP_TASKBAR;
#define S(x) if (_glfw.x11.x) { states[count++] = _glfw.x11.x; } else { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Window manager does not support _%s", #x); ok = false; }
switch (config.type) {
case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_BACKGROUND: S(NET_WM_STATE_BELOW); break;
case GLFW_LAYER_SHELL_PANEL:
// i3 does not support NET_WM_STATE_BELOW but panels work without it
if (_glfw.x11.NET_WM_STATE_BELOW) { S(NET_WM_STATE_BELOW); }
break;
case GLFW_LAYER_SHELL_TOP: case GLFW_LAYER_SHELL_OVERLAY: S(NET_WM_STATE_ABOVE); break;
}
#undef S
} else if (wndconfig) {
if (!wndconfig->decorated) _glfwPlatformSetWindowDecorated(window, false);
if (_glfw.x11.NET_WM_STATE && !window->monitor) {
if (wndconfig->floating) {
if (_glfw.x11.NET_WM_STATE_ABOVE) states[count++] = _glfw.x11.NET_WM_STATE_ABOVE;
}
if (wndconfig->maximized) {
if (_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT && _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ) {
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
window->x11.maximized = true;
}
}
}
}
if (count && _glfw.x11.NET_WM_STATE) XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_STATE,
XA_ATOM, 32, PropModeReplace, (unsigned char*) states, count);
}
if (!wndconfig && ok) {
_glfwPlatformSetWindowPos(window, wg->x, wg->y);
_glfwPlatformSetWindowSize(window, wg->width, wg->height);
}
return ok;
#undef config
}
// Create the X11 window (and its colormap)
//
static bool createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
Visual* visual, int depth)
{
WindowGeometry wg = {.width=wndconfig->width, .height=wndconfig->height};
if (window->x11.layer_shell.is_active) {
wg = calculate_layer_geometry(window);
window->resizable = false;
int width = wndconfig->width;
int height = wndconfig->height;
if (wndconfig->scaleToMonitor)
{
width *= (int)_glfw.x11.contentScaleX;
height *= (int)_glfw.x11.contentScaleY;
}
// Create a colormap based on the visual used by the current context
@@ -748,11 +563,10 @@ static bool createNativeWindow(_GLFWwindow* window,
_glfwGrabErrorHandlerX11();
window->x11.parent = _glfw.x11.root;
debug_rendering("Creating window with geometry: %dx%d@%dx%d\n", wg.width, wg.height, wg.x, wg.y);
window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root,
wg.x, wg.y, // Position
wg.width, wg.height,
0, 0, // Position
width, height,
0, // Border width
depth, // Color depth
InputOutput,
@@ -774,6 +588,39 @@ static bool createNativeWindow(_GLFWwindow* window,
_glfw.x11.context,
(XPointer) window);
if (!wndconfig->decorated)
_glfwPlatformSetWindowDecorated(window, false);
if (_glfw.x11.NET_WM_STATE && !window->monitor)
{
Atom states[3];
int count = 0;
if (wndconfig->floating)
{
if (_glfw.x11.NET_WM_STATE_ABOVE)
states[count++] = _glfw.x11.NET_WM_STATE_ABOVE;
}
if (wndconfig->maximized)
{
if (_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
{
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
window->x11.maximized = true;
}
}
if (count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) states, count);
}
}
// Declare the WM protocols supported by GLFW
{
Atom protocols[] =
@@ -796,9 +643,32 @@ static bool createNativeWindow(_GLFWwindow* window,
(unsigned char*) &pid, 1);
}
if (!update_wm_hints(window, &wg, wndconfig)) return false;
// without this floating window position is incorrect on KDE
if (window->x11.layer_shell.is_active) _glfwPlatformSetWindowPos(window, wg.x, wg.y);
if (_glfw.x11.NET_WM_WINDOW_TYPE && _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL)
{
Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &type, 1);
}
// Set ICCCM WM_HINTS property
{
XWMHints* hints = XAllocWMHints();
if (!hints)
{
_glfwInputError(GLFW_OUT_OF_MEMORY,
"X11: Failed to allocate WM hints");
return false;
}
hints->flags = StateHint;
hints->initial_state = NormalState;
XSetWMHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
}
updateNormalHints(window, width, height);
// Set ICCCM WM_CLASS property
{
@@ -1561,7 +1431,6 @@ static void processEvent(XEvent *event)
if (event->xconfigure.width != window->x11.width ||
event->xconfigure.height != window->x11.height)
{
debug_rendering("Window resized to: %d %d from: %d %d\n", event->xconfigure.width, event->xconfigure.height, window->x11.width, window->x11.height);
_glfwInputFramebufferSize(window,
event->xconfigure.width,
event->xconfigure.height);
@@ -1596,9 +1465,9 @@ static void processEvent(XEvent *event)
return;
}
}
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
{
debug_rendering("Window moved to: %d %d from: %d %d\n", xpos, ypos, window->x11.xpos, window->x11.xpos);
_glfwInputWindowPos(window, xpos, ypos);
window->x11.xpos = xpos;
window->x11.ypos = ypos;
@@ -2000,12 +1869,9 @@ void _glfwPushSelectionToManagerX11(void)
int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig, const GLFWLayerShellConfig *lsc)
{
(void)lsc;
Visual* visual = NULL;
int depth;
if (lsc) {
window->x11.layer_shell.is_active = true;
window->x11.layer_shell.config = *lsc;
} else window->x11.layer_shell.is_active = false;
if (ctxconfig->client != GLFW_NO_API)
{
@@ -2097,16 +1963,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
XFlush(_glfw.x11.display);
}
const GLFWLayerShellConfig*
_glfwPlatformGetLayerShellConfig(_GLFWwindow *window) {
return &window->x11.layer_shell.config;
}
bool
_glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig *value) {
if (value) window->x11.layer_shell.config = *value;
WindowGeometry wg = calculate_layer_geometry(window);
update_wm_hints(window, &wg, NULL);
bool _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig *value) {
(void)window; (void)value;
return false;
}
@@ -2463,11 +2321,6 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
return;
XMapWindow(_glfw.x11.display, window->x11.handle);
// without this floating window position is incorrect on KDE
if (window->x11.layer_shell.is_active) {
WindowGeometry wg = calculate_layer_geometry(window);
_glfwPlatformSetWindowPos(window, wg.x, wg.y);
}
waitForVisibilityNotify(window);
}
@@ -3420,4 +3273,18 @@ GLFWAPI int glfwSetX11LaunchCommand(GLFWwindow *handle, char **argv, int argc)
return XSetCommand(_glfw.x11.display, window->x11.handle, argv, argc);
}
GLFWAPI void glfwSetX11WindowAsDock(int32_t x11_window_id) {
_GLFW_REQUIRE_INIT();
Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_DOCK;
XChangeProperty(_glfw.x11.display, x11_window_id,
_glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &type, 1);
}
GLFWAPI void glfwSetX11WindowStrut(int32_t x11_window_id, uint32_t dimensions[12]) {
_GLFW_REQUIRE_INIT();
XChangeProperty(_glfw.x11.display, x11_window_id,
_glfw.x11.NET_WM_STRUT_PARTIAL, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*) dimensions, 12);
}

8
go.mod
View File

@@ -1,4 +1,4 @@
module github.com/kovidgoyal/kitty
module kitty
go 1.23.0
@@ -6,7 +6,7 @@ toolchain go1.24.1
require (
github.com/ALTree/bigfloat v0.2.0
github.com/alecthomas/chroma/v2 v2.17.2
github.com/alecthomas/chroma/v2 v2.17.0
github.com/bmatcuk/doublestar/v4 v4.8.1
github.com/dlclark/regexp2 v1.11.5
github.com/edwvee/exiffix v0.0.0-20240229113213-0dbb146775be
@@ -17,8 +17,8 @@ require (
github.com/shirou/gopsutil/v3 v3.24.5
github.com/zeebo/xxh3 v1.0.2
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b
golang.org/x/image v0.27.0
golang.org/x/sys v0.33.0
golang.org/x/image v0.26.0
golang.org/x/sys v0.32.0
howett.net/plist v1.0.1
)

12
go.sum
View File

@@ -2,8 +2,8 @@ github.com/ALTree/bigfloat v0.2.0 h1:AwNzawrpFuw55/YDVlcPw0F0cmmXrmngBHhVrvdXPvM
github.com/ALTree/bigfloat v0.2.0/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI=
github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
github.com/alecthomas/chroma/v2 v2.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI=
github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
@@ -63,15 +63,15 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI=
golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=

View File

@@ -4,13 +4,13 @@ package ask
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/cli/markup"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/style"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"io"
"kitty/tools/cli/markup"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/style"
"kitty/tools/wcswidth"
"os"
"regexp"
"strings"

View File

@@ -9,9 +9,9 @@ import (
"path/filepath"
"time"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/readline"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -6,9 +6,9 @@ import (
"errors"
"fmt"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/cli/markup"
"github.com/kovidgoyal/kitty/tools/tui"
"kitty/tools/cli"
"kitty/tools/cli/markup"
"kitty/tools/tui"
)
var _ = fmt.Print

View File

@@ -10,7 +10,7 @@ import (
"sync"
"time"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -9,10 +9,10 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/tui"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -5,8 +5,8 @@ import (
"math"
"sync"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -2,10 +2,10 @@ package choose_fonts
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/subseq"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/tui"
"kitty/tools/tui/subseq"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -5,9 +5,9 @@ import (
"path/filepath"
"strings"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/config"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -4,9 +4,9 @@ import (
"fmt"
"strings"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tui/graphics"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -5,10 +5,10 @@ import (
"strconv"
"strings"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/readline"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tui"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -5,11 +5,11 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/readline"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/style"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
"kitty/tools/utils/style"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -4,9 +4,9 @@ import (
"fmt"
"os"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"kitty/tools/cli"
"kitty/tools/tty"
"kitty/tools/tui/loop"
)
var _ = fmt.Print

View File

@@ -2,7 +2,7 @@ package choose_fonts
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/utils"
"slices"
"strings"
)

View File

@@ -7,8 +7,8 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/shlex"
"kitty/tools/utils"
"kitty/tools/utils/shlex"
)
var _ = fmt.Print

View File

@@ -6,10 +6,10 @@ import (
"strconv"
"sync"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tui"
"kitty/tools/tui/graphics"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -11,9 +11,9 @@ import (
"os"
"strings"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -5,7 +5,7 @@ package clipboard
import (
"os"
"github.com/kovidgoyal/kitty/tools/cli"
"kitty/tools/cli"
)
func run_mime_loop(opts *Options, args []string) (err error) {

View File

@@ -14,10 +14,10 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/images"
)
var _ = fmt.Print
@@ -201,7 +201,7 @@ func unescape_metadata_value(k, x string) (ans string) {
return x
}
func Encode_bytes(metadata map[string]string, payload []byte) string {
func encode_bytes(metadata map[string]string, payload []byte) string {
ans := strings.Builder{}
enc_payload := ""
if len(payload) > 0 {
@@ -228,7 +228,7 @@ func Encode_bytes(metadata map[string]string, payload []byte) string {
}
func encode(metadata map[string]string, payload string) string {
return Encode_bytes(metadata, utils.UnsafeStringToBytes(payload))
return encode_bytes(metadata, utils.UnsafeStringToBytes(payload))
}
func error_from_status(status string) error {

View File

@@ -8,11 +8,10 @@ import (
"io"
"os"
"path/filepath"
"slices"
"strings"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print
@@ -38,7 +37,12 @@ func (self *Input) has_mime_matching(predicate func(string) bool) bool {
if predicate(self.mime_type) {
return true
}
return slices.ContainsFunc(self.extra_mime_types, predicate)
for _, i := range self.extra_mime_types {
if predicate(i) {
return true
}
}
return false
}
func write_loop(inputs []*Input, opts *Options) (err error) {
@@ -95,7 +99,7 @@ func write_loop(inputs []*Input, opts *Options) (err error) {
i := inputs[0]
n, err := i.src.Read(buf[:])
if n > 0 {
waiting_for_write = lp.QueueWriteString(Encode_bytes(make_metadata("wdata", i.mime_type), buf[:n]))
waiting_for_write = lp.QueueWriteString(encode_bytes(make_metadata("wdata", i.mime_type), buf[:n]))
}
if err != nil {
if errors.Is(err, io.EOF) {

View File

@@ -11,7 +11,7 @@ import (
"strings"
"unicode/utf8"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -9,7 +9,7 @@ import (
"strings"
"testing"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/utils"
"github.com/google/go-cmp/cmp"
)

View File

@@ -11,8 +11,8 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"kitty/tools/utils"
"kitty/tools/utils/images"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/lexers"

View File

@@ -6,18 +6,17 @@ import (
"archive/tar"
"bytes"
"fmt"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/kovidgoyal/kitty/kittens/ssh"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/kittens/ssh"
"kitty/tools/cli"
"kitty/tools/config"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print
@@ -37,33 +36,16 @@ var conf *Config
var opts *Options
var lp *loop.Loop
var temp_files []string
func resolve_path(path string) (ans string, is_dir bool, err error) {
var s fs.FileInfo
if s, err = os.Stat(path); err != nil {
return
} else {
if s.Mode()&fs.ModeNamedPipe != 0 {
var src, dest *os.File
if src, err = os.Open(path); err != nil {
return
}
defer src.Close()
if dest, err = os.CreateTemp("", fmt.Sprintf("*-pipe-%s", filepath.Base(path))); err != nil {
return
}
defer dest.Close()
temp_files = append(temp_files, dest.Name())
if _, err = io.Copy(dest, src); err != nil {
return
}
return dest.Name(), false, nil
} else {
return path, s.IsDir(), nil
}
func isdir(path string) bool {
if s, err := os.Stat(path); err == nil {
return s.IsDir()
}
return false
}
func exists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func get_ssh_file(hostname, rpath string) (string, error) {
@@ -151,22 +133,15 @@ func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) {
if err != nil {
return 1, err
}
defer func() {
for _, path := range temp_files {
os.Remove(path)
}
}()
var left_is_dir, right_is_dir bool
if left, left_is_dir, err = resolve_path(left); err != nil {
return 1, err
}
if right, right_is_dir, err = resolve_path(right); err != nil {
return 1, err
}
if left_is_dir != right_is_dir {
if isdir(left) != isdir(right) {
return 1, fmt.Errorf("The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.'")
}
if !exists(left) {
return 1, fmt.Errorf("%s does not exist", left)
}
if !exists(right) {
return 1, fmt.Errorf("%s does not exist", right)
}
lp, err = loop.New()
loop.MouseTrackingMode(lp, loop.BUTTONS_AND_DRAG_MOUSE_TRACKING)
if err != nil {

View File

@@ -8,13 +8,13 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty"
"kitty/tools/config"
"kitty/tools/tty"
"kitty/tools/tui"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -6,9 +6,9 @@ import (
"bytes"
"errors"
"fmt"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/shlex"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/utils/shlex"
"os/exec"
"path/filepath"
"strconv"

View File

@@ -10,12 +10,12 @@ import (
"strconv"
"strings"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/sgr"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/style"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/tui/graphics"
"kitty/tools/tui/loop"
"kitty/tools/tui/sgr"
"kitty/tools/utils"
"kitty/tools/utils/style"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -9,10 +9,10 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/tui"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -8,13 +8,13 @@ import (
"strconv"
"strings"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/readline"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/config"
"kitty/tools/tui"
"kitty/tools/tui/graphics"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -11,13 +11,13 @@ import (
"strings"
"unicode"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/style"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/cli"
"kitty/tools/tty"
"kitty/tools/tui"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/style"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -19,10 +19,10 @@ import (
"github.com/dlclark/regexp2"
"github.com/seancfoley/ipaddress-go/ipaddr"
"github.com/kovidgoyal/kitty"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty"
"kitty/tools/config"
"kitty/tools/tty"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -5,8 +5,8 @@ package hints
import (
"errors"
"fmt"
"github.com/kovidgoyal/kitty"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty"
"kitty/tools/utils"
"os"
"path/filepath"
"strconv"

View File

@@ -15,8 +15,8 @@ import (
"sync"
"unicode"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/cli"
"kitty/tools/utils"
"golang.org/x/sys/unix"
)

View File

@@ -4,7 +4,7 @@ package hyperlinked_grep
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/utils/shlex"
"kitty/tools/utils/shlex"
"testing"
"github.com/google/go-cmp/cmp"

View File

@@ -8,11 +8,11 @@ import (
"os"
"time"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"kitty/tools/tui/graphics"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/utils/shm"
)
var _ = fmt.Print

View File

@@ -5,8 +5,8 @@ package icat
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/utils/images"
"kitty/tools/tui/graphics"
"kitty/tools/utils/images"
)
var _ = fmt.Print

View File

@@ -11,13 +11,13 @@ import (
"sync/atomic"
"time"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/style"
"kitty/tools/cli"
"kitty/tools/tty"
"kitty/tools/tui"
"kitty/tools/tui/graphics"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/utils/style"
"golang.org/x/sys/unix"
)
@@ -222,7 +222,7 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
keep_going.Store(true)
if !opts.DetectSupport && num_of_items > 0 {
num_workers := utils.Max(1, utils.Min(num_of_items, runtime.NumCPU()))
for range num_workers {
for i := 0; i < num_workers; i++ {
go run_worker()
}
}

View File

@@ -4,13 +4,13 @@ package icat
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"image"
"image/gif"
"kitty/tools/tty"
"kitty/tools/tui/graphics"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/utils/shm"
"github.com/edwvee/exiffix"
"github.com/kovidgoyal/imaging"

View File

@@ -15,11 +15,11 @@ import (
"path/filepath"
"strings"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"kitty/tools/tty"
"kitty/tools/tui/graphics"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/utils/shm"
)
var _ = fmt.Print

View File

@@ -8,20 +8,20 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/kovidgoyal/kitty"
"io"
"kitty"
"math"
not_rand "math/rand/v2"
"os"
"path/filepath"
"strings"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/graphics"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/images"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"kitty/tools/tui"
"kitty/tools/tui/graphics"
"kitty/tools/tui/loop"
"kitty/tools/utils"
"kitty/tools/utils/images"
"kitty/tools/utils/shm"
)
var _ = fmt.Print

View File

@@ -12,10 +12,10 @@ import (
"strings"
"time"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/cli"
"kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -13,7 +13,7 @@ import (
"golang.org/x/sys/unix"
"github.com/kovidgoyal/kitty/tools/simdstring"
"kitty/tools/simdstring"
)
var _ = fmt.Print

View File

@@ -16,8 +16,8 @@ import (
"fmt"
"os"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tty"
"kitty/tools/cli"
"kitty/tools/tty"
)
var _ = fmt.Print

View File

@@ -1,63 +0,0 @@
package panel
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/utils"
"golang.org/x/sys/unix"
)
var _ = fmt.Print
func complete_kitty_listen_on(completions *cli.Completions, word string, arg_num int) {
if !strings.Contains(word, ":") {
mg := completions.AddMatchGroup("Address family")
mg.NoTrailingSpace = true
for _, q := range []string{"unix:", "tcp:"} {
if strings.HasPrefix(q, word) {
mg.AddMatch(q)
}
}
} else if strings.HasPrefix(word, "unix:") && !strings.HasPrefix(word, "unix:@") {
cli.FnmatchCompleter("UNIX sockets", cli.CWD, "*")(completions, word[len("unix:"):], arg_num)
completions.AddPrefixToAllMatches("unix:")
}
}
var CompleteKittyListenOn = complete_kitty_listen_on
func GetQuickAccessKittyExe() (kitty_exe string, err error) {
if kitty_exe, err = filepath.EvalSymlinks(utils.KittyExe()); err != nil {
return "", fmt.Errorf("Failed to find path to the kitty executable, this kitten requires the kitty executable to function. The kitty executable or a symlink to it must be placed in the same directory as the kitten executable. Error: %w", err)
}
if runtime.GOOS == "darwin" {
q := filepath.Join(filepath.Dir(filepath.Dir(kitty_exe)), "kitty-quick-access.app", "Contents", "MacOS", "kitty-quick-access")
if err := unix.Access(q, unix.X_OK); err == nil {
kitty_exe = q
}
}
return kitty_exe, nil
}
func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
kitty_exe, err := GetQuickAccessKittyExe()
if err != nil {
return 1, err
}
argv := []string{kitty_exe, "+kitten", "panel"}
argv = append(argv, o.AsCommandLine()...)
err = unix.Exec(kitty_exe, append(argv, args...), os.Environ())
rc = 1
return
}
func EntryPoint(parent *cli.Command) {
create_cmd(parent, main)
}

View File

@@ -1,19 +1,18 @@
#!/usr/bin/env python
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import os
import sys
from collections.abc import Callable
from contextlib import suppress
from functools import partial
from typing import Iterable, Mapping, Sequence
from typing import Any, Mapping, Sequence
from kitty.cli import parse_args
from kitty.cli_stub import PanelCLIOptions
from kitty.constants import is_macos, kitten_exe
from kitty.constants import is_macos, is_wayland, kitten_exe
from kitty.fast_data_types import (
GLFW_EDGE_BOTTOM,
GLFW_EDGE_CENTER,
GLFW_EDGE_CENTER_SIZED,
GLFW_EDGE_LEFT,
GLFW_EDGE_NONE,
GLFW_EDGE_RIGHT,
@@ -25,29 +24,111 @@ from kitty.fast_data_types import (
GLFW_LAYER_SHELL_OVERLAY,
GLFW_LAYER_SHELL_PANEL,
GLFW_LAYER_SHELL_TOP,
set_layer_shell_config,
glfw_primary_monitor_size,
make_x11_window_a_dock_window,
toggle_os_window_visibility,
)
from kitty.simple_cli_definitions import build_panel_cli_spec
from kitty.os_window_size import WindowSizeData, edge_spacing
from kitty.simple_cli_definitions import panel_kitten_options_spec
from kitty.types import LayerShellConfig
from kitty.typing_compat import BossType
from kitty.typing_compat import BossType, EdgeLiteral
from kitty.utils import log_error
quake = (
'kitty +kitten panel --edge=top --layer=overlay --lines=25 --focus-policy=exclusive'
' -o background_opacity=0.8 --toggle-visibility --single-instance --instance-group=quake'
)
default_quake_cmdline = f'{quake} --exclusive-zone=0 --override-exclusive-zone --detach'
default_macos_quake_cmdline = f'{quake}'
args = PanelCLIOptions()
help_text = 'Use a command line program to draw a GPU accelerated panel on your desktop'
usage = '[cmdline-to-run ...]'
def panel_kitten_options_spec() -> str:
if not hasattr(panel_kitten_options_spec, 'ans'):
setattr(panel_kitten_options_spec, 'ans', build_panel_cli_spec({}))
ans: str = getattr(panel_kitten_options_spec, 'ans')
return ans
def parse_panel_args(args: list[str]) -> tuple[PanelCLIOptions, list[str]]:
return parse_args(args, panel_kitten_options_spec, usage, help_text, 'kitty +kitten panel', result_class=PanelCLIOptions)
Strut = tuple[int, int, int, int, int, int, int, int, int, int, int, int]
def create_strut(
win_id: int,
left: int = 0, right: int = 0, top: int = 0, bottom: int = 0, left_start_y: int = 0, left_end_y: int = 0,
right_start_y: int = 0, right_end_y: int = 0, top_start_x: int = 0, top_end_x: int = 0,
bottom_start_x: int = 0, bottom_end_x: int = 0
) -> Strut:
return left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x
def create_top_strut(win_id: int, width: int, height: int) -> Strut:
return create_strut(win_id, top=height, top_end_x=width)
def create_bottom_strut(win_id: int, width: int, height: int) -> Strut:
return create_strut(win_id, bottom=height, bottom_end_x=width)
def create_left_strut(win_id: int, width: int, height: int) -> Strut:
return create_strut(win_id, left=width, left_end_y=height)
def create_right_strut(win_id: int, width: int, height: int) -> Strut:
return create_strut(win_id, right=width, right_end_y=height)
window_width = window_height = 0
def setup_x11_window(win_id: int) -> None:
if is_wayland():
return
try:
func = globals()[f'create_{args.edge}_strut']
except KeyError:
raise SystemExit(f'The value {args.edge} is not support for --edge on X11')
strut = func(win_id, window_width, window_height)
make_x11_window_a_dock_window(win_id, strut)
def initial_window_size_func(opts: WindowSizeData, cached_values: dict[str, Any]) -> Callable[[int, int, float, float, float, float], tuple[int, int]]:
def es(which: EdgeLiteral) -> float:
return edge_spacing(which, opts)
def initial_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> tuple[int, int]:
if not is_macos and not is_wayland():
# Not sure what the deal with scaling on X11 is
xscale = yscale = 1
global window_width, window_height
monitor_width, monitor_height = glfw_primary_monitor_size()
x = dual_distance(args.columns, min_cell_value_if_no_pixels=1)
rwidth = x[1] if x[1] else (x[0] * cell_width / xscale)
x = dual_distance(args.lines, min_cell_value_if_no_pixels=1)
rheight = x[1] if x[1] else (x[0] * cell_width / yscale)
if args.edge in {'left', 'right'}:
spacing = es('left') + es('right')
window_width = int(rwidth + (dpi_x / 72) * spacing + 1)
window_height = monitor_height
elif args.edge in {'top', 'bottom'}:
spacing = es('top') + es('bottom')
window_height = int(rheight + (dpi_y / 72) * spacing + 1)
window_width = monitor_width
elif args.edge in {'background', 'center'}:
window_width, window_height = monitor_width, monitor_height
else:
x_spacing = es('left') + es('right')
window_width = int(rwidth + (dpi_x / 72) * x_spacing + 1)
y_spacing = es('top') + es('bottom')
window_height = int(rheight + (dpi_y / 72) * y_spacing + 1)
return window_width, window_height
return initial_window_size
def dual_distance(spec: str, min_cell_value_if_no_pixels: int = 0) -> tuple[int, int]:
with suppress(Exception):
return int(spec), 0
@@ -67,14 +148,11 @@ def layer_shell_config(opts: PanelCLIOptions) -> LayerShellConfig:
}.get(opts.layer, GLFW_LAYER_SHELL_PANEL)
ltype = GLFW_LAYER_SHELL_BACKGROUND if opts.edge == 'background' else ltype
edge = {
'top': GLFW_EDGE_TOP, 'bottom': GLFW_EDGE_BOTTOM, 'left': GLFW_EDGE_LEFT, 'right': GLFW_EDGE_RIGHT,
'center': GLFW_EDGE_CENTER, 'none': GLFW_EDGE_NONE, 'center-sized': GLFW_EDGE_CENTER_SIZED,
'top': GLFW_EDGE_TOP, 'bottom': GLFW_EDGE_BOTTOM, 'left': GLFW_EDGE_LEFT, 'right': GLFW_EDGE_RIGHT, 'center': GLFW_EDGE_CENTER, 'none': GLFW_EDGE_NONE
}.get(opts.edge, GLFW_EDGE_TOP)
focus_policy = {
'not-allowed': GLFW_FOCUS_NOT_ALLOWED, 'exclusive': GLFW_FOCUS_EXCLUSIVE, 'on-demand': GLFW_FOCUS_ON_DEMAND
}.get(opts.focus_policy, GLFW_FOCUS_NOT_ALLOWED)
if opts.hide_on_focus_loss:
focus_policy = GLFW_FOCUS_ON_DEMAND
x, y = dual_distance(opts.columns, min_cell_value_if_no_pixels=1), dual_distance(opts.lines, min_cell_value_if_no_pixels=1)
return LayerShellConfig(type=ltype,
edge=edge,
@@ -87,49 +165,22 @@ def layer_shell_config(opts: PanelCLIOptions) -> LayerShellConfig:
focus_policy=focus_policy,
requested_exclusive_zone=opts.exclusive_zone,
override_exclusive_zone=opts.override_exclusive_zone,
hide_on_focus_loss=opts.hide_on_focus_loss,
output_name=opts.output_name or '')
mtime_map: dict[str, float] = {}
def have_config_files_been_updated(config_files: Iterable[str]) -> bool:
ans = False
for cf in config_files:
try:
mtime = os.path.getmtime(cf)
except OSError:
mtime = 0
if mtime_map.get(cf, 0) != mtime:
ans = True
mtime_map[cf] = mtime
return ans
def handle_single_instance_command(boss: BossType, sys_args: Sequence[str], environ: Mapping[str, str], notify_on_os_window_death: str | None = '') -> None:
global args
from kitty.cli import parse_override
from kitty.main import run_app
from kitty.tabs import SpecialWindow
try:
new_args, items = parse_panel_args(list(sys_args[1:]))
args, items = parse_panel_args(list(sys_args[1:]))
except BaseException as e:
log_error(f'Invalid arguments received over single instance socket: {sys_args} with error: {e}')
return
lsc = layer_shell_config(new_args)
layer_shell_config_changed = lsc != run_app.layer_shell_config
config_changed = have_config_files_been_updated(new_args.config) or args.config != new_args.config or args.override != new_args.override
args = new_args
if config_changed:
boss.load_config_file(*args.config, overrides=tuple(map(parse_override, new_args.override)))
if args.toggle_visibility and boss.os_window_map:
for os_window_id in boss.os_window_map:
toggle_os_window_visibility(os_window_id)
if layer_shell_config_changed:
set_layer_shell_config(os_window_id, lsc)
return
items = items or [kitten_exe(), 'run-shell']
lsc = layer_shell_config(args)
os_window_id = boss.add_os_panel(lsc, args.cls, args.name)
if notify_on_os_window_death:
boss.os_window_death_actions[os_window_id] = partial(boss.notify_on_os_window_death, notify_on_os_window_death)
@@ -138,18 +189,8 @@ def handle_single_instance_command(boss: BossType, sys_args: Sequence[str], envi
def main(sys_args: list[str]) -> None:
# run_kitten run using runpy.run_module which does not import into
# sys.modules, which means the module will be re-imported later, causing
# global variables to be duplicated, so do it now.
from kittens.panel.main import actual_main
actual_main(sys_args)
return
def actual_main(sys_args: list[str]) -> None:
global args
args, items = parse_panel_args(sys_args[1:])
have_config_files_been_updated(args.config)
sys.argv = ['kitty']
if args.debug_rendering:
sys.argv.append('--debug-rendering')
@@ -179,6 +220,9 @@ def actual_main(sys_args: list[str]) -> None:
from kitty.main import run_app
run_app.cached_values_name = 'panel'
run_app.layer_shell_config = layer_shell_config(args)
if not is_macos:
run_app.first_window_callback = setup_x11_window
run_app.initial_window_size_func = initial_window_size_func
real_main(called_from_panel=True)

View File

@@ -3,14 +3,14 @@ package query_terminal
import (
"bytes"
"fmt"
"github.com/kovidgoyal/kitty"
"kitty"
"os"
"slices"
"strings"
"time"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"kitty/tools/cli"
"kitty/tools/tui/loop"
)
var _ = fmt.Print

View File

@@ -1,105 +0,0 @@
package quick_access_terminal
import (
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/kovidgoyal/kitty/kittens/panel"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/config"
"golang.org/x/sys/unix"
)
var _ = fmt.Print
var complete_kitty_listen_on = panel.CompleteKittyListenOn
func load_config(opts *Options) (ans *Config, err error) {
ans = NewConfig()
p := config.ConfigParser{LineHandler: ans.Parse}
err = p.LoadConfig("quick-access-terminal.conf", opts.Config, opts.Override)
if err != nil {
return nil, err
}
return ans, nil
}
func main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) {
conf, err := load_config(opts)
if err != nil {
return 1, err
}
kitty_exe, err := panel.GetQuickAccessKittyExe()
if err != nil {
return 1, err
}
argv := []string{kitty_exe, "+kitten", "panel", "--toggle-visibility", "--exclusive-zone=0", "--override-exclusive-zone", "--layer=overlay", "--single-instance"}
argv = append(argv, fmt.Sprintf("--lines=%s", conf.Lines))
argv = append(argv, fmt.Sprintf("--columns=%s", conf.Columns))
argv = append(argv, fmt.Sprintf("--edge=%s", conf.Edge))
if conf.Margin_top != 0 {
argv = append(argv, fmt.Sprintf("--margin-top=%d", conf.Margin_top))
}
if conf.Margin_bottom != 0 {
argv = append(argv, fmt.Sprintf("--margin-bottom=%d", conf.Margin_bottom))
}
if conf.Margin_left != 0 {
argv = append(argv, fmt.Sprintf("--margin-left=%d", conf.Margin_left))
}
if conf.Margin_right != 0 {
argv = append(argv, fmt.Sprintf("--margin-right=%d", conf.Margin_right))
}
if len(conf.Kitty_conf) > 0 {
for _, c := range conf.Kitty_conf {
argv = append(argv, fmt.Sprintf("--config=%s", c))
}
}
if len(conf.Kitty_override) > 0 {
for _, c := range conf.Kitty_override {
argv = append(argv, fmt.Sprintf("--override=%s", c))
}
}
argv = append(argv, fmt.Sprintf("--override=background_opacity=%f", conf.Background_opacity))
if runtime.GOOS != "darwin" {
argv = append(argv, fmt.Sprintf("--app-id=%s", conf.App_id))
}
if conf.Output_name != "" {
argv = append(argv, fmt.Sprintf("--output-name=%s", conf.Output_name))
}
argv = append(argv, fmt.Sprintf("--focus-policy=%s", conf.Focus_policy))
if conf.Start_as_hidden {
argv = append(argv, `--start-as-hidden`)
}
if conf.Hide_on_focus_loss {
argv = append(argv, `--hide-on-focus-loss`)
}
if opts.DebugRendering {
argv = append(argv, `--debug-rendering`)
}
if opts.Detach {
argv = append(argv, `--detach`)
}
if opts.DetachedLog != "" {
if dl, err := filepath.Abs(opts.DetachedLog); err != nil {
return 1, err
} else {
argv = append(argv, dl)
}
}
if opts.InstanceGroup != "" {
argv = append(argv, fmt.Sprintf("--instance-group=%s", opts.InstanceGroup))
}
argv = append(argv, args...)
err = unix.Exec(kitty_exe, argv, os.Environ())
rc = 1
return
}
func EntryPoint(parent *cli.Command) {
create_cmd(parent, main)
}

View File

@@ -1,141 +0,0 @@
#!/usr/bin/env python
# License: GPLv3 Copyright: 2025, Kovid Goyal <kovid at kovidgoyal.net>
import sys
from kitty.conf.types import Definition
from kitty.constants import appname
from kitty.simple_cli_definitions import CONFIG_HELP
help_text = 'A quick access terminal window that you can bring up instantly with a keypress or a command.'
definition = Definition(
'!kittens.quick_access_terminal',
)
agr = definition.add_group
egr = definition.end_group
opt = definition.add_option
agr('qat', 'Window appearance')
opt('lines', '25',
long_text='''
The number of lines shown in the window, when the window is along the top or bottom edges of the screen.
If it has the suffix :code:`px` then it sets the height of the window in pixels instead of lines.
''',)
opt('columns', '80',
long_text='''
The number of columns shown in the window, when the window is along the left or right edges of the screen.
If it has the suffix :code:`px` then it sets the width of the window in pixels instead of columns.
''',)
opt('edge', 'top', choices=('top', 'bottom', 'left', 'right'),
long_text='Which edge of the screen to place the window along')
opt('background_opacity', '0.85', option_type='unit_float', long_text='''
The background opacity of the window. This works the same as the kitty
option of the same name, it is present here as it has a different
default value for the quick access terminal.
''')
opt('hide_on_focus_loss', 'no', option_type='to_bool', long_text='''
Hide the window when it loses keyboard focus automatically. Using this option
will force :opt:`focus_policy` to :code:`on-demand`.
''')
opt('margin_left', '0', option_type='int',
long_text='Set the left margin for the window, in pixels. Has no effect for windows on the right edge of the screen.')
opt('margin_right', '0', option_type='int',
long_text='Set the right margin for the window, in pixels. Has no effect for windows on the left edge of the screen.')
opt('margin_top', '0', option_type='int',
long_text='Set the top margin for the window, in pixels. Has no effect for windows on the bottom edge of the screen.')
opt('margin_bottom', '0', option_type='int',
long_text='Set the bottom margin for the window, in pixels. Has no effect for windows on the top edge of the screen.')
opt('+kitty_conf', '',
long_text='Path to config file to use for kitty when drawing the window. Can be specified multiple times. By default, the'
' normal kitty.conf is used. Relative paths are resolved with respect to the kitty config directory.'
)
opt('+kitty_override', '', long_text='Override individual kitty configuration options, can be specified multiple times.'
' Syntax: :italic:`name=value`. For example: :code:`font_size=20`.'
)
opt('app_id', f'{appname}-quick-access',
long_text='On Wayland set the :italic:`namespace` of the layer shell surface.'
' On X11 set the WM_CLASS assigned to the quick access window. (Linux only)')
opt('output_name', '', long_text='''
The panel can only be displayed on a single monitor (output) at a time. This allows
you to specify which output is used, by name. If not specified the compositor will choose an
output automatically, typically the last output the user interacted with or the primary monitor.
You can get a list of available outputs by running: :code:`kitten panel --output-name list`.
''')
opt('start_as_hidden', 'no', option_type='to_bool',
long_text='Whether to start the quick access terminal hidden. Useful if you are starting it as part of system startup.')
opt('focus_policy', 'exclusive', choices=('exclusive', 'on-demand'), long_text='''
How to manage window focus. A value of :code:`exclusive` means prevent other windows from getting focus.
However, whether this works is entirely dependent on the compositor/desktop environment.
It does not have any effect on macOS and KDE, for example. Note that on sway using :code:`on-demand` means
the compositor will not focus the window when it appears until you click on it, which is why the default is set
to :code:`exclusive`.
''')
def options_spec() -> str:
return f'''
--config -c
type=list
completion=type:file ext:conf group:"Config files" kwds:none,NONE
{CONFIG_HELP.format(conf_name='quick-access-terminal', appname=appname)}
--override -o
type=list
Override individual configuration options, can be specified multiple times.
Syntax: :italic:`name=value`. For example: :italic:`-o lines=12`
--detach
type=bool-set
Detach from the controlling terminal, if any, running in an independent child process,
the parent process exits immediately.
--detached-log
Path to a log file to store STDOUT/STDERR when using :option:`--detach`
--instance-group
default=quick-access
The unique name of this quick access terminal Use a different name if you want multiple such terminals.
--debug-rendering
type=bool-set
For debugging interactions with the compositor/window manager.
'''
def main(args: list[str]) -> None:
raise SystemExit('This kitten should be run as: kitten quick-access-terminal')
if __name__ == '__main__':
main(sys.argv)
elif __name__ == '__doc__':
cd: dict = sys.cli_docs # type: ignore
cd['usage'] = '[cmdline-to-run ...]'
cd['options'] = options_spec
cd['help_text'] = help_text
cd['short_desc'] = help_text
elif __name__ == '__conf__':
sys.options_definition = definition # type: ignore

View File

@@ -87,8 +87,8 @@ class KittenMetadata(NamedTuple):
def create_kitten_handler(kitten: str, orig_args: list[str]) -> KittenMetadata:
from kitty.constants import config_dir
m = import_kitten_main_module(config_dir, kitten)
kitten = resolved_kitten(kitten)
m = import_kitten_main_module(config_dir, kitten)
main = m['start']
handle_result = m['end']
return KittenMetadata(
@@ -110,13 +110,12 @@ def set_debug(kitten: str) -> None:
def launch(args: list[str]) -> None:
config_dir, kitten = args[:2]
original_kitten_name = kitten
kitten = resolved_kitten(kitten)
del args[:2]
args = [kitten] + args
os.environ['KITTY_CONFIG_DIRECTORY'] = config_dir
set_debug(kitten)
m = import_kitten_main_module(config_dir, original_kitten_name)
m = import_kitten_main_module(config_dir, kitten)
try:
result = m['start'](args)
finally:
@@ -140,14 +139,11 @@ def run_kitten(kitten: str, run_name: str = '__main__') -> None:
if kitten in all_kitten_names():
runpy.run_module(f'kittens.{kitten}.main', run_name=run_name)
return
kitten = original_kitten_name
# Look for a custom kitten
if not kitten.endswith('.py'):
kitten += '.py'
from kitty.constants import config_dir
path = path_to_custom_kitten(config_dir, kitten)
if not os.path.exists(path):
path = path_to_custom_kitten(config_dir, resolved_kitten(kitten))
if not os.path.exists(path):
print('Available builtin kittens:', file=sys.stderr)
for kitten in all_kitten_names():

View File

@@ -6,8 +6,8 @@ import (
"fmt"
"strings"
"github.com/kovidgoyal/kitty/tools/cli/markup"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"kitty/tools/cli/markup"
"kitty/tools/tui/loop"
)
var _ = fmt.Print

View File

@@ -5,9 +5,9 @@ package show_key
import (
"errors"
"fmt"
"github.com/kovidgoyal/kitty/tools/cli/markup"
"github.com/kovidgoyal/kitty/tools/tty"
"io"
"kitty/tools/cli/markup"
"kitty/tools/tty"
"os"
"golang.org/x/sys/unix"

View File

@@ -5,7 +5,7 @@ package show_key
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/cli"
"kitty/tools/cli"
)
var _ = fmt.Print

View File

@@ -9,9 +9,9 @@ import (
"strings"
"time"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"kitty/tools/cli"
"kitty/tools/tty"
"kitty/tools/utils/shm"
)
var _ = fmt.Print

View File

@@ -13,10 +13,10 @@ import (
"strings"
"time"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/paths"
"github.com/kovidgoyal/kitty/tools/utils/shlex"
"kitty/tools/config"
"kitty/tools/utils"
"kitty/tools/utils/paths"
"kitty/tools/utils/shlex"
"github.com/bmatcuk/doublestar/v4"
"golang.org/x/sys/unix"

View File

@@ -4,7 +4,7 @@ package ssh
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/utils"
"os"
"os/user"
"path/filepath"
@@ -112,7 +112,7 @@ func TestSSHConfigParsing(t *testing.T) {
hostname = "2"
rt()
ci, err := ParseCopyInstruction("--exclude moose --exclude second --dest=target " + cf)
ci, err := ParseCopyInstruction("--exclude moose --dest=target " + cf)
if err != nil {
t.Fatal(err)
}
@@ -124,7 +124,7 @@ func TestSSHConfigParsing(t *testing.T) {
if diff != "" {
t.Fatalf("Incorrect local_path:\n%s", diff)
}
diff = cmp.Diff([]string{"moose", "second"}, ci[0].exclude_patterns)
diff = cmp.Diff([]string{"moose"}, ci[0].exclude_patterns)
if diff != "" {
t.Fatalf("Incorrect excludes:\n%s", diff)
}

View File

@@ -10,9 +10,9 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/kovidgoyal/kitty"
"io"
"io/fs"
"kitty"
"maps"
"net/url"
"os"
@@ -28,16 +28,16 @@ import (
"syscall"
"time"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/themes"
"github.com/kovidgoyal/kitty/tools/tty"
"github.com/kovidgoyal/kitty/tools/tui"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/shell_integration"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/utils/secrets"
"github.com/kovidgoyal/kitty/tools/utils/shlex"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"kitty/tools/cli"
"kitty/tools/themes"
"kitty/tools/tty"
"kitty/tools/tui"
"kitty/tools/tui/loop"
"kitty/tools/tui/shell_integration"
"kitty/tools/utils"
"kitty/tools/utils/secrets"
"kitty/tools/utils/shlex"
"kitty/tools/utils/shm"
"golang.org/x/sys/unix"
)

View File

@@ -6,9 +6,9 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
"github.com/kovidgoyal/kitty"
"github.com/kovidgoyal/kitty/tools/utils/shm"
"io/fs"
"kitty"
"kitty/tools/utils/shm"
"os"
"os/exec"
"path"

View File

@@ -11,9 +11,9 @@ import (
"strings"
"sync"
"github.com/kovidgoyal/kitty"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty"
"kitty/tools/config"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -9,7 +9,7 @@ import (
"path/filepath"
"testing"
"github.com/kovidgoyal/kitty/tools/utils/shlex"
"kitty/tools/utils/shlex"
"github.com/google/go-cmp/cmp"
)

View File

@@ -5,9 +5,9 @@ package themes
import (
"fmt"
"github.com/kovidgoyal/kitty/tools/themes"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/themes"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

View File

@@ -11,10 +11,10 @@ import (
"strings"
"time"
"github.com/kovidgoyal/kitty/tools/cli"
"github.com/kovidgoyal/kitty/tools/themes"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/utils"
"kitty/tools/cli"
"kitty/tools/themes"
"kitty/tools/tui/loop"
"kitty/tools/utils"
)
var _ = fmt.Print

View File

@@ -4,20 +4,20 @@ package themes
import (
"fmt"
"github.com/kovidgoyal/kitty"
"io"
"kitty"
"maps"
"regexp"
"slices"
"strings"
"time"
"github.com/kovidgoyal/kitty/tools/config"
"github.com/kovidgoyal/kitty/tools/themes"
"github.com/kovidgoyal/kitty/tools/tui/loop"
"github.com/kovidgoyal/kitty/tools/tui/readline"
"github.com/kovidgoyal/kitty/tools/utils"
"github.com/kovidgoyal/kitty/tools/wcswidth"
"kitty/tools/config"
"kitty/tools/themes"
"kitty/tools/tui/loop"
"kitty/tools/tui/readline"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print

Some files were not shown because too many files have changed in this diff Show More