Improve handling of output names
Now can use panel --output-name list to list available outputs. Also, --output-name works on macOS
This commit is contained in:
parent
67c1ce7280
commit
88f4c829eb
15 changed files with 100 additions and 24 deletions
|
|
@ -1945,6 +1945,17 @@ void _glfwPlatformDestroyWindow(_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
|
||||
|
|
@ -1975,6 +1986,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||
// 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);
|
||||
|
|
|
|||
3
glfw/glfw3.h
vendored
3
glfw/glfw3.h
vendored
|
|
@ -1314,7 +1314,7 @@ typedef struct GLFWLayerShellConfig {
|
|||
int requested_top_margin, requested_left_margin, requested_bottom_margin, requested_right_margin;
|
||||
} previous;
|
||||
bool was_toggled_to_fullscreen;
|
||||
char output_name[64];
|
||||
char output_name[128];
|
||||
GLFWFocusPolicy focus_policy;
|
||||
unsigned x_size_in_cells, x_size_in_pixels;
|
||||
unsigned y_size_in_cells, y_size_in_pixels;
|
||||
|
|
@ -2385,6 +2385,7 @@ 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.
|
||||
*
|
||||
|
|
|
|||
2
glfw/internal.h
vendored
2
glfw/internal.h
vendored
|
|
@ -490,7 +490,7 @@ struct _GLFWwindow
|
|||
//
|
||||
struct _GLFWmonitor
|
||||
{
|
||||
char* name;
|
||||
const char *name, *description;
|
||||
void* userPointer;
|
||||
|
||||
// Physical dimensions in millimeters.
|
||||
|
|
|
|||
15
glfw/monitor.c
vendored
15
glfw/monitor.c
vendored
|
|
@ -186,7 +186,8 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor)
|
|||
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||
|
||||
free(monitor->modes);
|
||||
free(monitor->name);
|
||||
free((void*)monitor->name);
|
||||
free((void*)monitor->description);
|
||||
free(monitor);
|
||||
}
|
||||
|
||||
|
|
@ -393,9 +394,19 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
|
|||
assert(monitor != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return monitor->name;
|
||||
return monitor->name ? 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;
|
||||
|
|
|
|||
24
glfw/wl_monitor.c
vendored
24
glfw/wl_monitor.c
vendored
|
|
@ -41,20 +41,15 @@ static void outputHandleGeometry(void* data,
|
|||
int32_t physicalWidth,
|
||||
int32_t physicalHeight,
|
||||
int32_t subpixel UNUSED,
|
||||
const char* make,
|
||||
const char* model,
|
||||
const char* make UNUSED,
|
||||
const char* model UNUSED,
|
||||
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,
|
||||
|
|
@ -105,15 +100,20 @@ static void outputHandleName(void* data,
|
|||
struct wl_output* output UNUSED,
|
||||
const char* name) {
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
if (name) strncpy(monitor->wl.friendly_name, name, sizeof(monitor->wl.friendly_name)-1);
|
||||
if (name) {
|
||||
if (monitor->name) free((void*)monitor->name);
|
||||
monitor->name = _glfw_strdup(name);
|
||||
}
|
||||
}
|
||||
|
||||
static void outputHandleDescription(void* data,
|
||||
struct wl_output* output UNUSED,
|
||||
const char* description) {
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
if (description) strncpy(monitor->wl.description, description, sizeof(monitor->wl.description)-1);
|
||||
|
||||
if (description) {
|
||||
if (monitor->description) free((void*)monitor->description);
|
||||
monitor->description = _glfw_strdup(description);
|
||||
}
|
||||
}
|
||||
|
||||
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 geometry handler.
|
||||
monitor = _glfwAllocMonitor(NULL, 0, 0);
|
||||
// The actual name of this output will be set in the handlers.
|
||||
monitor = _glfwAllocMonitor("unnamed", 0, 0);
|
||||
|
||||
output = wl_registry_bind(_glfw.wl.registry,
|
||||
name,
|
||||
|
|
|
|||
1
glfw/wl_platform.h
vendored
1
glfw/wl_platform.h
vendored
|
|
@ -406,7 +406,6 @@ typedef struct _GLFWmonitorWayland
|
|||
{
|
||||
struct wl_output* output;
|
||||
uint32_t name;
|
||||
char friendly_name[64], description[64];
|
||||
int currentMode;
|
||||
|
||||
int x;
|
||||
|
|
|
|||
2
glfw/wl_window.c
vendored
2
glfw/wl_window.c
vendored
|
|
@ -971,7 +971,7 @@ 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->wl.friendly_name, name) == 0) return m->wl.output;
|
||||
if (strcmp(m->name, name) == 0) return m->wl.output;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ func main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) {
|
|||
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))
|
||||
}
|
||||
}
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -71,9 +71,10 @@
|
|||
|
||||
|
||||
opt('output_name', '', long_text='''
|
||||
On Wayland or X11, the panel can only be displayed on a single monitor (output) at a time. This allows
|
||||
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',
|
||||
|
|
|
|||
|
|
@ -1570,6 +1570,7 @@ def set_os_window_pos(os_window_id: int, x: int, y: int) -> None:
|
|||
def get_all_processes() -> Tuple[int, ...]:
|
||||
pass
|
||||
|
||||
def get_monitor_names() -> tuple[tuple[str, str], ...]: ...
|
||||
|
||||
def num_users() -> int:
|
||||
pass
|
||||
|
|
|
|||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
|
|
@ -89,6 +89,9 @@ load_glfw(const char* path) {
|
|||
*(void **) (&glfwGetMonitorName_impl) = dlsym(handle, "glfwGetMonitorName");
|
||||
if (glfwGetMonitorName_impl == NULL) fail("Failed to load glfw function glfwGetMonitorName with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwGetMonitorDescription_impl) = dlsym(handle, "glfwGetMonitorDescription");
|
||||
if (glfwGetMonitorDescription_impl == NULL) fail("Failed to load glfw function glfwGetMonitorDescription with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwSetMonitorUserPointer_impl) = dlsym(handle, "glfwSetMonitorUserPointer");
|
||||
if (glfwSetMonitorUserPointer_impl == NULL) fail("Failed to load glfw function glfwSetMonitorUserPointer with error: %s", dlerror());
|
||||
|
||||
|
|
|
|||
6
kitty/glfw-wrapper.h
generated
6
kitty/glfw-wrapper.h
generated
|
|
@ -1052,7 +1052,7 @@ typedef struct GLFWLayerShellConfig {
|
|||
int requested_top_margin, requested_left_margin, requested_bottom_margin, requested_right_margin;
|
||||
} previous;
|
||||
bool was_toggled_to_fullscreen;
|
||||
char output_name[64];
|
||||
char output_name[128];
|
||||
GLFWFocusPolicy focus_policy;
|
||||
unsigned x_size_in_cells, x_size_in_pixels;
|
||||
unsigned y_size_in_cells, y_size_in_pixels;
|
||||
|
|
@ -1817,6 +1817,10 @@ typedef const char* (*glfwGetMonitorName_func)(GLFWmonitor*);
|
|||
GFW_EXTERN glfwGetMonitorName_func glfwGetMonitorName_impl;
|
||||
#define glfwGetMonitorName glfwGetMonitorName_impl
|
||||
|
||||
typedef const char* (*glfwGetMonitorDescription_func)(GLFWmonitor*);
|
||||
GFW_EXTERN glfwGetMonitorDescription_func glfwGetMonitorDescription_impl;
|
||||
#define glfwGetMonitorDescription glfwGetMonitorDescription_impl
|
||||
|
||||
typedef void (*glfwSetMonitorUserPointer_func)(GLFWmonitor*, void*);
|
||||
GFW_EXTERN glfwSetMonitorUserPointer_func glfwSetMonitorUserPointer_impl;
|
||||
#define glfwSetMonitorUserPointer glfwSetMonitorUserPointer_impl
|
||||
|
|
|
|||
18
kitty/glfw.c
18
kitty/glfw.c
|
|
@ -2143,6 +2143,23 @@ get_monitor_workarea(PYNOARG) {
|
|||
return Py_NewRef(result);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
get_monitor_names(PYNOARG) {
|
||||
int count = 0;
|
||||
GLFWmonitor **monitors = glfwGetMonitors(&count);
|
||||
if (count <= 0 || !monitors) return PyTuple_New(0);
|
||||
RAII_PyObject(result, PyTuple_New(count)); if (!result) return NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
const char *name = glfwGetMonitorName(monitors[i]);
|
||||
const char *description = glfwGetMonitorDescription(monitors[i]);
|
||||
PyObject *x = Py_BuildValue("ss", name, description);
|
||||
if (!x) return NULL;
|
||||
PyTuple_SET_ITEM(result, i, x);
|
||||
}
|
||||
return Py_NewRef(result);
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
primary_monitor_content_scale(PYNOARG) {
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
|
|
@ -2643,6 +2660,7 @@ static PyMethodDef module_methods[] = {
|
|||
{"glfw_get_system_color_theme", (PyCFunction)glfw_get_system_color_theme, METH_VARARGS, ""},
|
||||
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
|
||||
{"glfw_get_monitor_workarea", (PyCFunction)get_monitor_workarea, METH_NOARGS, ""},
|
||||
{"glfw_get_monitor_names", (PyCFunction)get_monitor_names, METH_NOARGS, ""},
|
||||
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
SingleKey,
|
||||
create_os_window,
|
||||
free_font_data,
|
||||
glfw_get_monitor_names,
|
||||
glfw_get_monitor_workarea,
|
||||
glfw_init,
|
||||
glfw_terminate,
|
||||
|
|
@ -220,9 +221,30 @@ def is_panel_kitten() -> bool:
|
|||
return _is_panel_kitten
|
||||
|
||||
|
||||
def list_monitors() -> None:
|
||||
monitor_names = glfw_get_monitor_names()
|
||||
has_descriptions = False
|
||||
for (name, desc) in monitor_names:
|
||||
if desc:
|
||||
has_descriptions = True
|
||||
break
|
||||
isatty = sys.stdout.isatty()
|
||||
for (name, desc) in monitor_names:
|
||||
if isatty:
|
||||
name = f'\x1b[32m{name}\x1b[39m' # ]]
|
||||
print(name)
|
||||
if desc:
|
||||
print(f'\t{desc}')
|
||||
if has_descriptions:
|
||||
print()
|
||||
|
||||
|
||||
def _run_app(opts: Options, args: CLIOptions, bad_lines: Sequence[BadLine] = (), talk_fd: int = -1) -> None:
|
||||
global _is_panel_kitten
|
||||
_is_panel_kitten = run_app.cached_values_name == 'panel'
|
||||
if _is_panel_kitten and run_app.layer_shell_config.output_name == 'list':
|
||||
list_monitors()
|
||||
return
|
||||
if is_macos:
|
||||
global_shortcuts = set_cocoa_global_shortcuts(opts)
|
||||
if opts.macos_custom_beam_cursor:
|
||||
|
|
|
|||
|
|
@ -639,9 +639,10 @@ def build_panel_cli_spec(defaults: dict[str, str]) -> str:
|
|||
|
||||
|
||||
--output-name
|
||||
On Wayland or X11, the panel can only be displayed on a single monitor (output) at a time. This allows
|
||||
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.
|
||||
Use the special value :code:`list` to get a list of available outputs.
|
||||
|
||||
|
||||
--class --app-id
|
||||
|
|
|
|||
Loading…
Reference in a new issue