Languages

Menu
Sites
Language
윈도우를 이동시키는 방법

안녕하세요. !

현재 윈도우를 투명하게 만들고, 사이즈를 줄여 위젯처럼 사용하게 하려고 합니다.

ad->win = elm_win_add(NULL, "HappyPuppy", ELM_WIN_NOTIFICATION);

error = efl_util_set_notification_window_level(ad->win, EFL_UTIL_NOTIFICATION_LEVEL_2);

 

이 때 드래그를 통해 윈도우를 이동시키고 싶은데 잘 되지 않아 질문 드립니다.

제가 사용하고 있는 방법은 현재 마우스 포인터 좌표값을 읽고, 윈도우를 이동시키는 방법을 사용하고 있습니다.

evas_pointer_canvas_xy_get(evas_object_evas_get(ad->win), &mx, &my);
evas_object_move(ad->win, mx, my);

 

edc에서 dragable 을 사용하는 방법을 해보려고 했는데, 그건 윈도우 내에 포함되어 있는 오브젝트에게만 적용되는 것 같아서 위의 방법을 생각해보았습니다.

이런 방식으로 처리하니, 다음과 같은 문제점이 생겼습니다.

 

1. 윈도우가 이동하지만, 매끄럽지 않습니다.

2. 마우스 좌표값이 튀는 현상이 발생합니다.

3. 손이 이동하는 만큼 좌표값이 변하지 않습니다. (변화폭이 작습니다.)

4. 클릭을 했을 경우 어떤 고정된 위치로 돌아갑니다.

 

짧지만 설명을 더하기 위해, 영상을 준비해보았습니다.

 

감사합니다.

 

---------------------------------

죄송합니다. 본문에 영상을 올릴려고 시도하다가 계속 안되어, 댓글에 올렸는데 시도한 것들이 삭제가 안되네요.

Edited by: 시언 박 on 06 Aug, 2015
View Selected Answer

Responses

11 Replies
시언 박

[video:https://www.youtube.com/watch?v=OKSzO78G_mE&feature=youtu.be]

 

시언 박

[video:https://www.youtube.com/watch?v=OKSzO78G_mE&feature=youtu.be]

 

시언 박

https://www.youtube.com/watch?v=OKSzO78G_mE&feature=youtu.be

시언 박

<iframe width="560" height="315" src="https://www.youtube.com/embed/OKSzO78G_mE" frameborder="0" allowfullscreen></iframe>

시언 박

시언 박

계속 테스트를 해보고 있는데요, 이번엔 스레드로 해당 부분을 처리해보았는데 결과는 같았습니다.

그래서 evas_pointer_output_xy() 를 통해 얻은 좌표를 가지고 evas_object_move()를 해주는 것이 아닌가 싶어서, 

앱 안에 있는 버튼 객체를 이동시켰는데, 나름 부드럽게 잘 됩니다.

윈도우 자체는 다른 방법을 써야하는건지.. 참 난감하네요.

시언 박

테스트 하고 있는 소스입니다...;; 

#include <tizen.h>
#include "aaaaaaa.h"
#include <Evas.h>
#include <efl_util.h>
typedef struct appdata {
    Evas_Object *win;
	Evas_Object *conform;
	Evas_Object *label;
	Evas_Object *btn;
	Evas_Object *img;
	Ecore_Thread *thread;
} appdata_s;

static void
win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
{
	ui_app_exit();
}

static void
win_back_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = data;
	/* Let window go to hide state. */
	elm_win_lower(ad->win);
}
void clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
   dlog_print(DLOG_DEBUG, LOG_TAG, "--->Button clicked\n");
}

typedef struct user_data{
	Evas_Object *obj;
	int x;
	int y;
} user_data;

static void _thread_run_cb(void *data, Ecore_Thread *thread)
{
	appdata_s *ad = data;
	Evas_Object *win = ad->win;
	Evas *e = evas_object_evas_get(win);
	int mx = 0, my = 0;

	dlog_print(DLOG_DEBUG, LOG_TAG, "---->Thread Start\n");
	while(1)
	{
		evas_pointer_canvas_xy_get(e, &mx, &my);
		user_data *ud = malloc(sizeof(user_data));
		ud->obj = win;
		ud->x = mx;
		ud->y = my;

		ecore_thread_feedback(thread, ud);
		usleep(30000);

		if (ecore_thread_check(thread))
			return;

	}
}

static void _thread_feedback_cb(void *data, Ecore_Thread *thead, void *msg)
{
	user_data *ud = msg;
	evas_object_move(ud->obj, ud->x, ud->y);
	free(ud);
}

static void _thread_end_cb(void *data, Ecore_Thread *thread)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "---->Thread End\n");
}

static void _thread_cancel_cb(void *data, Ecore_Thread *thread)
{
	dlog_print(DLOG_DEBUG, LOG_TAG, "---->Thread Cancel\n");
}


Eina_Bool isPressed = EINA_FALSE;

void pressed_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = data;
   dlog_print(DLOG_DEBUG, LOG_TAG, "---->Button pressed\n");

   if(!isPressed){
	   isPressed = EINA_TRUE;
	   ad->thread = ecore_thread_feedback_run(_thread_run_cb, _thread_feedback_cb, _thread_end_cb, _thread_cancel_cb, ad, EINA_TRUE);
	}

   dlog_print(DLOG_DEBUG, LOG_TAG, "--------------> clicked !!!!!!!!");
}

void unpressed_cb(void *data, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = data;
	if(isPressed)
	{
		isPressed = EINA_FALSE;
		if(ad->thread)
			ecore_thread_cancel(ad->thread);

		dlog_print(DLOG_DEBUG, LOG_TAG, "----> Thread Cancel\n");
	}
   dlog_print(DLOG_DEBUG, LOG_TAG, "----> Button Unpressed\n");
}

static void
create_base_gui(appdata_s *ad)
{
	/* Window */
	ad->win = elm_win_add(NULL, "HappyPuppy", ELM_WIN_NOTIFICATION);

	if (!ad->win) return;

	elm_win_conformant_set(ad->win, EINA_TRUE);
	elm_win_alpha_set(ad->win, EINA_TRUE);
	elm_win_override_set(ad->win, EINA_TRUE);
	elm_win_autodel_set(ad->win, EINA_TRUE);

	// Set notification level
	 efl_util_set_notification_window_level(ad->win, EFL_UTIL_NOTIFICATION_LEVEL_2);

	elm_win_autodel_set(ad->win, EINA_TRUE);
	evas_object_move(ad->win, 50, 50);
	evas_object_resize(ad->win, 300, 300);

	evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);
	eext_object_event_callback_add(ad->win, EEXT_CALLBACK_BACK, win_back_cb, ad);

	/* Conformant */
	ad->conform = elm_conformant_add(ad->win);
	elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
	elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE);
	evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	elm_win_resize_object_add(ad->win, ad->conform);
	evas_object_show(ad->conform);

	ad->btn = elm_button_add(ad->conform);
	evas_object_move(ad->btn, 100,100);
	evas_object_resize(ad->btn, 100, 100);
	elm_win_floating_mode_set(ad->win, EINA_TRUE);
	evas_object_show(ad->btn);

	elm_button_autorepeat_set(ad->btn, EINA_TRUE);
	elm_button_autorepeat_gap_timeout_set(ad->btn, 1);

	evas_object_smart_callback_add(ad->btn, "clicked", clicked_cb, ad);
	evas_object_smart_callback_add(ad->btn, "repeated", pressed_cb, ad);
	evas_object_smart_callback_add(ad->btn, "unpressed", unpressed_cb, ad);

	//	evas_object_event_callback_add(ad->img, EVAS_CALLBACK_MOUSE_MOVE, pressed_cb, ad);

	/* Show window after base gui is set up */
	evas_object_show(ad->win);
}

static bool
app_create(void *data)
{
	appdata_s *ad = data;
	create_base_gui(ad);
	return true;
}

static void app_control(app_control_h app_control, void *data){}
static void app_pause(void *data){}
static void app_resume(void *data){}
static void app_terminate(void *data){}
static void ui_app_lang_changed(app_event_info_h event_info, void *user_data){
	char *locale = NULL;
	system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale);
	elm_language_set(locale);
	free(locale);
	return;
}
static void ui_app_orient_changed(app_event_info_h event_info, void *user_data){}
static void ui_app_region_changed(app_event_info_h event_info, void *user_data){}
static void ui_app_low_battery(app_event_info_h event_info, void *user_data){}
static void ui_app_low_memory(app_event_info_h event_info, void *user_data){}
int main(int argc, char *argv[])
{
	appdata_s ad = {0,};
	int ret = 0;

	ui_app_lifecycle_callback_s event_callback = {0,};
	app_event_handler_h handlers[5] = {NULL, };

	event_callback.create = app_create;
	event_callback.terminate = app_terminate;
	event_callback.pause = app_pause;
	event_callback.resume = app_resume;
	event_callback.app_control = app_control;

	ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, ui_app_low_battery, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, ui_app_low_memory, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, ui_app_orient_changed, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, ui_app_lang_changed, &ad);
	ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, ui_app_region_changed, &ad);
	ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]);

	ret = ui_app_main(argc, argv, &event_callback, &ad);
	if (ret != APP_ERROR_NONE) {
		dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);
	}

	return ret;
}

 

시언 박

이게 계속 테스트를 하다 보니까, evas_object_move의 문제가 아니라 evas_pointer_output_xy_get()의 값이 튀어서 생기는 문제라고 생각됩니다.
마우스 값을 가져오기 않고,  +1 을 해주는 변수값으로 이동을 시켰을 때 부드럽게 이동이 되었습니다.

그래서 이번엔 칼만 필터를 적용해보았습니다.

 

 

부드럽게 되는데, 제자리에서 가속도처럼 이동하네요,, 이제 어떻게 해야할지 또 고민에 빠져봅니다.

시언 박

하.. 드디어 문제를 해결했습니다!!

 

 

칼만필터를 천천히 보다가, 해결했습니다. ^^ 감사합니다~

Mark as answer
pius lee

으윽....

이걸 해결하시기 위해 칼만 필터까지 보셧다니, 오버테크놀러지네요. 칼만필터 쓰지 마세요. 값이 튀지 않습니다.

지금 처하신 상황은 값이 튀는게 아니라, 마우스 좌표값을 잘못 해석 하셨기 때문입니다.

window의 position과 최초 클릭시 position, 그리고 움직였을때 position을 잘 계산 하셔야 합니다.

그리고 event안에서 바로 움직이는게 아니라 하신대로 스레드로 해도 되지만, 훨씬 간단하게 그냥 event loop를 사용하게, ecore animation 을 사용하면 아주 간단해 집니다.

다음 코드는 제가 간단하게 짜본 이미지 붙인 window를 손으로 움직이는 소스 입니다. _drag_anim_play 부분을 보시면 이해 가실 것이라 생각이 듭니다.

#include "testwindowmove.h"
#include <efl_util.h>

typedef struct appdata {
    Evas_Object *win;

	Evas_Coord cx;
	Evas_Coord cy;

	Ecore_Animator *ea;

	Evas *evas;
} appdata_s;

static Eina_Bool _drag_anim_play(void *data)
{
	appdata_s *ad = data;

	int x,y, tx, ty;
	elm_win_screen_position_get(ad->win, &x, &y);
	evas_pointer_output_xy_get(ad->evas, &tx, &ty);
	evas_object_move(ad->win, x + tx - ad->cx, y + ty - ad->cy);

	return 1;
}

static void _ev_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = data;
	if (ad->ea == NULL)	ad->ea = ecore_animator_add(_drag_anim_play, ad);
	evas_pointer_output_xy_get(ad->evas, &ad->cx, &ad->cy);
}
static void _ev_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
	appdata_s *ad = data;
	ecore_animator_del(ad->ea);
	ad->ea = NULL;
}

static void create_base_gui(appdata_s *ad)
{
	ad->win = elm_win_add(NULL, "HappyPuppy", ELM_WIN_BASIC);
	efl_util_set_notification_window_level(ad->win, EFL_UTIL_NOTIFICATION_LEVEL_2);
	elm_win_alpha_set(ad->win, EINA_TRUE);
	evas_object_resize(ad->win, 100, 100);
	elm_win_override_set(ad->win, EINA_TRUE);

	char path[256] = {0,};
	char *resdir = app_get_resource_path();
	strcat(path, resdir);
	strcat(path, "cow.png");
	free(resdir);

	Evas_Object *bg = elm_image_add(ad->win);
	elm_image_file_set(bg, path, NULL);
	elm_win_resize_object_add(ad->win, bg);
	evas_object_show(bg);

	ad->evas = evas_object_evas_get(ad->win);
	evas_object_event_callback_add(bg, EVAS_CALLBACK_MOUSE_DOWN, _ev_down, ad);
	evas_object_event_callback_add(bg, EVAS_CALLBACK_MOUSE_UP, _ev_up, ad);

	evas_object_show(ad->win);
}

static bool app_create(void *data)
{
	appdata_s *ad = data;

	create_base_gui(ad);

	return true;
}

int main(int argc, char *argv[])
{
	appdata_s ad = {0,};
	int ret = 0;

	ui_app_lifecycle_callback_s event_callback = {0,};
	event_callback.create = app_create;
	ret = ui_app_main(argc, argv, &event_callback, &ad);
	return ret;
}

 

시언 박

;;..;; 저..바본가보네요 ㅠㅠ

 

감사합니다 !