/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include "libpikabase/pikabase.h" #include "libpikaconfig/pikaconfig.h" #include "libpikawidgets/pikawidgets.h" #define PIKA_ENABLE_CONTROLLER_UNDER_CONSTRUCTION #include "libpikawidgets/pikacontroller.h" #include "widgets-types.h" #include "core/pika.h" #include "core/pikalist.h" #include "pikaaction.h" #include "pikaactiongroup.h" #include "pikacontrollerinfo.h" #include "pikacontrollers.h" #include "pikacontrollerkeyboard.h" #include "pikacontrollerwheel.h" #include "pikaenumaction.h" #include "pikauimanager.h" #include "pika-intl.h" #define PIKA_CONTROLLER_MANAGER_DATA_KEY "pika-controller-manager" typedef struct _PikaControllerManager PikaControllerManager; struct _PikaControllerManager { PikaContainer *controllers; GQuark event_mapped_id; PikaController *wheel; PikaController *keyboard; PikaUIManager *ui_manager; }; /* local function prototypes */ static PikaControllerManager * pika_controller_manager_get (Pika *pika); static void pika_controller_manager_free (PikaControllerManager *manager); static void pika_controllers_add (PikaContainer *container, PikaControllerInfo *info, PikaControllerManager *manager); static void pika_controllers_remove (PikaContainer *container, PikaControllerInfo *info, PikaControllerManager *manager); static gboolean pika_controllers_event_mapped (PikaControllerInfo *info, PikaController *controller, const PikaControllerEvent *event, const gchar *action_name, PikaControllerManager *manager); /* public functions */ void pika_controllers_init (Pika *pika) { PikaControllerManager *manager; g_return_if_fail (PIKA_IS_PIKA (pika)); g_return_if_fail (pika_controller_manager_get (pika) == NULL); manager = g_slice_new0 (PikaControllerManager); g_object_set_data_full (G_OBJECT (pika), PIKA_CONTROLLER_MANAGER_DATA_KEY, manager, (GDestroyNotify) pika_controller_manager_free); manager->controllers = pika_list_new (PIKA_TYPE_CONTROLLER_INFO, TRUE); g_signal_connect (manager->controllers, "add", G_CALLBACK (pika_controllers_add), manager); g_signal_connect (manager->controllers, "remove", G_CALLBACK (pika_controllers_remove), manager); manager->event_mapped_id = pika_container_add_handler (manager->controllers, "event-mapped", G_CALLBACK (pika_controllers_event_mapped), manager); g_type_class_ref (PIKA_TYPE_CONTROLLER_WHEEL); g_type_class_ref (PIKA_TYPE_CONTROLLER_KEYBOARD); } void pika_controllers_exit (Pika *pika) { g_return_if_fail (PIKA_IS_PIKA (pika)); g_return_if_fail (pika_controller_manager_get (pika) != NULL); g_object_set_data (G_OBJECT (pika), PIKA_CONTROLLER_MANAGER_DATA_KEY, NULL); g_type_class_unref (g_type_class_peek (PIKA_TYPE_CONTROLLER_WHEEL)); g_type_class_unref (g_type_class_peek (PIKA_TYPE_CONTROLLER_KEYBOARD)); } void pika_controllers_restore (Pika *pika, PikaUIManager *ui_manager) { PikaControllerManager *manager; GFile *file; GError *error = NULL; g_return_if_fail (PIKA_IS_PIKA (pika)); g_return_if_fail (PIKA_IS_UI_MANAGER (ui_manager)); manager = pika_controller_manager_get (pika); g_return_if_fail (manager != NULL); g_return_if_fail (manager->ui_manager == NULL); manager->ui_manager = ui_manager; file = pika_directory_file ("controllerrc", NULL); if (pika->be_verbose) g_print ("Parsing '%s'\n", pika_file_get_utf8_name (file)); if (! pika_config_deserialize_file (PIKA_CONFIG (manager->controllers), file, NULL, &error)) { if (error->code == PIKA_CONFIG_ERROR_OPEN_ENOENT) { g_clear_error (&error); g_object_unref (file); if (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR")) { gchar *path; path = g_build_filename (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"), "etc", "controllerrc", NULL); file = g_file_new_for_path (path); g_free (path); } else { file = pika_sysconf_directory_file ("controllerrc", NULL); } if (! pika_config_deserialize_file (PIKA_CONFIG (manager->controllers), file, NULL, &error)) { pika_message_literal (pika, NULL, PIKA_MESSAGE_ERROR, error->message); } } else { pika_message_literal (pika, NULL, PIKA_MESSAGE_ERROR, error->message); } g_clear_error (&error); } pika_list_reverse (PIKA_LIST (manager->controllers)); g_object_unref (file); } void pika_controllers_save (Pika *pika) { const gchar *header = "PIKA controllerrc\n" "\n" "This file will be entirely rewritten each time you exit."; const gchar *footer = "end of controllerrc"; PikaControllerManager *manager; GFile *file; GError *error = NULL; g_return_if_fail (PIKA_IS_PIKA (pika)); manager = pika_controller_manager_get (pika); g_return_if_fail (manager != NULL); file = pika_directory_file ("controllerrc", NULL); if (pika->be_verbose) g_print ("Writing '%s'\n", pika_file_get_utf8_name (file)); if (! pika_config_serialize_to_file (PIKA_CONFIG (manager->controllers), file, header, footer, NULL, &error)) { pika_message_literal (pika, NULL, PIKA_MESSAGE_ERROR, error->message); g_error_free (error); } g_object_unref (file); } PikaContainer * pika_controllers_get_list (Pika *pika) { PikaControllerManager *manager; g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL); manager = pika_controller_manager_get (pika); g_return_val_if_fail (manager != NULL, NULL); return manager->controllers; } PikaUIManager * pika_controllers_get_ui_manager (Pika *pika) { PikaControllerManager *manager; g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL); manager = pika_controller_manager_get (pika); g_return_val_if_fail (manager != NULL, NULL); return manager->ui_manager; } PikaController * pika_controllers_get_wheel (Pika *pika) { PikaControllerManager *manager; g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL); manager = pika_controller_manager_get (pika); g_return_val_if_fail (manager != NULL, NULL); return manager->wheel; } PikaController * pika_controllers_get_keyboard (Pika *pika) { PikaControllerManager *manager; g_return_val_if_fail (PIKA_IS_PIKA (pika), NULL); manager = pika_controller_manager_get (pika); g_return_val_if_fail (manager != NULL, NULL); return manager->keyboard; } /* private functions */ static PikaControllerManager * pika_controller_manager_get (Pika *pika) { return g_object_get_data (G_OBJECT (pika), PIKA_CONTROLLER_MANAGER_DATA_KEY); } static void pika_controller_manager_free (PikaControllerManager *manager) { pika_container_remove_handler (manager->controllers, manager->event_mapped_id); g_clear_object (&manager->controllers); g_slice_free (PikaControllerManager, manager); } static void pika_controllers_add (PikaContainer *container, PikaControllerInfo *info, PikaControllerManager *manager) { if (PIKA_IS_CONTROLLER_WHEEL (info->controller)) manager->wheel = info->controller; else if (PIKA_IS_CONTROLLER_KEYBOARD (info->controller)) manager->keyboard = info->controller; } static void pika_controllers_remove (PikaContainer *container, PikaControllerInfo *info, PikaControllerManager *manager) { if (info->controller == manager->wheel) manager->wheel = NULL; else if (info->controller == manager->keyboard) manager->keyboard = NULL; } static gboolean pika_controllers_event_mapped (PikaControllerInfo *info, PikaController *controller, const PikaControllerEvent *event, const gchar *action_name, PikaControllerManager *manager) { GList *list; for (list = pika_ui_manager_get_action_groups (manager->ui_manager); list; list = g_list_next (list)) { PikaActionGroup *group = list->data; PikaAction *action; action = pika_action_group_get_action (group, action_name); if (action) { switch (event->type) { case PIKA_CONTROLLER_EVENT_VALUE: if (G_VALUE_HOLDS_DOUBLE (&event->value.value) && PIKA_IS_ENUM_ACTION (action) && PIKA_ENUM_ACTION (action)->value_variable) { gdouble value = g_value_get_double (&event->value.value); pika_action_emit_activate (PIKA_ACTION (action), g_variant_new_int32 (value * 1000)); break; } /* else fallthru */ case PIKA_CONTROLLER_EVENT_TRIGGER: default: pika_action_activate (action); break; } return TRUE; } } return FALSE; }