Issue #13709: wait we get our first surface focus before listing…
… input devices. Per Carlos' advice on gtk#7534, I wait for us to get a focus, since the pad devices are only created at that point. Note that this is a Wayland-only issue, but since it doesn't matter too much that input devices are not initialized before we have a focused GUI anyway, let's make this simpler. At the earliest, the splash focus can announce a focus, but since it is possible to start GIMP without the splash, display shells will also possibly announce the first focus (there will always be a display shell focusing at some point for any GUI GIMP!).
This commit is contained in:
parent
10cf3f05ee
commit
d92c237a17
6 changed files with 217 additions and 108 deletions
|
|
@ -97,6 +97,7 @@ enum
|
|||
CLIPBOARD_CHANGED,
|
||||
FILTER_HISTORY_CHANGED,
|
||||
IMAGE_OPENED,
|
||||
FOCUSED_ONCE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
|
@ -205,6 +206,13 @@ gimp_class_init (GimpClass *klass)
|
|||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_FILE);
|
||||
|
||||
gimp_signals[FOCUSED_ONCE] =
|
||||
g_signal_new ("focused-once",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, 0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
object_class->constructed = gimp_constructed;
|
||||
object_class->set_property = gimp_set_property;
|
||||
object_class->get_property = gimp_get_property;
|
||||
|
|
@ -293,6 +301,8 @@ gimp_init (Gimp *gimp)
|
|||
|
||||
gimp->templates = gimp_list_new (GIMP_TYPE_TEMPLATE, TRUE);
|
||||
gimp_object_set_static_name (GIMP_OBJECT (gimp->templates), "templates");
|
||||
|
||||
gimp->focused_once = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -917,6 +927,26 @@ gimp_exit (Gimp *gimp,
|
|||
gimp, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_set_focused_once (Gimp *gimp)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
|
||||
if (! gimp->focused_once)
|
||||
{
|
||||
gimp->focused_once = TRUE;
|
||||
g_signal_emit (gimp, gimp_signals[FOCUSED_ONCE], 0);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_has_focused_once (Gimp *gimp)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
||||
|
||||
return gimp->focused_once;
|
||||
}
|
||||
|
||||
GList *
|
||||
gimp_get_image_iter (Gimp *gimp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -133,6 +133,9 @@ struct _Gimp
|
|||
|
||||
/* the context used by the interface */
|
||||
GimpContext *user_context;
|
||||
|
||||
/* GUI focus occured. See gtk#7534. */
|
||||
gboolean focused_once;
|
||||
};
|
||||
|
||||
struct _GimpClass
|
||||
|
|
@ -189,6 +192,9 @@ gboolean gimp_is_restored (Gimp *gimp);
|
|||
void gimp_exit (Gimp *gimp,
|
||||
gboolean force);
|
||||
|
||||
void gimp_set_focused_once (Gimp *gimp);
|
||||
gboolean gimp_has_focused_once (Gimp *gimp);
|
||||
|
||||
GList * gimp_get_image_iter (Gimp *gimp);
|
||||
GList * gimp_get_display_iter (Gimp *gimp);
|
||||
GList * gimp_get_image_windows (Gimp *gimp);
|
||||
|
|
|
|||
|
|
@ -258,8 +258,13 @@ gimp_display_shell_events (GtkWidget *widget,
|
|||
{
|
||||
GdkEventFocus *fevent = (GdkEventFocus *) event;
|
||||
|
||||
if (fevent->in && shell->display->config->activate_on_focus)
|
||||
set_display = TRUE;
|
||||
if (fevent->in)
|
||||
{
|
||||
gimp_set_focused_once (gimp);
|
||||
|
||||
if (shell->display->config->activate_on_focus)
|
||||
set_display = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,10 @@ static gboolean splash_key_event (GtkWidget *window,
|
|||
GimpSplash *splash);
|
||||
static gboolean splash_unset_alt (GimpSplash *splash);
|
||||
|
||||
static gboolean splash_window_focus (GtkWidget *window,
|
||||
GtkDirectionType direction,
|
||||
Gimp *gimp);
|
||||
|
||||
static void splash_rectangle_union (GdkRectangle *dest,
|
||||
PangoRectangle *pango_rect,
|
||||
gint offset_x,
|
||||
|
|
@ -293,6 +297,10 @@ splash_create (Gimp *gimp,
|
|||
gtk_box_pack_end (GTK_BOX (vbox), splash->progress, FALSE, FALSE, 0);
|
||||
gtk_widget_show (splash->progress);
|
||||
|
||||
g_signal_connect (splash->window, "focus",
|
||||
G_CALLBACK (splash_window_focus),
|
||||
gimp);
|
||||
|
||||
gtk_widget_show (splash->window);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
|
@ -485,6 +493,19 @@ splash_unset_alt (GimpSplash *splash)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
splash_window_focus (GtkWidget *window,
|
||||
GtkDirectionType direction,
|
||||
Gimp *gimp)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (splash->window,
|
||||
G_CALLBACK (splash_window_focus),
|
||||
gimp);
|
||||
gimp_set_focused_once (gimp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* area returns the union of the previous and new ink rectangles */
|
||||
static void
|
||||
splash_position_layouts (GimpSplash *splash,
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ static void gimp_device_manager_get_property (GObject *object,
|
|||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void gimp_device_manager_focused_once (GimpDeviceManager *manager);
|
||||
|
||||
static void gimp_device_manager_display_opened (GdkDisplayManager *disp_manager,
|
||||
GdkDisplay *display,
|
||||
GimpDeviceManager *manager);
|
||||
|
|
@ -168,54 +170,17 @@ gimp_device_manager_constructed (GObject *object)
|
|||
{
|
||||
GimpDeviceManager *manager = GIMP_DEVICE_MANAGER (object);
|
||||
GimpDeviceManagerPrivate *private = GET_PRIVATE (object);
|
||||
GdkDisplayManager *disp_manager;
|
||||
GSList *displays;
|
||||
GSList *list;
|
||||
GdkDisplay *display;
|
||||
GdkSeat *seat;
|
||||
GdkDevice *pointer;
|
||||
GimpDeviceInfo *device_info;
|
||||
GimpContext *user_context;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
gimp_assert (GIMP_IS_GIMP (private->gimp));
|
||||
|
||||
disp_manager = gdk_display_manager_get ();
|
||||
|
||||
displays = gdk_display_manager_list_displays (disp_manager);
|
||||
|
||||
/* present displays in the order in which they were opened */
|
||||
displays = g_slist_reverse (displays);
|
||||
|
||||
for (list = displays; list; list = g_slist_next (list))
|
||||
{
|
||||
gimp_device_manager_display_opened (disp_manager, list->data, manager);
|
||||
}
|
||||
|
||||
g_slist_free (displays);
|
||||
|
||||
g_signal_connect (disp_manager, "display-opened",
|
||||
G_CALLBACK (gimp_device_manager_display_opened),
|
||||
manager);
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
seat = gdk_display_get_default_seat (display);
|
||||
|
||||
pointer = gdk_seat_get_pointer (seat);
|
||||
|
||||
device_info = gimp_device_info_get_by_device (pointer);
|
||||
gimp_device_manager_set_current_device (manager, device_info);
|
||||
|
||||
g_signal_connect_object (private->gimp->config, "notify::devices-share-tool",
|
||||
G_CALLBACK (gimp_device_manager_config_notify),
|
||||
manager, 0);
|
||||
|
||||
user_context = gimp_get_user_context (private->gimp);
|
||||
|
||||
g_signal_connect_object (user_context, "tool-changed",
|
||||
G_CALLBACK (gimp_device_manager_tool_changed),
|
||||
manager, 0);
|
||||
if (gimp_has_focused_once (private->gimp))
|
||||
gimp_device_manager_focused_once (manager);
|
||||
else
|
||||
g_signal_connect_object (private->gimp, "focused-once",
|
||||
G_CALLBACK (gimp_device_manager_focused_once),
|
||||
manager, G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -397,6 +362,59 @@ gimp_device_manager_reconfigure_pads (GimpDeviceManager *manager)
|
|||
|
||||
/* private functions */
|
||||
|
||||
static void
|
||||
gimp_device_manager_focused_once (GimpDeviceManager *manager)
|
||||
{
|
||||
GimpDeviceManagerPrivate *private = GET_PRIVATE (manager);
|
||||
GdkDisplayManager *disp_manager;
|
||||
GSList *displays;
|
||||
GSList *list;
|
||||
GdkDisplay *display;
|
||||
GdkSeat *seat;
|
||||
GdkDevice *pointer;
|
||||
GimpDeviceInfo *device_info;
|
||||
GimpContext *user_context;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (private->gimp,
|
||||
G_CALLBACK (gimp_device_manager_focused_once),
|
||||
manager);
|
||||
|
||||
disp_manager = gdk_display_manager_get ();
|
||||
displays = gdk_display_manager_list_displays (disp_manager);
|
||||
|
||||
/* present displays in the order in which they were opened */
|
||||
displays = g_slist_reverse (displays);
|
||||
|
||||
for (list = displays; list; list = g_slist_next (list))
|
||||
{
|
||||
gimp_device_manager_display_opened (disp_manager, list->data, manager);
|
||||
}
|
||||
|
||||
g_slist_free (displays);
|
||||
|
||||
g_signal_connect (disp_manager, "display-opened",
|
||||
G_CALLBACK (gimp_device_manager_display_opened),
|
||||
manager);
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
seat = gdk_display_get_default_seat (display);
|
||||
|
||||
pointer = gdk_seat_get_pointer (seat);
|
||||
|
||||
device_info = gimp_device_info_get_by_device (pointer);
|
||||
gimp_device_manager_set_current_device (manager, device_info);
|
||||
|
||||
g_signal_connect_object (private->gimp->config, "notify::devices-share-tool",
|
||||
G_CALLBACK (gimp_device_manager_config_notify),
|
||||
manager, 0);
|
||||
|
||||
user_context = gimp_get_user_context (private->gimp);
|
||||
|
||||
g_signal_connect_object (user_context, "tool-changed",
|
||||
G_CALLBACK (gimp_device_manager_tool_changed),
|
||||
manager, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_device_manager_display_opened (GdkDisplayManager *disp_manager,
|
||||
GdkDisplay *display,
|
||||
|
|
@ -427,6 +445,14 @@ gimp_device_manager_display_opened (GdkDisplayManager *disp_manager,
|
|||
device = gdk_seat_get_pointer (seat);
|
||||
gimp_device_manager_device_added (seat, device, manager);
|
||||
|
||||
/* XXX The whole reason why we created the "focused-once" signal on
|
||||
* Gimp object is because on Wayland, GDK returns a NULL GdkDevice for
|
||||
* tablet pads until a surface got in focus at least once (see
|
||||
* gtk#7534). So we wait for this one-time focus before querying
|
||||
* devices. It makes things a bit more bothersome, but is acceptable
|
||||
* since anyway we can't do anything with input devices before we have
|
||||
* a GUI.
|
||||
*/
|
||||
devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_ALL);
|
||||
|
||||
/* create device info structures for present devices */
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@
|
|||
static gboolean devicerc_deleted = FALSE;
|
||||
|
||||
|
||||
static void gimp_devices_restore_on_focused_once (Gimp *gimp);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
|
|
@ -87,69 +90,12 @@ gimp_devices_exit (Gimp *gimp)
|
|||
void
|
||||
gimp_devices_restore (Gimp *gimp)
|
||||
{
|
||||
GimpDeviceManager *manager;
|
||||
GList *list;
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
|
||||
manager = gimp_devices_get_manager (gimp);
|
||||
|
||||
g_return_if_fail (GIMP_IS_DEVICE_MANAGER (manager));
|
||||
|
||||
for (list = GIMP_LIST (manager)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpDeviceInfo *device_info = list->data;
|
||||
|
||||
gimp_device_info_save_tool (device_info);
|
||||
gimp_device_info_set_default_tool (device_info);
|
||||
}
|
||||
|
||||
file = gimp_directory_file ("devicerc", NULL);
|
||||
|
||||
if (gimp->be_verbose)
|
||||
g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
|
||||
|
||||
if (! gimp_config_deserialize_file (GIMP_CONFIG (manager),
|
||||
file,
|
||||
gimp,
|
||||
&error))
|
||||
{
|
||||
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
|
||||
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
|
||||
|
||||
g_error_free (error);
|
||||
/* don't bail out here */
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
for (list = GIMP_LIST (manager)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpDeviceInfo *device_info = list->data;
|
||||
|
||||
if (! GIMP_TOOL_PRESET (device_info)->tool_options)
|
||||
{
|
||||
gimp_device_info_save_tool (device_info);
|
||||
|
||||
g_printerr ("%s: set default tool on loaded GimpDeviceInfo without tool options: %s\n",
|
||||
G_STRFUNC, gimp_object_get_name (device_info));
|
||||
}
|
||||
}
|
||||
|
||||
if (! GIMP_GUI_CONFIG (gimp->config)->devices_share_tool)
|
||||
{
|
||||
GimpDeviceInfo *current_device;
|
||||
|
||||
current_device = gimp_device_manager_get_current_device (manager);
|
||||
|
||||
gimp_device_info_restore_tool (current_device);
|
||||
}
|
||||
if (gimp_has_focused_once (gimp))
|
||||
gimp_devices_restore_on_focused_once (gimp);
|
||||
else
|
||||
g_signal_connect (gimp, "focused-once",
|
||||
G_CALLBACK (gimp_devices_restore_on_focused_once),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -395,3 +341,78 @@ gimp_devices_check_change (Gimp *gimp,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Private functions */
|
||||
|
||||
static void
|
||||
gimp_devices_restore_on_focused_once (Gimp *gimp)
|
||||
{
|
||||
GimpDeviceManager *manager;
|
||||
GList *list;
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (gimp,
|
||||
G_CALLBACK (gimp_devices_restore_on_focused_once),
|
||||
NULL);
|
||||
|
||||
manager = gimp_devices_get_manager (gimp);
|
||||
|
||||
g_return_if_fail (GIMP_IS_DEVICE_MANAGER (manager));
|
||||
|
||||
for (list = GIMP_LIST (manager)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpDeviceInfo *device_info = list->data;
|
||||
|
||||
gimp_device_info_save_tool (device_info);
|
||||
gimp_device_info_set_default_tool (device_info);
|
||||
}
|
||||
|
||||
file = gimp_directory_file ("devicerc", NULL);
|
||||
|
||||
if (gimp->be_verbose)
|
||||
g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
|
||||
|
||||
if (! gimp_config_deserialize_file (GIMP_CONFIG (manager),
|
||||
file,
|
||||
gimp,
|
||||
&error))
|
||||
{
|
||||
if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
|
||||
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
|
||||
|
||||
g_error_free (error);
|
||||
/* don't bail out here */
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
for (list = GIMP_LIST (manager)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpDeviceInfo *device_info = list->data;
|
||||
|
||||
if (! GIMP_TOOL_PRESET (device_info)->tool_options)
|
||||
{
|
||||
gimp_device_info_save_tool (device_info);
|
||||
|
||||
g_printerr ("%s: set default tool on loaded GimpDeviceInfo without tool options: %s\n",
|
||||
G_STRFUNC, gimp_object_get_name (device_info));
|
||||
}
|
||||
}
|
||||
|
||||
if (! GIMP_GUI_CONFIG (gimp->config)->devices_share_tool)
|
||||
{
|
||||
GimpDeviceInfo *current_device;
|
||||
|
||||
current_device = gimp_device_manager_get_current_device (manager);
|
||||
|
||||
gimp_device_info_restore_tool (current_device);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue