#include <memory>
#include <vector>
#include <string>
+#include <cmath>
static const double GENGRID_ITEM_HEIGHT_WIDTH_PROPORTION = 1.2;
static const int ITEMS_IN_GENGRID_PER_ROW = 4;
void removeMenu();
bool isMenuShown() const;
void createMenuContent();
+ Rectangle calculateMenuGeometry();
+ Size calculateMenuItemSize();
+ std::string findActivityInMenu(int x, int y);
void addBackButton(Evas_Object *);
void refreshMenu();
void navigateThroughSubMenuOrCreateActivityChangeRequest(MenuItem *);
void sendTapActivityChangeRequest();
std::string getCompleteLabelOfMenu();
std::string getCompleteLabelOfMainMenu();
- Optional<telephony_call_state_e> getPhoneCallState();
+ Optional<telephony_call_status_e> getPhoneCallState();
bool isRealUIElementSlider();
bool hasRealUIElementEditableTextIface();
std::string getCompleteLabelOfButtonsKeysMenu();
Optional<bool> realUiElementHasEditableText;
std::unique_ptr<Evas_Object, void(*)(Evas_Object *)> popup;
std::unique_ptr<Evas_Object, void(*)(Evas_Object *)> virtualBackButton;
- std::unique_ptr<DBus::DBusClient> dbusClient;
+ DBus::DBusClient dbusClient;
+ DBus::DBusClient dbusClient2;
VConfInterface::CallbackHandle autoTapWaitingPeriodCallbackHandle;
ecore::Timer timer;
double autoTapWaitingPeriod;
DoneCallback activityDoneCallback;
+ std::string checkedMenuItem;
};
SelectActivity::SelectActivity(): UIActivity(activityType), popup(nullptr, evas_object_del),
- virtualBackButton(nullptr, evas_object_del), autoTapWaitingPeriod(AUTO_TAP_WAITING_PERIOD_DEFAULT_TIME) {}
+ virtualBackButton(nullptr, evas_object_del), autoTapWaitingPeriod(AUTO_TAP_WAITING_PERIOD_DEFAULT_TIME)
+{
+ // TODO: Creating dbusClient2 is an ugly way to make signals below work properly.
+ // This TEMPORARY solution must be removed during refactor of SelectActivity.
+ dbusClient2 = DBus::DBusClient{dbusLocators::accessibilityEMod::BUS, dbusLocators::accessibilityEMod::OBJ_PATH, dbusLocators::accessibilityEMod::INTERFACE, DBus::ConnectionType::SYSTEM};
+
+ dbusClient2.addSignal<void(int, int)>(dbusLocators::accessibilityEMod::MENU_MOUSE_DOWN_SIGNAL, [this](auto x, auto y) {
+ checkedMenuItem = this->findActivityInMenu(x, y);
+ });
+ dbusClient2.addSignal<void(int, int)>(dbusLocators::accessibilityEMod::MENU_MOUSE_UP_SIGNAL, [this](auto x, auto y) {
+ auto act = this->findActivityInMenu(x, y);
+ if (act == checkedMenuItem) {
+ for (auto &it : gengridItemsData) {
+ if (it.first->getName() == act) {
+ this->navigateThroughSubMenuOrCreateActivityChangeRequest(it.first.get());
+ }
+ }
+ }
+ checkedMenuItem = {};
+ });
+}
+
SelectActivity::~SelectActivity()
{
screenScannerManager->cancelForcingScanningMethod();
if (isMenuShown()) {
ASSERT(!realUiElements.empty());
- notify(std::make_shared<ActivityChangeRequest>("TAP", std::vector<std::shared_ptr<UIElement>> {elem})); /*elem is popup menu item*/
+ elem->activate({});
return;
}
return;
}
+ auto navIface = Singleton<UniversalSwitch>::instance().getNavigationInterface();
+ if (navIface)
+ navIface->setUIPresence(true);
+
auto window = Singleton<UniversalSwitch>::instance().getMainWindow()->getHandler();
popup.reset(elm_popup_add(window));
- elm_win_render(window);
evas_object_smart_callback_add(popup.get(), "dismissed", popupDismissedCb, this);
menu = Singleton<MenuBuilder>::instance().build(getCompleteLabelOfMenu());
- elm_popup_orient_set(popup.get(), menu->getAlignment() == Alignment::BOTTOM ? ELM_POPUP_ORIENT_BOTTOM : ELM_POPUP_ORIENT_CENTER);
elm_theme_extension_add(NULL, UNIVERSAL_SWITCH_EDJ);
elm_atspi_accessible_attribute_append(popup.get(), "ScanningMethod", "RowScanner");
elm_atspi_accessible_attribute_append(popup.get(), "EscapeFrameEnabled", "true");
+ elm_popup_orient_set(popup.get(), menu->getAlignment() == Alignment::BOTTOM ? ELM_POPUP_ORIENT_BOTTOM : ELM_POPUP_ORIENT_CENTER);
createMenuContent();
- dbusClient = std::make_unique<DBus::DBusClient>(dbusLocators::accessibilityEMod::BUS,
- dbusLocators::accessibilityEMod::OBJ_PATH, dbusLocators::accessibilityEMod::INTERFACE, DBus::ConnectionType::SYSTEM);
- dbusClient->method<void(bool)>(dbusLocators::accessibilityEMod::BACK_BUTTON_INTERCEPTION_ENABLED).call(true);
- dbusClient->addSignal<void()>(dbusLocators::accessibilityEMod::BACK_BUTTON_UP_SIGNAL, [this]() {
+ dbusClient = DBus::DBusClient{dbusLocators::accessibilityEMod::BUS,
+ dbusLocators::accessibilityEMod::OBJ_PATH, dbusLocators::accessibilityEMod::INTERFACE, DBus::ConnectionType::SYSTEM};
+ dbusClient.method<void(bool)>(dbusLocators::accessibilityEMod::BACK_BUTTON_INTERCEPTION_ENABLED).call(true);
+ dbusClient.addSignal<void()>(dbusLocators::accessibilityEMod::BACK_BUTTON_UP_SIGNAL, [this]() {
markAsCompleted();
removeMenu();
});
- Singleton<UniversalSwitch>::instance().getMainWindow()->acceptTouchInput(true);
+ elm_win_render(Singleton<UniversalSwitch>::instance().getMainWindow()->getHandler());
+ auto geo = calculateMenuGeometry();
+ dbusClient.method<void(bool)>(dbusLocators::accessibilityEMod::MENU_IS_SHOWN).call(true, geo.position.x, geo.position.y, geo.size.width, geo.size.height);
+
evas_object_show(popup.get());
timer.reset();
}
void SelectActivity::removeMenu()
{
- Singleton<UniversalSwitch>::instance().getMainWindow()->acceptTouchInput(false);
callbackHandle.reset();
for (auto &e : gengridItemsData)
timer.reset();
if (dbusClient) {
- dbusClient->method<void(bool)>(dbusLocators::accessibilityEMod::BACK_BUTTON_INTERCEPTION_ENABLED).call(false);
- dbusClient.reset();
+ dbusClient.method<void(bool)>(dbusLocators::accessibilityEMod::BACK_BUTTON_INTERCEPTION_ENABLED).call(false);
+ dbusClient.method<void(bool)>(dbusLocators::accessibilityEMod::MENU_IS_SHOWN).call(false, 0, 0, 0, 0);
+ dbusClient = {};
}
+
+ auto navIface = Singleton<UniversalSwitch>::instance().getNavigationInterface();
+ if (navIface)
+ navIface->setUIPresence(false);
}
void SelectActivity::createMenuContent()
{
auto content = elm_layout_add(popup.get());
elm_layout_file_set(content, UNIVERSAL_SWITCH_EDJ, "universalSwitchTransparentLayout");
- evas_object_size_hint_min_set(content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_weight_set(content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(content, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+ elm_win_render(Singleton<UniversalSwitch>::instance().getMainWindow()->getHandler());
+ auto geo = calculateMenuGeometry();
+ evas_object_geometry_set(content, 0, 0, geo.size.width, geo.size.height);
+
elm_object_content_set(popup.get(), content);
- auto screenWidth = 0;
- evas_object_geometry_get(content, nullptr, nullptr, &screenWidth, nullptr);
- auto itemSize = Size {screenWidth / ITEMS_IN_GENGRID_PER_ROW,
- static_cast<int>(screenWidth *GENGRID_ITEM_HEIGHT_WIDTH_PROPORTION / ITEMS_IN_GENGRID_PER_ROW)};
+ auto itemSize = calculateMenuItemSize();
auto gengrid = elm_gengrid_add(content);
elm_object_style_set(gengrid, "popup");
addBackButton(content);
}
+Rectangle SelectActivity::calculateMenuGeometry()
+{
+ using EinaListDestr = Eina_List * (*)(Eina_List *);
+
+ //FIXME: Calculations below base on constant hierarchy of objects and probably should be done without
+ // asking for accessible tree nodes.
+
+ std::unique_ptr<Eina_List, EinaListDestr> children_1(elm_atspi_accessible_children_get(popup.get()), eina_list_free);
+ auto chld = static_cast<Eo *>(eina_list_nth(children_1.get(), 0));
+
+ std::unique_ptr<Eina_List, EinaListDestr> children_2(elm_atspi_accessible_children_get(chld), eina_list_free);
+ chld = static_cast<Eo *>(eina_list_nth(children_2.get(), 1));
+
+ int x, y, w, h;
+ evas_object_geometry_get(chld, &x, &y, &w, &h);
+
+ return {{x, y}, {w, h}};
+}
+
+Size SelectActivity::calculateMenuItemSize()
+{
+ auto geo = calculateMenuGeometry();
+ return Size {geo.size.width / ITEMS_IN_GENGRID_PER_ROW, static_cast<int>(geo.size.width *GENGRID_ITEM_HEIGHT_WIDTH_PROPORTION / ITEMS_IN_GENGRID_PER_ROW)};
+}
+
+std::string SelectActivity::findActivityInMenu(int x, int y)
+{
+ auto menuGeo = calculateMenuGeometry();
+ auto itemSize = calculateMenuItemSize();
+
+ auto itemsNo = gengridItemsData.size();
+
+ auto fakeElem = Rectangle{{menuGeo.position.x, menuGeo.position.y}, {itemSize}};
+
+ for (auto i = 0u; i < itemsNo; ++i) {
+ if (x > fakeElem.position.x && x < fakeElem.position.x + itemSize.width && y > fakeElem.position.y && y < fakeElem.position.y + itemSize.height)
+ return gengridItemsData[i].first->getName();
+
+ if ((i + 1) % ITEMS_IN_GENGRID_PER_ROW == 0) {
+ fakeElem.position.x = menuGeo.position.x;
+ fakeElem.position.y += itemSize.height;
+ } else {
+ fakeElem.position.x += itemSize.width;
+ }
+ }
+
+ return {};
+}
+
void SelectActivity::addBackButton(Evas_Object *content)
{
virtualBackButton.reset(elm_button_add(content));
void SelectActivity::navigateThroughSubMenuOrCreateActivityChangeRequest(MenuItem *menuItem)
{
- DEBUG("element %s", menuItem->getName().c_str());
-
if (menuItem->getName().empty())
return;
{
auto phoneCallState = getPhoneCallState();
- if (phoneCallState && *phoneCallState == TELEPHONY_CALL_STATE_CONNECTED)
+ if (phoneCallState && *phoneCallState == TELEPHONY_CALL_STATUS_ACTIVE)
return "IDS_MENU_MAIN_DURING_CALL";
- if (phoneCallState && *phoneCallState == TELEPHONY_CALL_STATE_CONNECTING)
+ if (phoneCallState && *phoneCallState == TELEPHONY_CALL_STATUS_INCOMING)
return "IDS_MENU_MAIN_INCOMING_CALL";
if (realUiElements[0]->getApplicationCategory() == UIElement::ApplicationCategory::HOMESCREEN)
return "IDS_MENU_MAIN_NORMAL";
}
-Optional<telephony_call_state_e> SelectActivity::getPhoneCallState()
+Optional<telephony_call_status_e> SelectActivity::getPhoneCallState()
{
telephony_handle_list_s list;
auto error = telephony_init(&list);
}
for (auto i = 0u; i < list.count; i++) {
- telephony_call_state_e callState;
- error = telephony_call_get_voice_call_state(list.handle[i], &callState);
+ telephony_call_h *callList;
+ unsigned int callCount;
+
+ error = telephony_call_get_call_list(list.handle[i], &callCount, &callList);
if (error != TELEPHONY_ERROR_NONE) {
- ERROR("Can't get call state. Error no. %d", error);
+ ERROR("Can't get call list. Error no. %d", error);
break;
}
- if (callState != TELEPHONY_CALL_STATE_IDLE) {
- telephony_deinit(&list);
- return callState;
+ for (auto k = 0u; k < callCount; ++k) {
+ telephony_call_status_e callState;
+ error = telephony_call_get_status(callList[i], &callState);
+ if (error != TELEPHONY_ERROR_NONE) {
+ ERROR("Can't get call state. Error no. %d", error);
+ break;
+ }
+
+ if (callState != TELEPHONY_CALL_STATUS_IDLE) {
+ telephony_deinit(&list);
+ return callState;
+ }
}
}
telephony_deinit(&list);
- return TELEPHONY_CALL_STATE_IDLE;
+ return TELEPHONY_CALL_STATUS_IDLE;
}
bool SelectActivity::isRealUIElementSlider()
void SelectActivity::gengridItemSelected(Elm_Gengrid_Item *item)
{
elm_gengrid_item_selected_set(item, EINA_FALSE);
- for (auto &e : gengridItemsData)
+ for (auto &e : gengridItemsData) {
if (e.second == item) {
navigateThroughSubMenuOrCreateActivityChangeRequest(e.first.get());
break;
}
+ }
}
void SelectActivity::popupDismissedCb(void *data, Evas_Object *obj, void *event_info)
Edje_Message_Int msg = {0, };
msg.val = value;
edje_object_message_send(elm_layout_edje_get(layout), EDJE_MESSAGE_INT, 0, &msg);
-}
\ No newline at end of file
+}
#include "UniversalSwitchLog.hpp"
#include "Window.hpp"
-#include "Ecore_Wayland.h"
+#include <Ecore_Wl2.h>
Window::Window()
: handler(nullptr, removeHandler)
}
handler.reset(windowHandler);
- waylandWindow = elm_win_wl_window_get(windowHandler);
+ auto ee = ecore_evas_ecore_evas_get(evas_object_evas_get(windowHandler));
+ waylandWindow = ecore_evas_wayland2_window_get(ee);
// TODO: name setter should be removed after reaching full functionality by navigation interface
elm_atspi_accessible_name_set(windowHandler, "UniversalSwitch Main Window");
- efl_util_set_notification_window_level(windowHandler, EFL_UTIL_NOTIFICATION_LEVEL_3);
+ efl_util_set_notification_window_level(windowHandler, EFL_UTIL_NOTIFICATION_LEVEL_TOP);
elm_win_alpha_set(windowHandler, EINA_TRUE);
auto size = getDimensions().size;
evas_object_resize(windowHandler, size.width, size.height);
int rotations[] = {0, 90, 270};
elm_win_wm_rotation_available_rotations_set(windowHandler, rotations, 3);
+
evas_object_show(windowHandler);
- acceptTouchInput(false);
+ Eina_Rectangle rect = {0, 0, 0, 0};
+
+ ecore_wl2_window_input_rect_set(waylandWindow, &rect);
+
+ waiveTouchInput();
auto status = efl_util_set_window_screen_mode(windowHandler, EFL_UTIL_SCREEN_MODE_ALWAYS_ON);
if (status)
return quickpanel.get();
}
-void Window::acceptTouchInput(bool state)
+void Window::waiveTouchInput()
{
- elm_win_override_set(handler.get(), state ? EINA_FALSE : EINA_TRUE);
- ecore_wl_window_focus_skip_set(waylandWindow, state ? EINA_FALSE : EINA_TRUE);
- auto size = 0;
- if (state) {
- auto dimensions = getDimensions();
- size = std::max(dimensions.size.width, dimensions.size.height);
- }
-
- ecore_wl_window_input_region_set(waylandWindow, 0, 0, size, size);
+ elm_win_override_set(handler.get(), EINA_TRUE);
+ ecore_wl2_window_focus_skip_set(waylandWindow, EINA_TRUE);
+ Eina_Rectangle rect = {0, 0, 0, 0};
+ ecore_wl2_window_input_rect_set(waylandWindow, &rect);
}