Add a command line switch to set the name part of WM_CLASS independently
This commit is contained in:
parent
02884c5045
commit
32a6dd2aa1
@ -36,6 +36,9 @@ version 0.5.1 [2017-12-01]
|
|||||||
|
|
||||||
- Add an option to control the audio bell volume on X11 systems
|
- Add an option to control the audio bell volume on X11 systems
|
||||||
|
|
||||||
|
- Add a command line switch to set the name part of the WM_CLASS window
|
||||||
|
property independently.
|
||||||
|
|
||||||
|
|
||||||
version 0.5.0 [2017-11-19]
|
version 0.5.0 [2017-11-19]
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|||||||
7
glfw/glfw3.h
vendored
7
glfw/glfw3.h
vendored
@ -2343,7 +2343,12 @@ GLFWAPI void glfwWindowHint(int hint, int value);
|
|||||||
* @remark @x11 The name and class of the `WM_CLASS` window property will by
|
* @remark @x11 The name and class of the `WM_CLASS` window property will by
|
||||||
* default be set to the window title passed to this function. Set the @ref
|
* default be set to the window title passed to this function. Set the @ref
|
||||||
* GLFW_X11_WM_CLASS_NAME and @ref GLFW_X11_WM_CLASS_CLASS init hints before
|
* GLFW_X11_WM_CLASS_NAME and @ref GLFW_X11_WM_CLASS_CLASS init hints before
|
||||||
* initialization to override this.
|
* initialization to override this. You can also set the title int he following
|
||||||
|
* special format, which allows setting the two parts of the WM_CLASS property
|
||||||
|
* and the window title independently:
|
||||||
|
* <01> WM_CLASS name <30> WM_CLASS class <30> title
|
||||||
|
* Here <01> refers to the byte value 01 (ASCII start-of-header) and <30> refers
|
||||||
|
* to the byte value 30 (ASCII record separator).
|
||||||
*
|
*
|
||||||
* @remark @wayland The window frame is currently unimplemented, as if
|
* @remark @wayland The window frame is currently unimplemented, as if
|
||||||
* [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`.
|
* [GLFW_DECORATED](@ref GLFW_DECORATED_hint) was always set to `GLFW_FALSE`.
|
||||||
|
|||||||
29
glfw/x11_window.c
vendored
29
glfw/x11_window.c
vendored
@ -703,9 +703,11 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
updateNormalHints(window, wndconfig->width, wndconfig->height);
|
updateNormalHints(window, wndconfig->width, wndconfig->height);
|
||||||
|
|
||||||
// Set ICCCM WM_CLASS property
|
// Set ICCCM WM_CLASS property and window title
|
||||||
{
|
{
|
||||||
XClassHint* hint = XAllocClassHint();
|
XClassHint* hint = XAllocClassHint();
|
||||||
|
char *wm_cclass = NULL, *wm_cname = NULL;
|
||||||
|
const char *real_title = wndconfig->title;
|
||||||
|
|
||||||
if (strlen(_glfw.hints.init.x11.className) &&
|
if (strlen(_glfw.hints.init.x11.className) &&
|
||||||
strlen(_glfw.hints.init.x11.classClass))
|
strlen(_glfw.hints.init.x11.classClass))
|
||||||
@ -713,10 +715,26 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
hint->res_name = (char*) _glfw.hints.init.x11.className;
|
hint->res_name = (char*) _glfw.hints.init.x11.className;
|
||||||
hint->res_class = (char*) _glfw.hints.init.x11.classClass;
|
hint->res_class = (char*) _glfw.hints.init.x11.classClass;
|
||||||
}
|
}
|
||||||
else if (strlen(wndconfig->title))
|
else if (strlen(real_title))
|
||||||
{
|
{
|
||||||
hint->res_name = (char*) wndconfig->title;
|
if (*real_title == 1) {
|
||||||
hint->res_class = (char*) wndconfig->title;
|
char *p = strchr(real_title, 30);
|
||||||
|
if (p && p > real_title + 1) {
|
||||||
|
wm_cname = calloc(p - real_title + 1, 1);
|
||||||
|
if (wm_cname) memcpy(wm_cname, real_title + 1, p - real_title - 1);
|
||||||
|
hint->res_name = wm_cname;
|
||||||
|
char *q = strchr(p + 1, 30);
|
||||||
|
if (q && q > p + 1) {
|
||||||
|
wm_cclass = calloc(q - p + 1, 1);
|
||||||
|
if (wm_cclass) memcpy(wm_cclass, p + 1, q - p - 1);
|
||||||
|
hint->res_class = wm_cclass;
|
||||||
|
real_title = q + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hint->res_name = (char*) real_title;
|
||||||
|
hint->res_class = (char*) real_title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -726,6 +744,8 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
|
XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
|
||||||
XFree(hint);
|
XFree(hint);
|
||||||
|
free(wm_cclass); free(wm_cname);
|
||||||
|
_glfwPlatformSetWindowTitle(window, real_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Announce support for Xdnd (drag and drop)
|
// Announce support for Xdnd (drag and drop)
|
||||||
@ -736,7 +756,6 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
PropModeReplace, (unsigned char*) &version, 1);
|
PropModeReplace, (unsigned char*) &version, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
|
||||||
|
|
||||||
if (_glfw.x11.im)
|
if (_glfw.x11.im)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -19,8 +19,9 @@ from .keys import get_key_map, get_shortcut
|
|||||||
from .session import create_session
|
from .session import create_session
|
||||||
from .tabs import SpecialWindow, TabManager
|
from .tabs import SpecialWindow, TabManager
|
||||||
from .utils import (
|
from .utils import (
|
||||||
end_startup_notification, get_primary_selection, init_startup_notification,
|
encode_wm_class, end_startup_notification, get_primary_selection,
|
||||||
open_url, safe_print, set_primary_selection, single_instance
|
init_startup_notification, open_url, safe_print, set_primary_selection,
|
||||||
|
single_instance
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -78,10 +79,10 @@ class Boss:
|
|||||||
startup_session = create_session(opts, args)
|
startup_session = create_session(opts, args)
|
||||||
self.add_os_window(startup_session, os_window_id=os_window_id)
|
self.add_os_window(startup_session, os_window_id=os_window_id)
|
||||||
|
|
||||||
def add_os_window(self, startup_session, os_window_id=None, wclass=None, size=None, visible=True):
|
def add_os_window(self, startup_session, os_window_id=None, wclass=None, wname=None, size=None, visible=True):
|
||||||
if os_window_id is None:
|
if os_window_id is None:
|
||||||
w, h = initial_window_size(self.opts) if size is None else size
|
w, h = initial_window_size(self.opts) if size is None else size
|
||||||
os_window_id = create_os_window(w, h, wclass or self.args.cls, visible)
|
os_window_id = create_os_window(w, h, encode_wm_class(wname or self.args.name, wclass or self.args.cls), visible)
|
||||||
tm = TabManager(os_window_id, self.opts, self.args, startup_session)
|
tm = TabManager(os_window_id, self.opts, self.args, startup_session)
|
||||||
self.os_window_map[os_window_id] = tm
|
self.os_window_map[os_window_id] = tm
|
||||||
return os_window_id
|
return os_window_id
|
||||||
@ -103,7 +104,7 @@ class Boss:
|
|||||||
args = option_parser().parse_args(msg['args'][1:])
|
args = option_parser().parse_args(msg['args'][1:])
|
||||||
opts = create_opts(args)
|
opts = create_opts(args)
|
||||||
session = create_session(opts, args)
|
session = create_session(opts, args)
|
||||||
os_window_id = self.add_os_window(session, wclass=args.cls, size=initial_window_size(opts))
|
os_window_id = self.add_os_window(session, wclass=args.cls, wname=args.name, size=initial_window_size(opts))
|
||||||
if startup_id:
|
if startup_id:
|
||||||
ctx = init_startup_notification(os_window_id, startup_id)
|
ctx = init_startup_notification(os_window_id, startup_id)
|
||||||
end_startup_notification(ctx)
|
end_startup_notification(ctx)
|
||||||
|
|||||||
@ -20,7 +20,13 @@ def option_parser():
|
|||||||
'--class',
|
'--class',
|
||||||
default=appname,
|
default=appname,
|
||||||
dest='cls',
|
dest='cls',
|
||||||
help=_('Set the WM_CLASS property')
|
help=_('Set the class part of the WM_CLASS property')
|
||||||
|
)
|
||||||
|
a(
|
||||||
|
'--name',
|
||||||
|
default=None,
|
||||||
|
dest='name',
|
||||||
|
help=_('Set the name part of the WM_CLASS property (defaults to using the value from {})').format('--class')
|
||||||
)
|
)
|
||||||
a(
|
a(
|
||||||
'--config',
|
'--config',
|
||||||
|
|||||||
10
kitty/glfw.c
10
kitty/glfw.c
@ -402,15 +402,6 @@ glfw_window_hint(PyObject UNUSED *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject*
|
|
||||||
glfw_init_hint_string(PyObject UNUSED *self, PyObject *args) {
|
|
||||||
int hint_id;
|
|
||||||
char *hint;
|
|
||||||
if (!PyArg_ParseTuple(args, "is", &hint_id, &hint)) return NULL;
|
|
||||||
glfwInitHintString(hint_id, hint);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
@ -694,7 +685,6 @@ static PyMethodDef module_methods[] = {
|
|||||||
{"glfw_post_empty_event", (PyCFunction)glfw_post_empty_event, METH_NOARGS, ""},
|
{"glfw_post_empty_event", (PyCFunction)glfw_post_empty_event, METH_NOARGS, ""},
|
||||||
{"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""},
|
{"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""},
|
||||||
{"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""},
|
{"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""},
|
||||||
{"glfw_init_hint_string", (PyCFunction)glfw_init_hint_string, METH_VARARGS, ""},
|
|
||||||
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
|
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""},
|
||||||
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
|
{"glfw_primary_monitor_content_scale", (PyCFunction)primary_monitor_content_scale, METH_NOARGS, ""},
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
|
|||||||
@ -14,13 +14,13 @@ from .cli import create_opts, option_parser
|
|||||||
from .config import initial_window_size, load_cached_values, save_cached_values
|
from .config import initial_window_size, load_cached_values, save_cached_values
|
||||||
from .constants import isosx, iswayland, logo_data_file
|
from .constants import isosx, iswayland, logo_data_file
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
change_wcwidth, create_os_window, glfw_init, glfw_init_hint_string,
|
change_wcwidth, create_os_window, glfw_init, glfw_terminate,
|
||||||
glfw_terminate, install_sigchld_handler, set_default_window_icon,
|
install_sigchld_handler, set_default_window_icon, set_logical_dpi,
|
||||||
set_logical_dpi, set_options, GLFW_X11_WM_CLASS_NAME, GLFW_X11_WM_CLASS_CLASS
|
set_options
|
||||||
)
|
)
|
||||||
from .fonts.box_drawing import set_scale
|
from .fonts.box_drawing import set_scale
|
||||||
from .utils import (
|
from .utils import (
|
||||||
detach, end_startup_notification, get_logical_dpi,
|
detach, encode_wm_class, end_startup_notification, get_logical_dpi,
|
||||||
init_startup_notification, single_instance
|
init_startup_notification, single_instance
|
||||||
)
|
)
|
||||||
from .window import load_shader_programs
|
from .window import load_shader_programs
|
||||||
@ -45,7 +45,7 @@ def run_app(opts, args):
|
|||||||
set_options(opts, iswayland, args.debug_gl)
|
set_options(opts, iswayland, args.debug_gl)
|
||||||
load_cached_values()
|
load_cached_values()
|
||||||
w, h = initial_window_size(opts)
|
w, h = initial_window_size(opts)
|
||||||
window_id = create_os_window(w, h, args.cls, True, load_all_shaders)
|
window_id = create_os_window(w, h, encode_wm_class(args.name, args.cls), True, load_all_shaders)
|
||||||
startup_ctx = init_startup_notification(window_id)
|
startup_ctx = init_startup_notification(window_id)
|
||||||
if not iswayland and not isosx: # no window icons on wayland
|
if not iswayland and not isosx: # no window icons on wayland
|
||||||
with open(logo_data_file, 'rb') as f:
|
with open(logo_data_file, 'rb') as f:
|
||||||
@ -137,10 +137,7 @@ def main():
|
|||||||
return
|
return
|
||||||
opts = create_opts(args)
|
opts = create_opts(args)
|
||||||
change_wcwidth(not opts.use_system_wcwidth)
|
change_wcwidth(not opts.use_system_wcwidth)
|
||||||
glfw_module = init_graphics()
|
init_graphics()
|
||||||
if glfw_module == 'x11':
|
|
||||||
glfw_init_hint_string(GLFW_X11_WM_CLASS_CLASS, args.cls)
|
|
||||||
glfw_init_hint_string(GLFW_X11_WM_CLASS_NAME, args.cls)
|
|
||||||
try:
|
try:
|
||||||
with setup_profiling(args):
|
with setup_profiling(args):
|
||||||
# Avoid needing to launch threads to reap zombies
|
# Avoid needing to launch threads to reap zombies
|
||||||
|
|||||||
@ -291,3 +291,9 @@ def single_instance(group_id=None):
|
|||||||
s.set_inheritable(False)
|
s.set_inheritable(False)
|
||||||
atexit.register(remove_socket_file, s)
|
atexit.register(remove_socket_file, s)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def encode_wm_class(name, cls, title=appname):
|
||||||
|
if isosx:
|
||||||
|
return title
|
||||||
|
return '\x01' + (name or cls) + '\x1e' + cls + '\x1e' + title
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user