backends: Handle numlock saving/restoring directly in backends
Simplify the handling of numlock state, so it can be entirely handled within the input thread. Since the saving/restoring is triggered inside each backend code, there's no need anymore for meta_backend_set_numlock(). Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403>
This commit is contained in:
parent
23f95348fd
commit
f7fbd6ea6f
11 changed files with 111 additions and 152 deletions
|
@ -100,9 +100,6 @@ struct _MetaBackendClass
|
|||
void (* update_screen_size) (MetaBackend *backend, int width, int height);
|
||||
void (* select_stage_events) (MetaBackend *backend);
|
||||
|
||||
void (* set_numlock) (MetaBackend *backend,
|
||||
gboolean numlock_state);
|
||||
|
||||
void (* set_pointer_constraint) (MetaBackend *backend,
|
||||
MetaPointerConstraint *constraint);
|
||||
};
|
||||
|
|
|
@ -157,7 +157,6 @@ struct _MetaBackendPrivate
|
|||
gboolean is_pointer_position_initialized;
|
||||
|
||||
guint device_update_idle_id;
|
||||
gulong keymap_state_changed_id;
|
||||
|
||||
GHashTable *device_monitors;
|
||||
|
||||
|
@ -198,16 +197,6 @@ meta_backend_finalize (GObject *object)
|
|||
MetaBackend *backend = META_BACKEND (object);
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
if (priv->keymap_state_changed_id)
|
||||
{
|
||||
ClutterSeat *seat;
|
||||
ClutterKeymap *keymap;
|
||||
|
||||
seat = clutter_backend_get_default_seat (priv->clutter_backend);
|
||||
keymap = clutter_seat_get_keymap (seat);
|
||||
g_clear_signal_handler (&priv->keymap_state_changed_id, keymap);
|
||||
}
|
||||
|
||||
g_list_free_full (priv->gpus, g_object_unref);
|
||||
|
||||
g_clear_object (&priv->current_device);
|
||||
|
@ -579,7 +568,6 @@ meta_backend_real_post_init (MetaBackend *backend)
|
|||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend);
|
||||
ClutterKeymap *keymap = clutter_seat_get_keymap (seat);
|
||||
|
||||
priv->stage = meta_stage_new (backend);
|
||||
clutter_actor_realize (priv->stage);
|
||||
|
@ -602,15 +590,6 @@ meta_backend_real_post_init (MetaBackend *backend)
|
|||
|
||||
priv->input_settings = meta_backend_create_input_settings (backend);
|
||||
|
||||
if (priv->input_settings)
|
||||
{
|
||||
priv->keymap_state_changed_id =
|
||||
g_signal_connect_swapped (keymap, "state-changed",
|
||||
G_CALLBACK (meta_input_settings_maybe_save_numlock_state),
|
||||
priv->input_settings);
|
||||
meta_input_settings_maybe_restore_numlock_state (priv->input_settings);
|
||||
}
|
||||
|
||||
priv->input_mapper = meta_input_mapper_new ();
|
||||
g_signal_connect (priv->input_mapper, "device-mapped",
|
||||
G_CALLBACK (input_mapper_device_mapped_cb), backend);
|
||||
|
@ -1357,14 +1336,6 @@ meta_backend_lock_layout_group (MetaBackend *backend,
|
|||
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_set_numlock (MetaBackend *backend,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->set_numlock (backend, numlock_state);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* meta_backend_get_stage:
|
||||
* @backend: A #MetaBackend
|
||||
|
|
|
@ -173,8 +173,9 @@ struct _MetaInputSettingsClass
|
|||
ClutterInputDevice *device);
|
||||
};
|
||||
|
||||
void meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings);
|
||||
void meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings);
|
||||
void meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings,
|
||||
gboolean numlock_state);
|
||||
gboolean meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings);
|
||||
|
||||
void meta_input_settings_set_device_matrix (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
|
|
|
@ -1161,8 +1161,6 @@ meta_input_settings_changed_cb (GSettings *settings,
|
|||
strcmp (key, "repeat-interval") == 0 ||
|
||||
strcmp (key, "delay") == 0)
|
||||
update_keyboard_repeat (input_settings);
|
||||
else if (strcmp (key, "remember-numlock-state") == 0)
|
||||
meta_input_settings_maybe_save_numlock_state (input_settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1838,41 +1836,34 @@ meta_input_settings_init (MetaInputSettings *settings)
|
|||
}
|
||||
|
||||
void
|
||||
meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings)
|
||||
meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
ClutterSeat *seat;
|
||||
ClutterKeymap *keymap;
|
||||
gboolean numlock_state;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
|
||||
if (!g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state"))
|
||||
return;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
keymap = clutter_seat_get_keymap (seat);
|
||||
numlock_state = clutter_keymap_get_num_lock_state (keymap);
|
||||
|
||||
if (numlock_state == g_settings_get_boolean (priv->keyboard_settings, "numlock-state"))
|
||||
return;
|
||||
|
||||
g_settings_set_boolean (priv->keyboard_settings, "numlock-state", numlock_state);
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
gboolean numlock_state;
|
||||
gboolean numlock_state = FALSE;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
|
||||
if (!g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state"))
|
||||
return;
|
||||
if (g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state"))
|
||||
numlock_state = g_settings_get_boolean (priv->keyboard_settings, "numlock-state");
|
||||
|
||||
numlock_state = g_settings_get_boolean (priv->keyboard_settings, "numlock-state");
|
||||
meta_backend_set_numlock (meta_get_backend (), numlock_state);
|
||||
return numlock_state;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -332,18 +332,6 @@ meta_backend_native_lock_layout_group (MetaBackend *backend,
|
|||
meta_backend_notify_keymap_layout_group_changed (backend, idx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_set_numlock (MetaBackend *backend,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
meta_seat_native_set_keyboard_numlock (META_SEAT_NATIVE (seat),
|
||||
numlock_state);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_set_pointer_constraint (MetaBackend *backend,
|
||||
MetaPointerConstraint *constraint)
|
||||
|
@ -576,7 +564,6 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
|||
backend_class->get_keymap_layout_group = meta_backend_native_get_keymap_layout_group;
|
||||
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
|
||||
backend_class->update_screen_size = meta_backend_native_update_screen_size;
|
||||
backend_class->set_numlock = meta_backend_native_set_numlock;
|
||||
|
||||
backend_class->set_pointer_constraint = meta_backend_native_set_pointer_constraint;
|
||||
}
|
||||
|
|
|
@ -344,9 +344,18 @@ meta_seat_impl_notify_key (MetaSeatImpl *seat_impl,
|
|||
if (update_keys && (changed_state & XKB_STATE_LEDS))
|
||||
{
|
||||
MetaInputDeviceNative *keyboard_native;
|
||||
gboolean numlock_active;
|
||||
|
||||
g_signal_emit (seat_impl, signals[MODS_STATE_CHANGED], 0);
|
||||
meta_seat_impl_sync_leds (seat_impl);
|
||||
|
||||
numlock_active =
|
||||
xkb_state_mod_name_is_active (seat_impl->xkb, XKB_MOD_NAME_NUM,
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
meta_input_settings_maybe_save_numlock_state (seat_impl->input_settings,
|
||||
numlock_active);
|
||||
|
||||
keyboard_native = META_INPUT_DEVICE_NATIVE (seat_impl->core_keyboard);
|
||||
meta_input_device_native_a11y_maybe_notify_toggle_keys (keyboard_native);
|
||||
}
|
||||
|
@ -2465,6 +2474,48 @@ static const struct libinput_interface libinput_interface = {
|
|||
close_restricted
|
||||
};
|
||||
|
||||
static void
|
||||
meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat_impl,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
xkb_mod_mask_t depressed_mods;
|
||||
xkb_mod_mask_t latched_mods;
|
||||
xkb_mod_mask_t locked_mods;
|
||||
xkb_mod_mask_t group_mods;
|
||||
xkb_mod_mask_t numlock;
|
||||
struct xkb_keymap *xkb_keymap;
|
||||
MetaKeymapNative *keymap;
|
||||
|
||||
keymap = seat_impl->keymap;
|
||||
xkb_keymap = meta_keymap_native_get_keyboard_map (keymap);
|
||||
|
||||
numlock = (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod2"));
|
||||
|
||||
depressed_mods =
|
||||
xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_DEPRESSED);
|
||||
latched_mods =
|
||||
xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LATCHED);
|
||||
locked_mods =
|
||||
xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LOCKED);
|
||||
group_mods =
|
||||
xkb_state_serialize_layout (seat_impl->xkb, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
|
||||
if (numlock_state)
|
||||
locked_mods |= numlock;
|
||||
else
|
||||
locked_mods &= ~numlock;
|
||||
|
||||
xkb_state_update_mask (seat_impl->xkb,
|
||||
depressed_mods,
|
||||
latched_mods,
|
||||
locked_mods,
|
||||
0, 0,
|
||||
group_mods);
|
||||
|
||||
meta_seat_impl_sync_leds (seat_impl);
|
||||
meta_keymap_native_update (seat_impl->keymap);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_seat_impl_constructed (GObject *object)
|
||||
{
|
||||
|
@ -2536,6 +2587,9 @@ meta_seat_impl_constructed (GObject *object)
|
|||
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL);
|
||||
}
|
||||
|
||||
if (meta_input_settings_maybe_restore_numlock_state (seat_impl->input_settings))
|
||||
meta_seat_impl_set_keyboard_numlock (seat_impl, TRUE);
|
||||
|
||||
seat_impl->has_touchscreen = has_touchscreen (seat_impl);
|
||||
seat_impl->has_tablet_switch = has_tablet_switch (seat_impl);
|
||||
update_touch_mode (seat_impl);
|
||||
|
@ -2604,6 +2658,7 @@ static void
|
|||
meta_seat_impl_finalize (GObject *object)
|
||||
{
|
||||
MetaSeatImpl *seat_impl = META_SEAT_IMPL (object);
|
||||
gboolean numlock_active;
|
||||
GSList *iter;
|
||||
|
||||
for (iter = seat_impl->devices; iter; iter = g_slist_next (iter))
|
||||
|
@ -2621,6 +2676,13 @@ meta_seat_impl_finalize (GObject *object)
|
|||
|
||||
meta_event_source_free (seat_impl->event_source);
|
||||
|
||||
numlock_active =
|
||||
xkb_state_mod_name_is_active (seat_impl->xkb, XKB_MOD_NAME_NUM,
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
meta_input_settings_maybe_save_numlock_state (seat_impl->input_settings,
|
||||
numlock_active);
|
||||
|
||||
xkb_state_unref (seat_impl->xkb);
|
||||
|
||||
meta_seat_impl_clear_repeat_timer (seat_impl);
|
||||
|
@ -2978,61 +3040,6 @@ meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat_impl,
|
|||
g_rw_lock_writer_unlock (&seat_impl->state_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_seat_impl_set_keyboard_numlock: (skip)
|
||||
* @seat: the #ClutterSeat created by the evdev backend
|
||||
* @numlock_set: TRUE to set NumLock ON, FALSE otherwise.
|
||||
*
|
||||
* Sets the NumLock state on the backend's #xkb_state .
|
||||
*/
|
||||
void
|
||||
meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat_impl,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
xkb_mod_mask_t depressed_mods;
|
||||
xkb_mod_mask_t latched_mods;
|
||||
xkb_mod_mask_t locked_mods;
|
||||
xkb_mod_mask_t group_mods;
|
||||
xkb_mod_mask_t numlock;
|
||||
struct xkb_keymap *xkb_keymap;
|
||||
MetaKeymapNative *keymap;
|
||||
|
||||
g_return_if_fail (META_IS_SEAT_IMPL (seat_impl));
|
||||
|
||||
g_rw_lock_writer_lock (&seat_impl->state_lock);
|
||||
|
||||
keymap = seat_impl->keymap;
|
||||
xkb_keymap = meta_keymap_native_get_keyboard_map (keymap);
|
||||
|
||||
numlock = (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod2"));
|
||||
|
||||
depressed_mods =
|
||||
xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_DEPRESSED);
|
||||
latched_mods =
|
||||
xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LATCHED);
|
||||
locked_mods =
|
||||
xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LOCKED);
|
||||
group_mods =
|
||||
xkb_state_serialize_layout (seat_impl->xkb, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
|
||||
if (numlock_state)
|
||||
locked_mods |= numlock;
|
||||
else
|
||||
locked_mods &= ~numlock;
|
||||
|
||||
xkb_state_update_mask (seat_impl->xkb,
|
||||
depressed_mods,
|
||||
latched_mods,
|
||||
locked_mods,
|
||||
0, 0,
|
||||
group_mods);
|
||||
|
||||
meta_seat_impl_sync_leds (seat_impl);
|
||||
meta_keymap_native_update (seat_impl->keymap);
|
||||
|
||||
g_rw_lock_writer_unlock (&seat_impl->state_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_seat_impl_set_keyboard_repeat:
|
||||
* @seat: the #ClutterSeat created by the evdev backend
|
||||
|
|
|
@ -209,9 +209,6 @@ void meta_seat_impl_set_keyboard_map (MetaSeatImpl *seat_im
|
|||
void meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat_impl,
|
||||
xkb_layout_index_t idx);
|
||||
|
||||
void meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat_impl,
|
||||
gboolean numlock_state);
|
||||
|
||||
void meta_seat_impl_set_keyboard_repeat (MetaSeatImpl *seat_impl,
|
||||
gboolean repeat,
|
||||
uint32_t delay,
|
||||
|
|
|
@ -612,20 +612,6 @@ meta_seat_native_get_keyboard_layout_index (MetaSeatNative *seat)
|
|||
return seat->xkb_layout_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_seat_native_set_keyboard_numlock: (skip)
|
||||
* @seat: the #ClutterSeat created by the evdev backend
|
||||
* @numlock_set: TRUE to set NumLock ON, FALSE otherwise.
|
||||
*
|
||||
* Sets the NumLock state on the backend's #xkb_state .
|
||||
*/
|
||||
void
|
||||
meta_seat_native_set_keyboard_numlock (MetaSeatNative *seat,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
meta_seat_impl_set_keyboard_numlock (seat->impl, numlock_state);
|
||||
}
|
||||
|
||||
MetaBarrierManagerNative *
|
||||
meta_seat_native_get_barrier_manager (MetaSeatNative *seat)
|
||||
{
|
||||
|
|
|
@ -107,9 +107,6 @@ void meta_seat_native_set_keyboard_layout_index (MetaSeatNative *seat,
|
|||
|
||||
xkb_layout_index_t meta_seat_native_get_keyboard_layout_index (MetaSeatNative *seat);
|
||||
|
||||
void meta_seat_native_set_keyboard_numlock (MetaSeatNative *seat,
|
||||
gboolean numlock_state);
|
||||
|
||||
void meta_seat_native_set_keyboard_repeat (MetaSeatNative *seat,
|
||||
gboolean repeat,
|
||||
uint32_t delay,
|
||||
|
|
|
@ -82,6 +82,8 @@ struct _MetaBackendX11Private
|
|||
uint8_t xkb_event_base;
|
||||
uint8_t xkb_error_base;
|
||||
|
||||
gulong keymap_state_changed_id;
|
||||
|
||||
struct xkb_keymap *keymap;
|
||||
xkb_layout_index_t keymap_layout_group;
|
||||
|
||||
|
@ -605,6 +607,14 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
|||
g_signal_connect_object (meta_backend_get_input_settings (backend),
|
||||
"kbd-a11y-changed",
|
||||
G_CALLBACK (on_kbd_a11y_changed), backend, 0);
|
||||
|
||||
if (meta_input_settings_maybe_restore_numlock_state (input_settings))
|
||||
{
|
||||
unsigned int num_mask;
|
||||
|
||||
num_mask = XkbKeysymToModifiers (priv->xdisplay, XK_Num_Lock);
|
||||
XkbLockModifiers (priv->xdisplay, XkbUseCoreKbd, num_mask, num_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,19 +768,6 @@ meta_backend_x11_get_keymap_layout_group (MetaBackend *backend)
|
|||
return priv->keymap_layout_group;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_set_numlock (MetaBackend *backend,
|
||||
gboolean numlock_state)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
unsigned int num_mask;
|
||||
|
||||
num_mask = XkbKeysymToModifiers (priv->xdisplay, XK_Num_Lock);
|
||||
XkbLockModifiers (priv->xdisplay, XkbUseCoreKbd, num_mask,
|
||||
numlock_state ? num_mask : 0);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_x11_handle_event (MetaBackendX11 *x11,
|
||||
XEvent *xevent)
|
||||
|
@ -853,9 +850,21 @@ initable_iface_init (GInitableIface *initable_iface)
|
|||
static void
|
||||
meta_backend_x11_finalize (GObject *object)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (object);
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (object);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (priv->keymap_state_changed_id)
|
||||
{
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
ClutterKeymap *keymap;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
keymap = clutter_seat_get_keymap (seat);
|
||||
g_clear_signal_handler (&priv->keymap_state_changed_id, keymap);
|
||||
}
|
||||
|
||||
if (priv->user_active_alarm != None)
|
||||
{
|
||||
XSyncDestroyAlarm (priv->xdisplay, priv->user_active_alarm);
|
||||
|
@ -880,7 +889,6 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
|||
backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
|
||||
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
||||
backend_class->get_keymap_layout_group = meta_backend_x11_get_keymap_layout_group;
|
||||
backend_class->set_numlock = meta_backend_x11_set_numlock;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <X11/Xatom.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/x11/meta-keymap-x11.h"
|
||||
#include "clutter/clutter.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
|
@ -218,6 +220,21 @@ update_locked_mods (MetaKeymapX11 *keymap_x11,
|
|||
if ((keymap_x11->caps_lock_state != old_caps_lock_state) ||
|
||||
(keymap_x11->num_lock_state != old_num_lock_state))
|
||||
g_signal_emit_by_name (keymap_x11, "state-changed");
|
||||
|
||||
if (keymap_x11->num_lock_state != old_num_lock_state)
|
||||
{
|
||||
MetaBackend *backend;
|
||||
MetaInputSettings *input_settings;
|
||||
|
||||
backend = meta_get_backend ();
|
||||
input_settings = meta_backend_get_input_settings (backend);
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
meta_input_settings_maybe_save_numlock_state (input_settings,
|
||||
keymap_x11->num_lock_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the code to retrieve the keymap direction and cache it
|
||||
|
|
Loading…
Reference in a new issue