From: jinhyung.jo Date: Wed, 14 Jan 2015 10:05:16 +0000 (+0900) Subject: Direct Rendering: New feature added X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.2~591 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c1636d620372cea284a2cec0299e1ee8d9580965;p=sdk%2Femulator%2Fqemu.git Direct Rendering: New feature added Modified the vigs & the yagl device for the direct rendering Added Qt5 UI for the direct rendering This is a compressed many commits produced by several authors below into one. Change-Id: I455f607c363851c57d0a250f1220ede6027e1ea0 Signed-off-by: GiWoong Kim Signed-off-by: Stanislav Vorobiov Signed-off-by: Vasiliy Ulyanov Signed-off-by: SungMin Ha Signed-off-by: hyunjin816.lee Signed-off-by: Munkyu Im Signed-off-by: SeokYeon Hwang Signed-off-by: Jinhyung Jo --- diff --git a/configure b/configure index 0a54bb8fb3..8ad78b87a0 100755 --- a/configure +++ b/configure @@ -337,6 +337,8 @@ libav="no" libpng="no" dxva2="no" vaapi="no" +qt="no" +qtabi="5.0" # glusterfs="" glusterfs_discard="no" @@ -1144,6 +1146,10 @@ for opt do ;; --enable-vaapi) vaapi="yes" ;; + --disable-qt) qt="no" + ;; + --enable-qt) qt="yes" + ;; # --disable-glusterfs) glusterfs="no" ;; @@ -1337,6 +1343,8 @@ Advanced options (experts only): --disable-gtk disable gtk UI --enable-gtk enable gtk UI --with-gtkabi select preferred GTK ABI 2.0 or 3.0 + --disable-qt disable Qt5 UI + --enable-qt enable Qt5 UI --disable-virtfs disable VirtFS --enable-virtfs enable VirtFS --disable-vnc disable VNC @@ -2177,6 +2185,42 @@ if test "$vte" != "no"; then fi fi +########################################## +# Qt probe + +qtversion="" +if test "$qt" != "no"; then + if test "$qtabi" = "5.0" ; then + qtpackage="Qt5Widgets Qt5Qml Qt5OpenGL Qt5Gui" + qtversion="5.0.0" + + if $pkg_config --exists "$qtpackage >= $qtversion"; then + qt_cflags=`$pkg_config --cflags $qtpackage` + qt_libs=`$pkg_config --libs $qtpackage` + libs_softmmu="$qt_libs $libs_softmmu" + + qt_cflags_private=`pkg-config --modversion Qt5Gui` + if test "$darwin" = "yes" ; then + qt_cflags_private=`pkg-config --cflags Qt5Gui | sed "s,QtGui.framework/Headers,&/$qt_cflags_private/QtGui,g"` + else + qt_cflags_private=`pkg-config --cflags Qt5Gui | sed "s,QtGui,&/$qt_cflags_private/QtGui,g"` + fi + + qt_cflags="$qt_cflags $qt_cflags_private" + if test "$mingw32" = "no" ; then + qt_cflags="$qt_cflags -fPIC" + fi + qt="yes" + elif test "$qt" = "yes"; then + feature_not_found "qt" "Install qt devel" + else + qt="no" + fi + else + qt="no" + fi +fi + ########################################## # SDL probe @@ -4499,6 +4543,7 @@ fi echo "pixman $pixman" echo "SDL support $sdl" echo "GTK support $gtk" +echo "Qt support $qt" echo "VTE support $vte" echo "curses support $curses" echo "curl support $curl" @@ -4863,6 +4908,10 @@ if test "$vte" = "yes" ; then echo "CONFIG_VTE=y" >> $config_host_mak echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak fi +if test "$qt" = "yes" ; then + echo "CONFIG_QT=y" >> $config_host_mak + echo "QT_CFLAGS=$qt_cflags" >> $config_host_mak +fi if test "$xen" = "yes" ; then echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak diff --git a/hw/vigs/Makefile.objs b/hw/vigs/Makefile.objs index 967bf46e7b..3ebd185f35 100644 --- a/hw/vigs/Makefile.objs +++ b/hw/vigs/Makefile.objs @@ -1,11 +1,11 @@ # VIGS -QEMU_CFLAGS += -I$(SRC_PATH)/hw/vigs/vigs_inc - obj-y += vigs_log.o obj-y += vigs_device.o libs_softmmu += $(GLX_LIBS) obj-y += vigs_comm.o obj-y += vigs_server.o +obj-y += vigs_onscreen_server.o +obj-y += vigs_offscreen_server.o obj-y += vigs_backend.o obj-y += vigs_surface.o obj-y += vigs_utils.o @@ -15,9 +15,16 @@ obj-y += vigs_fenceman.o obj-y += vigs_gl_pool.o obj-y += vigs_gl_backend.o obj-y += vigs_sw_backend.o +obj-$(CONFIG_QT) += vigs_qt5.o +ifndef CONFIG_QT +obj-y += vigs_qt5_stub.o +endif obj-y += work_queue.o obj-y += winsys.o obj-y += display.o + +$(obj)/vigs_qt5.o: QEMU_CFLAGS += $(QT_CFLAGS) + # GL GLX backend ifdef CONFIG_LINUX obj-y += vigs_gl_backend_glx.o @@ -25,8 +32,10 @@ endif # GL WGL backend ifdef CONFIG_WIN32 obj-y += vigs_gl_backend_wgl.o +$(obj)/%.o: QEMU_CFLAGS += -I$(SRC_PATH)/hw/vigs/vigs_inc endif # GL CGL backend ifdef CONFIG_DARWIN obj-y += vigs_gl_backend_cgl.o +$(obj)/%.o: QEMU_CFLAGS += -I$(SRC_PATH)/hw/vigs/vigs_inc endif diff --git a/hw/vigs/display.c b/hw/vigs/display.c index 961e7aa63e..65dae3e45c 100644 --- a/hw/vigs/display.c +++ b/hw/vigs/display.c @@ -1,4 +1,5 @@ #include "display.h" +#include "vigs_qt5.h" #include "qom/object_interfaces.h" #if defined(CONFIG_LINUX) #include @@ -24,7 +25,11 @@ static void displayobject_complete(UserCreatable *obj, Error **errp) XSetErrorHandler(x_error_handler); XInitThreads(); - dobj->dpy = XOpenDisplay(0); + dobj->dpy = (Display*)vigs_qt5_display(); + + if (!dobj->dpy) { + dobj->dpy = XOpenDisplay(0); + } if (!dobj->dpy) { error_setg(errp, "Cannot open X display"); diff --git a/hw/vigs/vigs_backend.h b/hw/vigs/vigs_backend.h index cffcd2bb55..bbbd90abfe 100644 --- a/hw/vigs/vigs_backend.h +++ b/hw/vigs/vigs_backend.h @@ -36,16 +36,6 @@ struct winsys_info; struct vigs_surface; struct vigs_plane; -typedef uint8_t *(*vigs_composite_start_cb)(void */*user_data*/, - uint32_t /*width*/, - uint32_t /*height*/, - uint32_t /*stride*/, - vigsp_surface_format /*format*/); - -typedef void (*vigs_composite_end_cb)(void */*user_data*/, - bool /*was_started*/, - bool /*dirty*/); - struct vigs_backend { struct winsys_info *ws_info; @@ -59,14 +49,19 @@ struct vigs_backend vigsp_surface_format /*format*/, vigsp_surface_id /*id*/); - void (*composite)(struct vigs_surface */*surface*/, + bool (*composite)(struct vigs_surface */*surface*/, const struct vigs_plane */*planes*/, - vigs_composite_start_cb /*start_cb*/, - vigs_composite_end_cb /*end_cb*/, - void */*user_data*/); + bool /*planes_dirty*/, + uint8_t */*display_data*/); + + bool (*capture)(struct vigs_surface */*surface*/, + void */*pixels*/); void (*batch_end)(struct vigs_backend */*backend*/); + bool (*display)(struct vigs_backend */*backend*/, + uint8_t */*display_data*/); + void (*destroy)(struct vigs_backend */*backend*/); }; diff --git a/hw/vigs/vigs_device.c b/hw/vigs/vigs_device.c index 562704bfdc..e2b02c4e78 100644 --- a/hw/vigs/vigs_device.c +++ b/hw/vigs/vigs_device.c @@ -28,10 +28,12 @@ */ #include "vigs_log.h" -#include "vigs_server.h" +#include "vigs_onscreen_server.h" +#include "vigs_offscreen_server.h" #include "vigs_backend.h" #include "vigs_regs.h" #include "vigs_fenceman.h" +#include "vigs_qt5.h" #include "display.h" #include "work_queue.h" #include "winsys.h" @@ -145,6 +147,29 @@ static void vigs_hw_update(void *opaque) } } +static void vigs_hw_display(void *opaque, console_ch_t *text) +{ + VIGSState *s = opaque; + DisplaySurface *ds = qemu_console_surface(s->con); + bool displayed; + + if (!surface_data(ds)) { + return; + } + + if (vigs_server_display(s->server, &displayed)) { + /* + * 'vigs_server_display' could have updated the surface, + * so fetch it again. + */ + ds = qemu_console_surface(s->con); + + dpy_gfx_update(s->con, 0, 0, surface_width(ds), surface_height(ds)); + } + + *text = displayed; +} + static void vigs_hw_invalidate(void *opaque) { VIGSState *s = opaque; @@ -266,10 +291,33 @@ static void vigs_io_write(void *opaque, hwaddr offset, } } +static void vigs_register_capture_request_listener(void *listener, + void (*handler)(void *)) +{ + return vigs_qt5_register_capture_request_listener(listener, handler); +} + +static void vigs_unregister_capture_request_listener(void *listener) +{ + return vigs_qt5_unregister_capture_request_listener(listener); +} + +static void vigs_process_captured(bool captured, void *pixels, + uint32_t width, uint32_t height) +{ + return vigs_qt5_process_captured(captured, pixels, width, height); +} + static struct GraphicHwOps vigs_hw_ops = { .invalidate = vigs_hw_invalidate, - .gfx_update = vigs_hw_update + .gfx_update = vigs_hw_update, + /* + * Hack. use 'graphic_hw_text_update' to do displaying, but + * we have no choice, that's the only way to direct-to-window + * rendering from Qt5. + */ + .text_update = vigs_hw_display, }; static const MemoryRegionOps vigs_io_ops = @@ -288,6 +336,13 @@ static struct vigs_display_ops vigs_dpy_ops = .fence_ack = vigs_fence_ack, }; +static struct vigs_capture_ops capture_ops = +{ + .register_listener = vigs_register_capture_request_listener, + .unregister_listener = vigs_unregister_capture_request_listener, + .process_captured = vigs_process_captured, +}; + static int vigs_device_init(PCIDevice *dev) { VIGSState *s = DO_UPCAST(VIGSState, dev, dev); @@ -421,12 +476,23 @@ static int vigs_device_init(PCIDevice *dev) goto fail; } - s->server = vigs_server_create(memory_region_get_ram_ptr(&s->vram_bar), - memory_region_get_ram_ptr(&s->ram_bar), - &vigs_dpy_ops, - s, - backend, - wqobj->wq); + if (vigs_qt5_onscreen_enabled()) { + s->server = vigs_onscreen_server_create(memory_region_get_ram_ptr(&s->vram_bar), + memory_region_get_ram_ptr(&s->ram_bar), + &vigs_dpy_ops, + &capture_ops, + s, + backend, + wqobj->wq); + } else { + s->server = vigs_offscreen_server_create(memory_region_get_ram_ptr(&s->vram_bar), + memory_region_get_ram_ptr(&s->ram_bar), + &vigs_dpy_ops, + &capture_ops, + s, + backend, + wqobj->wq); + } if (!s->server) { goto fail; @@ -484,7 +550,7 @@ static void vigs_device_exit(PCIDevice *dev) { VIGSState *s = DO_UPCAST(VIGSState, dev, dev); - vigs_server_destroy(s->server); + s->server->destroy(s->server); qemu_bh_delete(s->fence_ack_bh); diff --git a/hw/vigs/vigs_gl_backend.c b/hw/vigs/vigs_gl_backend.c index b27f99a217..e0cb37ee04 100644 --- a/hw/vigs/vigs_gl_backend.c +++ b/hw/vigs/vigs_gl_backend.c @@ -34,25 +34,16 @@ #include "vigs_log.h" #include "vigs_utils.h" #include "vigs_ref.h" +#include "vigs_qt5.h" #include "winsys_gl.h" -#include "work_queue.h" +#include "hw/pci/maru_brightness.h" +#include -struct vigs_gl_surface; - -struct vigs_gl_backend_read_pixels_work_item -{ - struct work_queue_item base; - - struct vigs_gl_backend *backend; +extern uint32_t qt5_window_width; +extern uint32_t qt5_window_height; +extern int qt5_window_angle; - vigs_composite_start_cb start_cb; - vigs_composite_end_cb end_cb; - void *user_data; - uint32_t width; - uint32_t height; - uint32_t stride; - vigsp_surface_format format; -}; +struct vigs_gl_surface; struct vigs_winsys_gl_surface { @@ -203,6 +194,136 @@ static const char *g_fs_color_source_gl3 = " FragColor = color;\n" "}\n"; +static const char *g_fs_dpy_source_gl2 = + "#version 120\n\n" + "uniform sampler2D tex;\n" + "uniform float brightness;\n" + "varying vec2 v_texCoord;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(tex, v_texCoord) * brightness;\n" + "}\n"; + +static const char *g_fs_dpy_source_gl3 = + "#version 140\n\n" + "uniform sampler2D tex;\n" + "uniform float brightness;\n" + "in vec2 v_texCoord;\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = texture(tex, v_texCoord) * brightness;\n" + "}\n"; + +static const char *g_fs_scale_source_gl2 = +"#version 120\n\ +\n\ +uniform sampler2D tex;\n\ +uniform float brightness;\n\ +uniform vec2 texSize;\n\ +varying vec2 v_texCoord;\n\ +vec4 cubic(float x)\n\ +{\n\ + float x2 = x * x;\n\ + float x3 = x2 * x;\n\ + vec4 w;\n\ + w.x = -x3 + 3*x2 - 3*x + 1;\n\ + w.y = 3*x3 - 6*x2 + 4;\n\ + w.z = -3*x3 + 3*x2 + 3*x + 1;\n\ + w.w = x3;\n\ + return w / 6.f;\n\ +}\n\ +void main()\n\ +{\n\ + vec2 texscale = vec2(1.0 / texSize.x, 1.0 / texSize.y);\n\ + vec2 texcoord = vec2(v_texCoord.x * texSize.x, v_texCoord.y * texSize.y);\n\ + float fx = fract(texcoord.x);\n\ + float fy = fract(texcoord.y);\n\ + texcoord.x -= fx;\n\ + texcoord.y -= fy;\n\ +\n\ + vec4 xcubic = cubic(fx);\n\ + vec4 ycubic = cubic(fy);\n\ +\n\ + vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y -\n\ +0.5, texcoord.y + 1.5);\n\ + vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x +\n\ +ycubic.y, ycubic.z + ycubic.w);\n\ + vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) /\n\ +s;\n\ +\n\ + vec4 sample0 = texture2D(tex, vec2(offset.x, offset.z) *\n\ +texscale);\n\ + vec4 sample1 = texture2D(tex, vec2(offset.y, offset.z) *\n\ +texscale);\n\ + vec4 sample2 = texture2D(tex, vec2(offset.x, offset.w) *\n\ +texscale);\n\ + vec4 sample3 = texture2D(tex, vec2(offset.y, offset.w) *\n\ +texscale);\n\ +\n\ + float sx = s.x / (s.x + s.y);\n\ + float sy = s.z / (s.z + s.w);\n\ +\n\ + gl_FragColor = mix(\n\ + mix(sample3, sample2, sx),\n\ + mix(sample1, sample0, sx), sy) * brightness;\n\ +}"; + +static const char *g_fs_scale_source_gl3 = +"#version 140\n\ +\n\ +uniform sampler2D tex;\n\ +uniform float brightness;\n\ +uniform vec2 texSize;\n\ +in vec2 v_texCoord;\n\ +out vec4 FragColor;\n\ +vec4 cubic(float x)\n\ +{\n\ + float x2 = x * x;\n\ + float x3 = x2 * x;\n\ + vec4 w;\n\ + w.x = -x3 + 3*x2 - 3*x + 1;\n\ + w.y = 3*x3 - 6*x2 + 4;\n\ + w.z = -3*x3 + 3*x2 + 3*x + 1;\n\ + w.w = x3;\n\ + return w / 6.f;\n\ +}\n\ +void main()\n\ +{\n\ + vec2 texscale = vec2(1.0 / texSize.x, 1.0 / texSize.y);\n\ + vec2 texcoord = vec2(v_texCoord.x * texSize.x, v_texCoord.y * texSize.y);\n\ + float fx = fract(texcoord.x);\n\ + float fy = fract(texcoord.y);\n\ + texcoord.x -= fx;\n\ + texcoord.y -= fy;\n\ +\n\ + vec4 xcubic = cubic(fx);\n\ + vec4 ycubic = cubic(fy);\n\ +\n\ + vec4 c = vec4(texcoord.x - 0.5, texcoord.x + 1.5, texcoord.y -\n\ +0.5, texcoord.y + 1.5);\n\ + vec4 s = vec4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x +\n\ +ycubic.y, ycubic.z + ycubic.w);\n\ + vec4 offset = c + vec4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) /\n\ +s;\n\ +\n\ + vec4 sample0 = texture(tex, vec2(offset.x, offset.z) *\n\ +texscale);\n\ + vec4 sample1 = texture(tex, vec2(offset.y, offset.z) *\n\ +texscale);\n\ + vec4 sample2 = texture(tex, vec2(offset.x, offset.w) *\n\ +texscale);\n\ + vec4 sample3 = texture(tex, vec2(offset.y, offset.w) *\n\ +texscale);\n\ +\n\ + float sx = s.x / (s.x + s.y);\n\ + float sy = s.z / (s.z + s.w);\n\ +\n\ + FragColor = mix(\n\ + mix(sample3, sample2, sx),\n\ + mix(sample1, sample0, sx), sy) * brightness;\n\ +}"; + static const char *g_vs_nv21_source_gl2 = "#version 120\n\n" "attribute vec4 vertCoord;\n" @@ -614,6 +735,102 @@ static void vigs_gl_draw_color_prog(struct vigs_gl_backend *backend, backend->DisableVertexAttribArray(backend->color_prog_vertCoord_loc); } +static void vigs_gl_draw_dpy_tex_prog(struct vigs_gl_backend *backend, + uint32_t count) +{ + uint32_t size = count * 16; + void *ptr; + + if (size > backend->dpy_vbo_size) { + backend->dpy_vbo_size = size; + backend->BufferData(GL_ARRAY_BUFFER, + size, + 0, + GL_STREAM_DRAW); + } + + if (backend->MapBufferRange) { + ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT); + + if (ptr) { + memcpy(ptr, vigs_vector_data(&backend->dpy_v1), size / 2); + memcpy(ptr + (size / 2), vigs_vector_data(&backend->dpy_v2), size / 2); + + backend->UnmapBuffer(GL_ARRAY_BUFFER); + } else { + VIGS_LOG_ERROR("glMapBufferRange failed"); + } + } else { + backend->Finish(); + backend->BufferSubData(GL_ARRAY_BUFFER, 0, + (size / 2), vigs_vector_data(&backend->dpy_v1)); + backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2), + (size / 2), vigs_vector_data(&backend->dpy_v2)); + } + + backend->EnableVertexAttribArray(backend->dpy_tex_prog_vertCoord_loc); + backend->EnableVertexAttribArray(backend->dpy_tex_prog_texCoord_loc); + + backend->VertexAttribPointer(backend->dpy_tex_prog_vertCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL); + backend->VertexAttribPointer(backend->dpy_tex_prog_texCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2)); + + backend->DrawArrays(GL_TRIANGLES, 0, count); + + backend->DisableVertexAttribArray(backend->dpy_tex_prog_texCoord_loc); + backend->DisableVertexAttribArray(backend->dpy_tex_prog_vertCoord_loc); +} + +static void vigs_gl_draw_dpy_scale_prog(struct vigs_gl_backend *backend, + uint32_t count) +{ + uint32_t size = count * 16; + void *ptr; + + if (size > backend->dpy_vbo_size) { + backend->dpy_vbo_size = size; + backend->BufferData(GL_ARRAY_BUFFER, + size, + 0, + GL_STREAM_DRAW); + } + + if (backend->MapBufferRange) { + ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT); + + if (ptr) { + memcpy(ptr, vigs_vector_data(&backend->dpy_v1), size / 2); + memcpy(ptr + (size / 2), vigs_vector_data(&backend->dpy_v2), size / 2); + + backend->UnmapBuffer(GL_ARRAY_BUFFER); + } else { + VIGS_LOG_ERROR("glMapBufferRange failed"); + } + } else { + backend->Finish(); + backend->BufferSubData(GL_ARRAY_BUFFER, 0, + (size / 2), vigs_vector_data(&backend->dpy_v1)); + backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2), + (size / 2), vigs_vector_data(&backend->dpy_v2)); + } + + backend->EnableVertexAttribArray(backend->dpy_scale_prog_vertCoord_loc); + backend->EnableVertexAttribArray(backend->dpy_scale_prog_texCoord_loc); + + backend->VertexAttribPointer(backend->dpy_scale_prog_vertCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL); + backend->VertexAttribPointer(backend->dpy_scale_prog_texCoord_loc, + 2, GL_FLOAT, GL_FALSE, 0, NULL + (size / 2)); + + backend->DrawArrays(GL_TRIANGLES, 0, count); + + backend->DisableVertexAttribArray(backend->dpy_scale_prog_texCoord_loc); + backend->DisableVertexAttribArray(backend->dpy_scale_prog_vertCoord_loc); +} + static void vigs_gl_draw_nv21_prog(struct vigs_gl_backend *backend, uint32_t count) { @@ -670,6 +887,28 @@ static void vigs_gl_create_ortho(GLfloat left, GLfloat right, ortho[15] = 1.0f; } +static void vigs_gl_rotate_ortho(const GLfloat ortho[16], + GLfloat angle, + GLfloat res[16]) +{ + GLfloat rot[4][4] = { + { cos(angle), sin(angle), 0, 0 }, + { -sin(angle), cos(angle), 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } + }; + int i, j, k; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + res[i * 4 + j] = 0.0f; + for (k = 0; k < 4; ++k) { + res[i * 4 + j] += ortho[i * 4 + k] * rot[k][j]; + } + } + } +} + static void vigs_gl_translate_color(vigsp_color color, vigsp_surface_format format, GLfloat res[4]) @@ -694,20 +933,20 @@ static void vigs_gl_translate_color(vigsp_color color, static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface *ws_sfc) { - GLuint cur_tex = 0; + GLuint cur_tex = 0, tmp_tex = 0; if (ws_sfc->tex) { return true; } - ws_sfc->backend->GenTextures(1, &ws_sfc->tex); + ws_sfc->backend->GenTextures(1, &tmp_tex); - if (!ws_sfc->tex) { + if (!tmp_tex) { return false; } ws_sfc->backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex); - ws_sfc->backend->BindTexture(GL_TEXTURE_2D, ws_sfc->tex); + ws_sfc->backend->BindTexture(GL_TEXTURE_2D, tmp_tex); /* * Workaround for problem in "Mesa DRI Intel(R) Ivybridge Desktop x86/MMX/SSE2, version 9.0.3": @@ -723,6 +962,8 @@ static bool vigs_winsys_gl_surface_create_texture(struct vigs_winsys_gl_surface NULL); ws_sfc->backend->BindTexture(GL_TEXTURE_2D, cur_tex); + ws_sfc->tex = tmp_tex; + return true; } @@ -777,6 +1018,55 @@ static bool vigs_gl_surface_setup_framebuffer(struct vigs_gl_surface *gl_sfc, return true; } +static bool vigs_gl_update_dpy_texture(struct vigs_gl_backend *gl_backend, + uint32_t width, uint32_t height, + GLfloat ortho[16]) +{ + GLuint cur_tex = 0; + + gl_backend->GetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&cur_tex); + + if (gl_backend->dpy_tex) { + if ((gl_backend->dpy_tex_width == width) && + (gl_backend->dpy_tex_height == height)) { + return true; + } + gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->dpy_tex); + } else { + GLuint tmp_tex = 0; + + gl_backend->GenTextures(1, &tmp_tex); + + if (!tmp_tex) { + return false; + } + + gl_backend->dpy_tex = tmp_tex; + + gl_backend->BindTexture(GL_TEXTURE_2D, tmp_tex); + + gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl_backend->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + gl_backend->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, + width, height, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + NULL); + + gl_backend->BindTexture(GL_TEXTURE_2D, cur_tex); + + memcpy(gl_backend->dpy_tex_ortho, + ortho, + sizeof(gl_backend->dpy_tex_ortho)); + gl_backend->dpy_tex_width = width; + gl_backend->dpy_tex_height = height; + + return true; +} + /* * @} */ @@ -1504,43 +1794,23 @@ static struct vigs_surface *vigs_gl_backend_create_surface(struct vigs_backend * return &gl_sfc->base; } -static void vigs_gl_backend_read_pixels_work(struct work_queue_item *wq_item) +static inline void +vigs_gl_backend_sort_planes(const struct vigs_plane *planes, + const struct vigs_plane **sorted_planes) { - struct vigs_gl_backend_read_pixels_work_item *item = (struct vigs_gl_backend_read_pixels_work_item*)wq_item; - struct vigs_gl_backend *backend = item->backend; - uint8_t *dst = NULL; - - VIGS_LOG_TRACE("enter"); - - if (backend->read_pixels_make_current(backend, true)) { - uint8_t *src; - - backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, backend->pbo); - - src = backend->MapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); - - if (src) { - dst = item->start_cb(item->user_data, - item->width, item->height, - item->stride, item->format); - - memcpy(dst, src, item->stride * item->height); - - if (!backend->UnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB)) { - VIGS_LOG_CRITICAL("glUnmapBuffer failed"); - } - } else { - VIGS_LOG_CRITICAL("glMapBuffer failed"); - } + /* + * Sort planes, only 2 of them now, don't bother... + */ - backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + assert(VIGS_MAX_PLANES == 2); - backend->read_pixels_make_current(backend, false); + if (planes[0].z_pos <= planes[1].z_pos) { + sorted_planes[0] = &planes[0]; + sorted_planes[1] = &planes[1]; + } else { + sorted_planes[0] = &planes[1]; + sorted_planes[1] = &planes[0]; } - - item->end_cb(item->user_data, (dst != NULL), true); - - g_free(item); } /* @@ -1567,6 +1837,17 @@ static bool vigs_gl_backend_composite_planes(struct vigs_gl_backend *gl_backend, continue; } + VIGS_LOG_DEBUG("plane[%u]: %ux%u format = %d, z_pos = %d, hflip = %d," + " vflip = %d, rotation = %d ", + i, + plane->width, + plane->height, + plane->format, + plane->z_pos, + plane->hflip, + plane->vflip, + plane->rotation); + src_w = plane->width; src_h = plane->height; @@ -1787,11 +2068,10 @@ static bool vigs_gl_backend_composite_planes(struct vigs_gl_backend *gl_backend, return bottom; } -static void vigs_gl_backend_composite(struct vigs_surface *surface, +static bool vigs_gl_backend_composite(struct vigs_surface *surface, const struct vigs_plane *planes, - vigs_composite_start_cb start_cb, - vigs_composite_end_cb end_cb, - void *user_data) + bool planes_dirty, + uint8_t *display_data) { struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)surface->backend; struct vigs_gl_surface *gl_root_sfc = (struct vigs_gl_surface*)surface; @@ -1801,13 +2081,18 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface, GLfloat *vert_coords; GLfloat *tex_coords; const struct vigs_plane *sorted_planes[VIGS_MAX_PLANES]; - uint32_t size = surface->stride * surface->ws_sfc->height; - struct vigs_gl_backend_read_pixels_work_item *item; bool bottom = true; VIGS_LOG_TRACE("enter"); - if (!surface->ptr && !ws_root_sfc->tex) { + if (surface->ptr) { + if (!vigs_qt5_onscreen_enabled() && !planes_dirty) { + memcpy(display_data, + surface->ptr, + surface->stride * surface->ws_sfc->height); + return true; + } + } else if (!ws_root_sfc->tex) { VIGS_LOG_WARN("compositing garbage (root surface) ???"); } @@ -1815,7 +2100,10 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface, goto out; } - if (!vigs_gl_surface_create_tmp_texture(gl_root_sfc)) { + if (!vigs_gl_update_dpy_texture(gl_backend, + surface->ws_sfc->width, + surface->ws_sfc->height, + gl_root_sfc->ortho)) { goto out; } @@ -1852,19 +2140,7 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface, goto out; } - /* - * Sort planes, only 2 of them now, don't bother... - */ - - assert(VIGS_MAX_PLANES == 2); - - if (planes[0].z_pos <= planes[1].z_pos) { - sorted_planes[0] = &planes[0]; - sorted_planes[1] = &planes[1]; - } else { - sorted_planes[0] = &planes[1]; - sorted_planes[1] = &planes[0]; - } + vigs_gl_backend_sort_planes(planes, sorted_planes); vigs_vector_resize(&gl_backend->v1, 0); vigs_vector_resize(&gl_backend->v2, 0); @@ -1896,7 +2172,7 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface, } gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, gl_root_sfc->tmp_tex, 0); + GL_TEXTURE_2D, gl_backend->dpy_tex, 0); bottom = vigs_gl_backend_composite_planes(gl_backend, sorted_planes, @@ -1917,14 +2193,25 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface, vert_coords[10] = 0; vert_coords[11] = 0; - tex_coords[6] = tex_coords[0] = 0; - tex_coords[7] =tex_coords[1] = 0; - tex_coords[2] = 1; - tex_coords[3] = 0; - tex_coords[8] = tex_coords[4] = 1; - tex_coords[9] = tex_coords[5] = 1; - tex_coords[10] = 0; - tex_coords[11] = 1; + if (!surface->ptr) { + tex_coords[6] = tex_coords[0] = 0; + tex_coords[7] = tex_coords[1] = 0; + tex_coords[2] = 1; + tex_coords[3] = 0; + tex_coords[8] = tex_coords[4] = 1; + tex_coords[9] = tex_coords[5] = 1; + tex_coords[10] = 0; + tex_coords[11] = 1; + } else { + tex_coords[6] = tex_coords[0] = 0; + tex_coords[7] = tex_coords[1] = 1; + tex_coords[2] = 1; + tex_coords[3] = 1; + tex_coords[8] = tex_coords[4] = 1; + tex_coords[9] = tex_coords[5] = 0; + tex_coords[10] = 0; + tex_coords[11] = 0; + } if (!bottom) { /* @@ -1959,55 +2246,48 @@ static void vigs_gl_backend_composite(struct vigs_surface *surface, bottom, gl_root_sfc->ortho); - /* - * Now schedule asynchronous glReadPixels. - */ +out: + gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0); - gl_backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, gl_backend->pbo); + return false; +} - if (size > gl_backend->pbo_size) { - gl_backend->pbo_size = size; - gl_backend->BufferData(GL_PIXEL_PACK_BUFFER_ARB, - size, - 0, - GL_STREAM_READ); - } +static bool vigs_gl_backend_capture(struct vigs_surface *surface, + void *pixels) +{ + struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)surface->backend; - gl_backend->PixelStorei(GL_PACK_ALIGNMENT, 1); - gl_backend->ReadPixels(0, 0, - surface->ws_sfc->width, surface->ws_sfc->height, - ws_root_sfc->tex_format, ws_root_sfc->tex_type, - NULL); + if (gl_backend->read_pixels_make_current(gl_backend, true)) { - gl_backend->BindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + if (!gl_backend->dpy_fb) { + gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb); - /* - * That's a tricky one, if we don't do this then it's not - * guaranteed that PBO will actually be updated by the time - * 'vigs_gl_backend_read_pixels_work' runs and since - * 'vigs_gl_backend_read_pixels_work' uses another OpenGL context - * we might get old results. - */ - gl_backend->Finish(); + if (!gl_backend->dpy_fb) { + VIGS_LOG_ERROR("cannot create capture FB"); - item = g_malloc(sizeof(*item)); + gl_backend->read_pixels_make_current(gl_backend, false); - work_queue_item_init(&item->base, &vigs_gl_backend_read_pixels_work); + return false; + } - item->backend = gl_backend; + } - item->start_cb = start_cb; - item->end_cb = end_cb; - item->user_data = user_data; - item->width = surface->ws_sfc->width; - item->height = surface->ws_sfc->height; - item->stride = surface->stride; - item->format = surface->format; + gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb); + gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, gl_backend->dpy_tex, 0); - work_queue_add_item(gl_backend->read_pixels_queue, &item->base); + gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width, + gl_backend->dpy_tex_height, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + pixels); + gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0); -out: - gl_backend->BindFramebuffer(GL_FRAMEBUFFER, 0); + gl_backend->read_pixels_make_current(gl_backend, false); + + return true; + } + + return false; } static void vigs_gl_backend_batch_end(struct vigs_backend *backend) @@ -2018,6 +2298,142 @@ static void vigs_gl_backend_batch_end(struct vigs_backend *backend) gl_backend->make_current(gl_backend, false); } +static bool vigs_gl_backend_display(struct vigs_backend *backend, + uint8_t *display_data) +{ + struct vigs_gl_backend *gl_backend = (struct vigs_gl_backend*)backend; + + VIGS_LOG_TRACE("enter"); + + if (vigs_qt5_onscreen_enabled()) { + GLfloat *vert_coords; + GLfloat *tex_coords; + bool scale; + GLfloat rotated_ortho[16]; + GLfloat *ortho; + float brightness = (float)(255 - brightness_tbl[brightness_level]) / 255.0f; + + if (display_off) { + brightness = 0.0f; + } + + if (!gl_backend->is_gl_2 && !gl_backend->dpy_vao) { + gl_backend->GenVertexArrays(1, &gl_backend->dpy_vao); + + if (!gl_backend->dpy_vao) { + VIGS_LOG_CRITICAL("cannot create VAO"); + exit(1); + } + + gl_backend->BindVertexArray(gl_backend->dpy_vao); + } + + gl_backend->BindBuffer(GL_ARRAY_BUFFER, gl_backend->dpy_vbo); + gl_backend->Disable(GL_DEPTH_TEST); + gl_backend->Disable(GL_BLEND); + + if (qt5_window_angle == 0) { + ortho = gl_backend->dpy_tex_ortho; + } else { + vigs_gl_rotate_ortho(gl_backend->dpy_tex_ortho, + (float)(360.0f - qt5_window_angle) * M_PI / 180.0f, + rotated_ortho); + ortho = rotated_ortho; + } + + scale = (qt5_window_width != gl_backend->dpy_tex_width) || + (qt5_window_height != gl_backend->dpy_tex_height); + + gl_backend->Viewport(0, 0, + qt5_window_width, + qt5_window_height); + + if (scale) { + float texSize[2]; + + gl_backend->UseProgram(gl_backend->dpy_scale_prog_id); + gl_backend->UniformMatrix4fv(gl_backend->dpy_scale_prog_proj_loc, 1, GL_FALSE, + ortho); + + texSize[0] = gl_backend->dpy_tex_width; + texSize[1] = gl_backend->dpy_tex_height; + + gl_backend->Uniform2fv(gl_backend->dpy_scale_prog_texSize_loc, 1, texSize); + gl_backend->Uniform1f(gl_backend->dpy_scale_prog_brightness_loc, brightness); + } else { + gl_backend->UseProgram(gl_backend->dpy_tex_prog_id); + gl_backend->UniformMatrix4fv(gl_backend->dpy_tex_prog_proj_loc, 1, GL_FALSE, + ortho); + gl_backend->Uniform1f(gl_backend->dpy_tex_prog_brightness_loc, brightness); + } + + gl_backend->BindTexture(GL_TEXTURE_2D, gl_backend->dpy_tex); + + vigs_vector_resize(&gl_backend->dpy_v1, 0); + vigs_vector_resize(&gl_backend->dpy_v2, 0); + + vert_coords = vigs_vector_append(&gl_backend->dpy_v1, + (12 * sizeof(GLfloat))); + tex_coords = vigs_vector_append(&gl_backend->dpy_v2, + (12 * sizeof(GLfloat))); + + vert_coords[6] = vert_coords[0] = 0; + vert_coords[7] = vert_coords[1] = gl_backend->dpy_tex_height; + vert_coords[2] = gl_backend->dpy_tex_width; + vert_coords[3] = gl_backend->dpy_tex_height; + vert_coords[8] = vert_coords[4] = gl_backend->dpy_tex_width; + vert_coords[9] = vert_coords[5] = 0; + vert_coords[10] = 0; + vert_coords[11] = 0; + + tex_coords[6] = tex_coords[0] = 0; + tex_coords[7] = tex_coords[1] = 0; + tex_coords[2] = 1; + tex_coords[3] = 0; + tex_coords[8] = tex_coords[4] = 1; + tex_coords[9] = tex_coords[5] = 1; + tex_coords[10] = 0; + tex_coords[11] = 1; + + if (scale) { + vigs_gl_draw_dpy_scale_prog(gl_backend, 6); + } else { + vigs_gl_draw_dpy_tex_prog(gl_backend, 6); + } + + gl_backend->Finish(); + + return true; + } else { + if (gl_backend->read_pixels_make_current(gl_backend, true)) { + if (!gl_backend->dpy_fb) { + gl_backend->GenFramebuffers(1, &gl_backend->dpy_fb); + + if (!gl_backend->dpy_fb) { + VIGS_LOG_CRITICAL("cannot create FB"); + exit(1); + } + + gl_backend->BindFramebuffer(GL_FRAMEBUFFER, gl_backend->dpy_fb); + } + + gl_backend->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, gl_backend->dpy_tex, 0); + + gl_backend->ReadPixels(0, 0, gl_backend->dpy_tex_width, + gl_backend->dpy_tex_height, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + display_data); + + gl_backend->read_pixels_make_current(gl_backend, false); + + return true; + } else { + return false; + } + } +} + bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) { if (!gl_backend->make_current(gl_backend, true)) { @@ -2177,9 +2593,10 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) gl_backend->yuv420_prog_vtex_loc = gl_backend->GetUniformLocation(gl_backend->yuv420_prog_id, "vtex"); gl_backend->GenBuffers(1, &gl_backend->vbo); + gl_backend->GenBuffers(1, &gl_backend->dpy_vbo); - if (!gl_backend->vbo) { - VIGS_LOG_CRITICAL("cannot create VBO"); + if (!gl_backend->vbo || !gl_backend->dpy_vbo) { + VIGS_LOG_CRITICAL("cannot create VBOs"); goto fail; } @@ -2197,27 +2614,81 @@ bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend) gl_backend->UseProgram(gl_backend->tex_prog_id); gl_backend->cur_prog_id = gl_backend->tex_prog_id; - gl_backend->GenBuffers(1, &gl_backend->pbo); + gl_backend->dpy_tex_prog_vs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_vs_tex_source_gl2 : g_vs_tex_source_gl3), + GL_VERTEX_SHADER); - if (!gl_backend->pbo) { - VIGS_LOG_CRITICAL("cannot create read_pixels PBO"); + if (!gl_backend->dpy_tex_prog_vs_id) { goto fail; } + gl_backend->dpy_tex_prog_fs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_fs_dpy_source_gl2 : g_fs_dpy_source_gl3), + GL_FRAGMENT_SHADER); + + if (!gl_backend->dpy_tex_prog_fs_id) { + goto fail; + } + + gl_backend->dpy_tex_prog_id = vigs_gl_create_program(gl_backend, + gl_backend->dpy_tex_prog_vs_id, + gl_backend->dpy_tex_prog_fs_id); + + if (!gl_backend->dpy_tex_prog_id) { + goto fail; + } + + gl_backend->dpy_tex_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->dpy_tex_prog_id, "proj"); + gl_backend->dpy_tex_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_tex_prog_id, "vertCoord"); + gl_backend->dpy_tex_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_tex_prog_id, "texCoord"); + gl_backend->dpy_tex_prog_brightness_loc = gl_backend->GetUniformLocation(gl_backend->dpy_tex_prog_id, "brightness"); + + gl_backend->dpy_scale_prog_vs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_vs_tex_source_gl2 : g_vs_tex_source_gl3), + GL_VERTEX_SHADER); + + if (!gl_backend->dpy_scale_prog_vs_id) { + goto fail; + } + + gl_backend->dpy_scale_prog_fs_id = vigs_gl_create_shader(gl_backend, + (gl_backend->is_gl_2 ? g_fs_scale_source_gl2 : g_fs_scale_source_gl3), + GL_FRAGMENT_SHADER); + + if (!gl_backend->dpy_scale_prog_fs_id) { + goto fail; + } + + gl_backend->dpy_scale_prog_id = vigs_gl_create_program(gl_backend, + gl_backend->dpy_scale_prog_vs_id, + gl_backend->dpy_scale_prog_fs_id); + + if (!gl_backend->dpy_scale_prog_id) { + goto fail; + } + + gl_backend->dpy_scale_prog_proj_loc = gl_backend->GetUniformLocation(gl_backend->dpy_scale_prog_id, "proj"); + gl_backend->dpy_scale_prog_vertCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_scale_prog_id, "vertCoord"); + gl_backend->dpy_scale_prog_texCoord_loc = gl_backend->GetAttribLocation(gl_backend->dpy_scale_prog_id, "texCoord"); + gl_backend->dpy_scale_prog_texSize_loc = gl_backend->GetUniformLocation(gl_backend->dpy_scale_prog_id, "texSize"); + gl_backend->dpy_scale_prog_brightness_loc = gl_backend->GetUniformLocation(gl_backend->dpy_scale_prog_id, "brightness"); + gl_backend->Disable(GL_DEPTH_TEST); gl_backend->Disable(GL_BLEND); gl_backend->base.batch_start = &vigs_gl_backend_batch_start; gl_backend->base.create_surface = &vigs_gl_backend_create_surface; gl_backend->base.composite = &vigs_gl_backend_composite; + gl_backend->base.capture = &vigs_gl_backend_capture; gl_backend->base.batch_end = &vigs_gl_backend_batch_end; + gl_backend->base.display = &vigs_gl_backend_display; gl_backend->make_current(gl_backend, false); vigs_vector_init(&gl_backend->v1, 0); vigs_vector_init(&gl_backend->v2, 0); - - gl_backend->read_pixels_queue = work_queue_create("vigs_work_queue"); + vigs_vector_init(&gl_backend->dpy_v1, 0); + vigs_vector_init(&gl_backend->dpy_v2, 0); return true; @@ -2229,10 +2700,25 @@ fail: void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend) { - work_queue_destroy(gl_backend->read_pixels_queue); - if (gl_backend->make_current(gl_backend, true)) { - gl_backend->DeleteBuffers(1, &gl_backend->pbo); + if (gl_backend->dpy_tex) { + gl_backend->DeleteTextures(1, &gl_backend->dpy_tex); + } + gl_backend->DeleteBuffers(1, &gl_backend->dpy_vbo); + gl_backend->DetachShader(gl_backend->dpy_scale_prog_id, + gl_backend->dpy_scale_prog_vs_id); + gl_backend->DetachShader(gl_backend->dpy_scale_prog_id, + gl_backend->dpy_scale_prog_fs_id); + gl_backend->DeleteShader(gl_backend->dpy_scale_prog_vs_id); + gl_backend->DeleteShader(gl_backend->dpy_scale_prog_fs_id); + gl_backend->DeleteProgram(gl_backend->dpy_scale_prog_id); + gl_backend->DetachShader(gl_backend->dpy_tex_prog_id, + gl_backend->dpy_tex_prog_vs_id); + gl_backend->DetachShader(gl_backend->dpy_tex_prog_id, + gl_backend->dpy_tex_prog_fs_id); + gl_backend->DeleteShader(gl_backend->dpy_tex_prog_vs_id); + gl_backend->DeleteShader(gl_backend->dpy_tex_prog_fs_id); + gl_backend->DeleteProgram(gl_backend->dpy_tex_prog_id); gl_backend->DeleteBuffers(1, &gl_backend->vbo); gl_backend->DetachShader(gl_backend->yuv420_prog_id, gl_backend->yuv420_prog_vs_id); @@ -2273,6 +2759,8 @@ void vigs_gl_backend_cleanup(struct vigs_gl_backend *gl_backend) gl_backend->make_current(gl_backend, false); } + vigs_vector_cleanup(&gl_backend->dpy_v2); + vigs_vector_cleanup(&gl_backend->dpy_v1); vigs_vector_cleanup(&gl_backend->v2); vigs_vector_cleanup(&gl_backend->v1); } diff --git a/hw/vigs/vigs_gl_backend.h b/hw/vigs/vigs_gl_backend.h index bfa41101a6..584ec04bfe 100644 --- a/hw/vigs/vigs_gl_backend.h +++ b/hw/vigs/vigs_gl_backend.h @@ -37,7 +37,6 @@ #include #include "winsys_gl.h" -struct work_queue; struct vigs_gl_pool; struct vigs_gl_backend @@ -121,6 +120,8 @@ struct vigs_gl_backend void (GLAPIENTRY* VertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); void (GLAPIENTRY* Uniform4fv)(GLint location, GLsizei count, const GLfloat* value); void (GLAPIENTRY* UniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (GLAPIENTRY* Uniform2fv)(GLint location, GLsizei count, const GLfloat* value); + void (GLAPIENTRY* Uniform1f)(GLint location, GLfloat v0); void (GLAPIENTRY* Uniform1i)(GLint location, GLint v0); void (GLAPIENTRY* Uniform2f)(GLint location, GLfloat v0, GLfloat v1); void (GLAPIENTRY* ActiveTexture)(GLenum texture); @@ -163,7 +164,8 @@ struct vigs_gl_backend */ /* - * Other. + * Rendering thread related. + * @{ */ GLuint vao; @@ -213,10 +215,46 @@ struct vigs_gl_backend GLuint cur_prog_id; - struct work_queue *read_pixels_queue; + /* + * @} + * Display thread related. + * @{ + */ - GLuint pbo; - uint32_t pbo_size; + struct vigs_vector dpy_v1; + struct vigs_vector dpy_v2; + + GLuint dpy_vao; + + GLuint dpy_tex_prog_vs_id; + GLuint dpy_tex_prog_fs_id; + GLuint dpy_tex_prog_id; + GLint dpy_tex_prog_proj_loc; + GLint dpy_tex_prog_vertCoord_loc; + GLint dpy_tex_prog_texCoord_loc; + GLint dpy_tex_prog_brightness_loc; + + GLuint dpy_scale_prog_vs_id; + GLuint dpy_scale_prog_fs_id; + GLuint dpy_scale_prog_id; + GLint dpy_scale_prog_proj_loc; + GLint dpy_scale_prog_vertCoord_loc; + GLint dpy_scale_prog_texCoord_loc; + GLint dpy_scale_prog_texSize_loc; + GLint dpy_scale_prog_brightness_loc; + + GLuint dpy_vbo; + uint32_t dpy_vbo_size; + + GLuint dpy_tex; + GLuint dpy_fb; + GLfloat dpy_tex_ortho[16]; + uint32_t dpy_tex_width; + uint32_t dpy_tex_height; + + /* + * @} + */ }; bool vigs_gl_backend_init(struct vigs_gl_backend *gl_backend); diff --git a/hw/vigs/vigs_gl_backend_cgl.c b/hw/vigs/vigs_gl_backend_cgl.c index e21a7a16c7..db07be622e 100644 --- a/hw/vigs/vigs_gl_backend_cgl.c +++ b/hw/vigs/vigs_gl_backend_cgl.c @@ -29,6 +29,7 @@ #include "vigs_gl_backend.h" #include "vigs_log.h" +#include "vigs_qt5.h" #include #include @@ -61,7 +62,6 @@ static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] = kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFANoRecovery, kCGLPFAPBuffer, 0 }; @@ -74,7 +74,6 @@ static const CGLPixelFormatAttribute pixel_format_3_2_core_attrs[] = kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFANoRecovery, kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, 0 }; @@ -257,6 +256,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display) CGLError error; CGLPixelFormatObj pixel_format; int n; + CGLContextObj qt5_ctx = NULL; gl_backend_cgl = g_malloc0(sizeof(*gl_backend_cgl)); @@ -321,6 +321,8 @@ struct vigs_backend *vigs_gl_backend_create(void *display) VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer); VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv); VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv); + VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv); + VIGS_GL_GET_PROC(Uniform1f, glUniform1f); VIGS_GL_GET_PROC(Uniform1i, glUniform1i); VIGS_GL_GET_PROC(Uniform2f, glUniform2f); VIGS_GL_GET_PROC(ActiveTexture, glActiveTexture); @@ -375,9 +377,16 @@ struct vigs_backend *vigs_gl_backend_create(void *display) goto fail2; } + if (vigs_qt5_onscreen_enabled()) { + qt5_ctx = (CGLContextObj)vigs_qt5_gl_context_create(gl_backend_cgl->base.is_gl_2); + if (!qt5_ctx) { + goto fail2; + } + } + if (!vigs_gl_backend_cgl_create_context(gl_backend_cgl, pixel_format, - NULL, + qt5_ctx, &gl_backend_cgl->context)) { goto fail3; } diff --git a/hw/vigs/vigs_gl_backend_glx.c b/hw/vigs/vigs_gl_backend_glx.c index 8faa13b48d..7b1fe13756 100644 --- a/hw/vigs/vigs_gl_backend_glx.c +++ b/hw/vigs/vigs_gl_backend_glx.c @@ -29,6 +29,7 @@ #include "vigs_gl_backend.h" #include "vigs_log.h" +#include "vigs_qt5.h" #include #include @@ -85,6 +86,7 @@ struct vigs_gl_backend_glx PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent; PFNGLXGETCURRENTCONTEXTPROC glXGetCurrentContext; PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext; + PFNGLXQUERYCONTEXTPROC glXQueryContext; /* GLX_ARB_create_context */ PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB; @@ -96,6 +98,16 @@ struct vigs_gl_backend_glx GLXContext read_pixels_ctx; }; +static const char *gl_3_2_check_funcs[] = +{ + "glGenTransformFeedbacks", + "glBindTransformFeedback", + "glPauseTransformFeedback", + "glResumeTransformFeedback", + "glDeleteTransformFeedbacks", + "glVertexAttribDivisor" +}; + static bool vigs_gl_backend_glx_check_gl_version(struct vigs_gl_backend_glx *gl_backend_glx, bool *is_gl_2) { @@ -126,6 +138,7 @@ static bool vigs_gl_backend_glx_check_gl_version(struct vigs_gl_backend_glx *gl_ int n = 0; GLXFBConfig *configs = NULL; GLXContext ctx = NULL; + unsigned int i; tmp = getenv("GL_VERSION"); @@ -178,6 +191,19 @@ static bool vigs_gl_backend_glx_check_gl_version(struct vigs_gl_backend_glx *gl_ VIGS_LOG_INFO("glXCreateContextAttribsARB failed, using OpenGL 2.1"); } + if (*is_gl_2 == false) { + for (i = 0; + i < sizeof(gl_3_2_check_funcs)/sizeof(gl_3_2_check_funcs[0]); + ++i) { + if (!gl_backend_glx->glXGetProcAddress((const GLubyte *) + gl_3_2_check_funcs[i])) { + VIGS_LOG_INFO("Failed to find function \"%s\", " + "using OpenGL 2.1", gl_3_2_check_funcs[i]); + *is_gl_2 = true; + } + } + } + out: if (ctx) { gl_backend_glx->glXMakeContextCurrent(gl_backend_glx->dpy, 0, 0, NULL); @@ -192,28 +218,50 @@ out: static GLXFBConfig vigs_gl_backend_glx_get_config(struct vigs_gl_backend_glx *gl_backend_glx) { - int config_attribs[] = - { - GLX_DOUBLEBUFFER, True, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_BUFFER_SIZE, 32, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, - None - }; int n = 0; GLXFBConfig *glx_configs; GLXFBConfig best_config = NULL; - glx_configs = gl_backend_glx->glXChooseFBConfig(gl_backend_glx->dpy, - DefaultScreen(gl_backend_glx->dpy), - config_attribs, - &n); + if (vigs_qt5_onscreen_enabled()) { + int config_attribs[] = + { + GLX_FBCONFIG_ID, 0, + None + }; + + if (gl_backend_glx->glXQueryContext(gl_backend_glx->dpy, + gl_backend_glx->ctx, + GLX_FBCONFIG_ID, + &config_attribs[1]) != Success) { + VIGS_LOG_CRITICAL("Unable to get context's GLX config"); + return NULL; + } + + glx_configs = gl_backend_glx->glXChooseFBConfig(gl_backend_glx->dpy, + DefaultScreen(gl_backend_glx->dpy), + config_attribs, + &n); + } else { + int config_attribs[] = + { + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_BUFFER_SIZE, 32, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, + None + }; + + glx_configs = gl_backend_glx->glXChooseFBConfig(gl_backend_glx->dpy, + DefaultScreen(gl_backend_glx->dpy), + config_attribs, + &n); + } if (n > 0) { int tmp; @@ -357,14 +405,18 @@ static void vigs_gl_backend_glx_destroy(struct vigs_backend *backend) vigs_gl_backend_cleanup(&gl_backend_glx->base); - gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, - gl_backend_glx->read_pixels_ctx); - - gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, - gl_backend_glx->ctx); - - gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, - gl_backend_glx->read_pixels_sfc); + if (gl_backend_glx->read_pixels_sfc) { + gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, + gl_backend_glx->read_pixels_sfc); + } + if (!vigs_qt5_onscreen_enabled() && gl_backend_glx->ctx) { + gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, + gl_backend_glx->ctx); + } + if (gl_backend_glx->read_pixels_ctx) { + gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, + gl_backend_glx->read_pixels_ctx); + } gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, gl_backend_glx->sfc); @@ -418,6 +470,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display) VIGS_GLX_GET_PROC(PFNGLXGETCURRENTCONTEXTPROC, glXGetCurrentContext); VIGS_GLX_GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext); VIGS_GLX_GET_PROC(PFNGLXCREATECONTEXTATTRIBSARBPROC, glXCreateContextAttribsARB); + VIGS_GLX_GET_PROC(PFNGLXQUERYCONTEXTPROC, glXQueryContext); VIGS_GL_GET_PROC(GenTextures, glGenTextures); VIGS_GL_GET_PROC(DeleteTextures, glDeleteTextures); @@ -470,6 +523,8 @@ struct vigs_backend *vigs_gl_backend_create(void *display) VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer); VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv); VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv); + VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv); + VIGS_GL_GET_PROC(Uniform1f, glUniform1f); VIGS_GL_GET_PROC(Uniform1i, glUniform1i); VIGS_GL_GET_PROC(Uniform2f, glUniform2f); VIGS_GL_GET_PROC(ActiveTexture, glActiveTexture); @@ -508,36 +563,64 @@ struct vigs_backend *vigs_gl_backend_create(void *display) VIGS_GL_GET_PROC(DeleteVertexArrays, glDeleteVertexArrays); } - config = vigs_gl_backend_glx_get_config(gl_backend_glx); + if (vigs_qt5_onscreen_enabled()) { + gl_backend_glx->ctx = + (GLXContext)vigs_qt5_gl_context_create(gl_backend_glx->base.is_gl_2); - if (!config) { - goto fail2; - } + if (!gl_backend_glx->ctx) { + goto fail2; + } - if (!vigs_gl_backend_glx_create_surface(gl_backend_glx, - config, - &gl_backend_glx->sfc)) { - goto fail2; - } + config = vigs_gl_backend_glx_get_config(gl_backend_glx); - if (!vigs_gl_backend_glx_create_surface(gl_backend_glx, - config, - &gl_backend_glx->read_pixels_sfc)) { - goto fail3; - } + if (!config) { + goto fail2; + } - if (!vigs_gl_backend_glx_create_context(gl_backend_glx, - config, - NULL, - &gl_backend_glx->ctx)) { - goto fail4; + if (!vigs_gl_backend_glx_create_surface(gl_backend_glx, + config, + &gl_backend_glx->read_pixels_sfc)) { + goto fail2; + } + + if (!vigs_gl_backend_glx_create_context(gl_backend_glx, + config, + gl_backend_glx->ctx, + &gl_backend_glx->read_pixels_ctx)) { + goto fail2; + } + } else { + config = vigs_gl_backend_glx_get_config(gl_backend_glx); + + if (!config) { + goto fail2; + } + + if (!vigs_gl_backend_glx_create_surface(gl_backend_glx, + config, + &gl_backend_glx->read_pixels_sfc)) { + goto fail2; + } + + if (!vigs_gl_backend_glx_create_context(gl_backend_glx, + config, + NULL, + &gl_backend_glx->ctx)) { + goto fail2; + } + + if (!vigs_gl_backend_glx_create_context(gl_backend_glx, + config, + gl_backend_glx->ctx, + &gl_backend_glx->read_pixels_ctx)) { + goto fail2; + } } - if (!vigs_gl_backend_glx_create_context(gl_backend_glx, + if (!vigs_gl_backend_glx_create_surface(gl_backend_glx, config, - gl_backend_glx->ctx, - &gl_backend_glx->read_pixels_ctx)) { - goto fail5; + &gl_backend_glx->sfc)) { + goto fail2; } gl_backend_glx->base.base.destroy = &vigs_gl_backend_glx_destroy; @@ -547,26 +630,29 @@ struct vigs_backend *vigs_gl_backend_create(void *display) gl_backend_glx->base.ws_info.context = gl_backend_glx->ctx; if (!vigs_gl_backend_init(&gl_backend_glx->base)) { - goto fail6; + goto fail3; } VIGS_LOG_DEBUG("created"); return &gl_backend_glx->base.base; -fail6: - gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, - gl_backend_glx->read_pixels_ctx); -fail5: - gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, - gl_backend_glx->ctx); -fail4: - gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, - gl_backend_glx->read_pixels_sfc); fail3: gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, gl_backend_glx->sfc); fail2: + if (gl_backend_glx->read_pixels_sfc) { + gl_backend_glx->glXDestroyPbuffer(gl_backend_glx->dpy, + gl_backend_glx->read_pixels_sfc); + } + if (!vigs_qt5_onscreen_enabled() && gl_backend_glx->ctx) { + gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, + gl_backend_glx->ctx); + } + if (gl_backend_glx->read_pixels_ctx) { + gl_backend_glx->glXDestroyContext(gl_backend_glx->dpy, + gl_backend_glx->read_pixels_ctx); + } dlclose(gl_backend_glx->handle); fail1: vigs_backend_cleanup(&gl_backend_glx->base.base); diff --git a/hw/vigs/vigs_gl_backend_wgl.c b/hw/vigs/vigs_gl_backend_wgl.c index 219eb4d1ec..1d8add5a27 100644 --- a/hw/vigs/vigs_gl_backend_wgl.c +++ b/hw/vigs/vigs_gl_backend_wgl.c @@ -29,6 +29,7 @@ #include "vigs_gl_backend.h" #include "vigs_log.h" +#include "vigs_qt5.h" #include #include #include @@ -122,6 +123,16 @@ struct vigs_gl_backend_wgl HGLRC read_pixels_ctx; }; +static const char *gl_3_2_check_funcs[] = +{ + "glGenTransformFeedbacks", + "glBindTransformFeedback", + "glPauseTransformFeedback", + "glResumeTransformFeedback", + "glDeleteTransformFeedbacks", + "glVertexAttribDivisor" +}; + static bool vigs_gl_backend_wgl_check_gl_version(struct vigs_gl_backend_wgl *gl_backend_wgl, bool *is_gl_2) { @@ -155,6 +166,7 @@ static bool vigs_gl_backend_wgl_check_gl_version(struct vigs_gl_backend_wgl *gl_ UINT n = 0; PIXELFORMATDESCRIPTOR pix_fmt; HGLRC ctx; + unsigned int i; tmp = getenv("GL_VERSION"); @@ -235,6 +247,19 @@ static bool vigs_gl_backend_wgl_check_gl_version(struct vigs_gl_backend_wgl *gl_ VIGS_LOG_INFO("wglCreateContextAttribsARB failed, using OpenGL 2.1"); } + if (*is_gl_2 == false) { + for (i = 0; + i < sizeof(gl_3_2_check_funcs)/sizeof(gl_3_2_check_funcs[0]); + ++i) { + if (!gl_backend_wgl->wglGetProcAddress((LPCSTR) + gl_3_2_check_funcs[i])) { + VIGS_LOG_INFO("Failed to find function \"%s\", " + "using OpenGL 2.1", gl_3_2_check_funcs[i]); + *is_gl_2 = true; + } + } + } + gl_backend_wgl->wglDeleteContext(ctx); out3: @@ -455,6 +480,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display) }; const char *ext_str = NULL; struct vigs_gl_backend_wgl *gl_backend_wgl = NULL; + HGLRC qt5_ctx = NULL; vigs_win_class.cbSize = sizeof(WNDCLASSEXA); vigs_win_class.style = 0; @@ -611,6 +637,8 @@ struct vigs_backend *vigs_gl_backend_create(void *display) VIGS_GL_GET_PROC(VertexAttribPointer, glVertexAttribPointer); VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv); VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv); + VIGS_GL_GET_PROC(Uniform2fv, glUniform2fv); + VIGS_GL_GET_PROC(Uniform1f, glUniform1f); VIGS_GL_GET_PROC(Uniform1i, glUniform1i); VIGS_GL_GET_PROC(Uniform2f, glUniform2f); VIGS_GL_GET_PROC(ActiveTexture, glActiveTexture); @@ -655,6 +683,14 @@ struct vigs_backend *vigs_gl_backend_create(void *display) DestroyWindow(tmp_win); tmp_win = NULL; + if (vigs_qt5_onscreen_enabled()) { + qt5_ctx = + (HGLRC)vigs_qt5_gl_context_create(gl_backend_wgl->base.is_gl_2); + if (!qt5_ctx) { + goto fail; + } + } + gl_backend_wgl->win = CreateWindow(VIGS_WGL_WIN_CLASS, "VIGSWin", WS_DISABLED | WS_POPUP, 0, 0, 1, 1, NULL, NULL, 0, 0); @@ -690,7 +726,7 @@ struct vigs_backend *vigs_gl_backend_create(void *display) } if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl, - NULL, + qt5_ctx, &gl_backend_wgl->ctx)) { goto fail; } diff --git a/hw/vigs/vigs_inc/GL/gl.h b/hw/vigs/vigs_inc/GL/gl.h index e65e1bc8a8..43eefe37dc 100644 --- a/hw/vigs/vigs_inc/GL/gl.h +++ b/hw/vigs/vigs_inc/GL/gl.h @@ -2087,7 +2087,7 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLsh #endif /* GL_GLEXT_LEGACY */ - +#ifdef GL_ARB_shader_objects #if GL_ARB_shader_objects #ifndef GL_MESA_shader_debug @@ -2106,7 +2106,7 @@ GLAPI GLsizei GLAPIENTRY glGetDebugLogLengthMESA (GLhandleARB obj, GLenum logTyp #endif /* GL_MESA_shader_debug */ #endif /* GL_ARB_shader_objects */ - +#endif /* * ???. GL_MESA_packed_depth_stencil diff --git a/hw/vigs/vigs_offscreen_server.c b/hw/vigs/vigs_offscreen_server.c new file mode 100644 index 0000000000..3f961a7a09 --- /dev/null +++ b/hw/vigs/vigs_offscreen_server.c @@ -0,0 +1,147 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "vigs_offscreen_server.h" +#include "vigs_backend.h" +#include "work_queue.h" + +struct vigs_display_work_item +{ + struct work_queue_item base; + + struct vigs_server *server; +}; + +static void vigs_offscreen_server_display_work(struct work_queue_item *wq_item) +{ + struct vigs_display_work_item *item = (struct vigs_display_work_item*)wq_item; + struct vigs_server *server = item->server; + int index = (&server->capture_buffers[0] == server->captured) ? 1 : 0; + + vigs_server_finish_update_display( + server, server->backend->display(server->backend, + server->capture_buffers[index].data)); + + g_free(item); +} + +static bool vigs_offscreen_server_begin_update(struct vigs_server *server, + bool is_capturing, + bool force) +{ + return vigs_server_process_captured(server, force); +} + +static void vigs_offscreen_server_finish_update(struct vigs_server *server, + bool composited, + bool dirty) +{ + if (dirty) { + vigs_server_finish_update_display(server, true); + } else if (composited) { + struct vigs_offscreen_server *offscreen_server = + (struct vigs_offscreen_server*)server; + + struct vigs_display_work_item *item; + + item = g_malloc(sizeof(*item)); + + work_queue_item_init(&item->base, &vigs_offscreen_server_display_work); + + item->server = server; + + work_queue_add_item(offscreen_server->display_queue, &item->base); + } else { + vigs_server_finish_update_display(server, false); + } +} + +static bool vigs_offscreen_server_display(struct vigs_server *server, + bool *displayed) +{ + *displayed = false; + return false; +} + +static bool vigs_offscreen_server_capture(struct vigs_server *server, + struct vigs_surface *sfc, + void *pixels) +{ + if (server->captured && server->captured->data) { + memcpy(pixels, + server->captured->data, + sfc->stride * sfc->ws_sfc->height); + + return true; + } + + return false; +} + +static void vigs_offscreen_server_destroy(struct vigs_server *server) +{ + struct vigs_offscreen_server *offscreen_server = + (struct vigs_offscreen_server*)server; + + work_queue_destroy(offscreen_server->display_queue); + + vigs_server_cleanup(server); + + g_free(server); +} + +struct vigs_server *vigs_offscreen_server_create(uint8_t *vram_ptr, + uint8_t *ram_ptr, + struct vigs_display_ops *display_ops, + struct vigs_capture_ops *capture_ops, + void *display_user_data, + struct vigs_backend *backend, + struct work_queue *render_queue) +{ + struct vigs_offscreen_server *server = NULL; + + server = g_malloc0(sizeof(*server)); + + if (!vigs_server_init(&server->base, vram_ptr, ram_ptr, + display_ops, capture_ops, display_user_data, + backend, render_queue)) { + g_free(server); + return NULL; + } + + server->display_queue = work_queue_create("display_queue"); + + server->base.begin_update = &vigs_offscreen_server_begin_update; + server->base.finish_update = &vigs_offscreen_server_finish_update; + server->base.display = &vigs_offscreen_server_display; + server->base.capture = &vigs_offscreen_server_capture; + server->base.destroy = &vigs_offscreen_server_destroy; + + return &server->base; +} diff --git a/hw/vigs/vigs_offscreen_server.h b/hw/vigs/vigs_offscreen_server.h new file mode 100644 index 0000000000..f0e715f669 --- /dev/null +++ b/hw/vigs/vigs_offscreen_server.h @@ -0,0 +1,50 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef _QEMU_VIGS_OFFSCREEN_SERVER_H +#define _QEMU_VIGS_OFFSCREEN_SERVER_H + +#include "vigs_server.h" + +struct vigs_offscreen_server +{ + struct vigs_server base; + + struct work_queue *display_queue; +}; + +struct vigs_server *vigs_offscreen_server_create(uint8_t *vram_ptr, + uint8_t *ram_ptr, + struct vigs_display_ops *display_ops, + struct vigs_capture_ops *capture_ops, + void *display_user_data, + struct vigs_backend *backend, + struct work_queue *render_queue); + +#endif diff --git a/hw/vigs/vigs_onscreen_server.c b/hw/vigs/vigs_onscreen_server.c new file mode 100644 index 0000000000..7fcc352b33 --- /dev/null +++ b/hw/vigs/vigs_onscreen_server.c @@ -0,0 +1,190 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "vigs_onscreen_server.h" +#include "vigs_backend.h" +#include "vigs_log.h" +#include "work_queue.h" + +static bool vigs_onscreen_server_begin_update(struct vigs_server *server, + bool is_capturing, + bool force) +{ + struct vigs_onscreen_server *onscreen_server = + (struct vigs_onscreen_server*)server; + + qemu_mutex_lock(&onscreen_server->mutex); + + if (force) { + ++onscreen_server->invalidate_cnt; + } + + if (is_capturing) { + /* + * If capturing is in progress then just skip this update. + */ + goto out; + } + + onscreen_server->updated = false; + onscreen_server->composited = false; + onscreen_server->dirty = false; + +out: + qemu_mutex_unlock(&onscreen_server->mutex); + + return false; +} + +static void vigs_onscreen_server_finish_update(struct vigs_server *server, + bool composited, + bool dirty) +{ + struct vigs_onscreen_server *onscreen_server = + (struct vigs_onscreen_server*)server; + + qemu_mutex_lock(&onscreen_server->mutex); + + onscreen_server->updated = true; + onscreen_server->composited = composited; + onscreen_server->dirty = dirty; + + qemu_mutex_unlock(&onscreen_server->mutex); + + qemu_cond_signal(&onscreen_server->cond); +} + +static bool vigs_onscreen_server_display(struct vigs_server *server, + bool *displayed) +{ + struct vigs_onscreen_server *onscreen_server = + (struct vigs_onscreen_server*)server; + bool force = false; + + qemu_mutex_lock(&onscreen_server->mutex); + + /* + * Wait until rendering is finished. + */ + while (!onscreen_server->updated) { + qemu_cond_wait(&onscreen_server->cond, &onscreen_server->mutex); + } + + if (onscreen_server->invalidate_cnt > 0) { + --onscreen_server->invalidate_cnt; + force = true; + } + + onscreen_server->updated = false; + + qemu_mutex_unlock(&onscreen_server->mutex); + + *displayed = true; + + if (onscreen_server->dirty) { + /* + * Software composition took place, finish ASAP and + * process captured data. + */ + vigs_server_finish_update_display(server, true); + return vigs_server_process_captured(server, force); + } else if (onscreen_server->composited) { + /* + * Hw composition took place, display the content. + */ + server->backend->display(server->backend, NULL); + } else if (force) { + /* + * Nothing happened, but if it's a forced display, then + * we should try to display hw stuff first, if there isn't any + * then display sw stuff. + */ + if (!server->backend->display(server->backend, NULL)) { + vigs_server_finish_update_display(server, false); + return vigs_server_process_captured(server, force); + } + } else { + *displayed = false; + } + + vigs_server_finish_update_display(server, false); + + return false; +} + +static bool vigs_onscreen_server_capture(struct vigs_server *server, + struct vigs_surface *sfc, + void *pixels) +{ + return server->backend->capture(sfc, pixels); +} + +static void vigs_onscreen_server_destroy(struct vigs_server *server) +{ + struct vigs_onscreen_server *onscreen_server = + (struct vigs_onscreen_server*)server; + + qemu_cond_destroy(&onscreen_server->cond); + qemu_mutex_destroy(&onscreen_server->mutex); + + vigs_server_cleanup(server); + + g_free(server); +} + +struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr, + uint8_t *ram_ptr, + struct vigs_display_ops *display_ops, + struct vigs_capture_ops *capture_ops, + void *display_user_data, + struct vigs_backend *backend, + struct work_queue *render_queue) +{ + struct vigs_onscreen_server *server = NULL; + + server = g_malloc0(sizeof(*server)); + + if (!vigs_server_init(&server->base, vram_ptr, ram_ptr, + display_ops, capture_ops, display_user_data, + backend, render_queue)) { + g_free(server); + return NULL; + } + + qemu_mutex_init(&server->mutex); + qemu_cond_init(&server->cond); + + server->base.begin_update = &vigs_onscreen_server_begin_update; + server->base.finish_update = &vigs_onscreen_server_finish_update; + server->base.display = &vigs_onscreen_server_display; + server->base.capture = &vigs_onscreen_server_capture; + server->base.destroy = &vigs_onscreen_server_destroy; + + return &server->base; +} diff --git a/hw/vigs/vigs_onscreen_server.h b/hw/vigs/vigs_onscreen_server.h new file mode 100644 index 0000000000..b0ea1e93d7 --- /dev/null +++ b/hw/vigs/vigs_onscreen_server.h @@ -0,0 +1,56 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef _QEMU_VIGS_ONSCREEN_SERVER_H +#define _QEMU_VIGS_ONSCREEN_SERVER_H + +#include "vigs_server.h" + +struct vigs_onscreen_server +{ + struct vigs_server base; + + QemuMutex mutex; + QemuCond cond; + bool updated; + bool composited; + bool dirty; + + int invalidate_cnt; +}; + +struct vigs_server *vigs_onscreen_server_create(uint8_t *vram_ptr, + uint8_t *ram_ptr, + struct vigs_display_ops *display_ops, + struct vigs_capture_ops *capture_ops, + void *display_user_data, + struct vigs_backend *backend, + struct work_queue *render_queue); + +#endif diff --git a/hw/vigs/vigs_qt5.cpp b/hw/vigs/vigs_qt5.cpp new file mode 100644 index 0000000000..1166c8d561 --- /dev/null +++ b/hw/vigs/vigs_qt5.cpp @@ -0,0 +1,171 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "vigs_qt5.h" +#include "config-host.h" +#include +#include +#include +#include + +extern QApplication *qt5App; +extern QOpenGLContext *qt5GLContext; +extern QSurfaceFormat qt5GLFormat; + +extern void qt5_register_capture_request_listener(void *listener, + void (*handler)(void *)); +extern void qt5_unregister_capture_request_listener(void *listener); +extern void qt5_process_captured(bool captured, void *pixels, + int width, int height); + +bool vigs_qt5_onscreen_enabled(void) +{ +#ifndef CONFIG_DARWIN + /* Qt5 bug, QGLWidget has some problem on MacOS. + * (scrambled screen when resizing, invalid region masking) */ + if (qt5App != NULL) { + return true; + } +#endif + + return false; +} + +void *vigs_qt5_display(void) +{ + if (!qt5App) { + return NULL; + } + + QPlatformNativeInterface *native = + QGuiApplication::platformNativeInterface(); + + return native->nativeResourceForScreen(QByteArray("display"), + QGuiApplication::primaryScreen()); +} + +void *vigs_qt5_gl_context_create(bool is_gl2) +{ + if (!qt5App) { + fprintf(stderr, "QT5 not enabled!\n"); + return NULL; + } + + if (qt5GLContext) { + fprintf(stderr, "QT5 GL context already created!\n"); + return NULL; + } + + qt5GLContext = new QOpenGLContext(); + + QSurfaceFormat format; + + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + format.setAlphaBufferSize(8); + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + + if (!is_gl2) { + format.setMajorVersion(3); +#ifdef CONFIG_DARWIN + format.setMinorVersion(2); + format.setProfile(QSurfaceFormat::CoreProfile); +#else + format.setMinorVersion(1); +#endif + } + + qt5GLContext->setScreen(QGuiApplication::primaryScreen()); + qt5GLContext->setFormat(format); + + if (!qt5GLContext->create()) { + fprintf(stderr, "Cannot create QT5 GL context!\n"); + + delete qt5GLContext; + qt5GLContext = NULL; + + return NULL; + } + + if (!is_gl2) { + if ((qt5GLContext->format().majorVersion() < 3) || + ((qt5GLContext->format().majorVersion() == 3) && + (qt5GLContext->format().minorVersion() < 1))) { + fprintf(stderr, "Cannot create QT5 3.1 GL context!\n"); + + delete qt5GLContext; + qt5GLContext = NULL; + + return NULL; + } + } + + QPlatformNativeInterface *native = + QGuiApplication::platformNativeInterface(); + + void *ret = NULL; + +#if defined(CONFIG_LINUX) + ret = native->nativeResourceForContext(QByteArray("glxcontext"), qt5GLContext); +#elif defined(CONFIG_WIN32) + ret = native->nativeResourceForContext(QByteArray("renderingContext"), qt5GLContext); +#elif defined(CONFIG_DARWIN) + ret = native->nativeResourceForContext(QByteArray("cglContextObj"), qt5GLContext); +#endif + + if (!ret) { + fprintf(stderr, "Cannot get native QT5 GL context!\n"); + + delete qt5GLContext; + qt5GLContext = NULL; + } + + qt5GLFormat = format; + + return ret; +} + +void vigs_qt5_register_capture_request_listener(void *listener, + void (*handler)(void *)) +{ + qt5_register_capture_request_listener(listener, handler); +} + +void vigs_qt5_unregister_capture_request_listener(void *listener) +{ + qt5_unregister_capture_request_listener(listener); +} + +void vigs_qt5_process_captured(bool captured, void *pixels, + int width, int height) +{ + qt5_process_captured(captured, pixels, width, height); +} diff --git a/hw/vigs/vigs_qt5.h b/hw/vigs/vigs_qt5.h new file mode 100644 index 0000000000..b88c84ebf8 --- /dev/null +++ b/hw/vigs/vigs_qt5.h @@ -0,0 +1,53 @@ +/* + * vigs + * + * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Stanislav Vorobiov + * Jinhyung Jo + * YeongKyoon Lee + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef _QEMU_VIGS_QT5_H +#define _QEMU_VIGS_QT5_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool vigs_qt5_onscreen_enabled(void); + +void *vigs_qt5_display(void); + +void *vigs_qt5_gl_context_create(bool is_gl2); + +void vigs_qt5_register_capture_request_listener(void *listener, + void (*handler)(void *)); +void vigs_qt5_unregister_capture_request_listener(void *listener); +void vigs_qt5_process_captured(bool captured, void *pixels, + int width, int height); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/hw/vigs/vigs_qt5_stub.c b/hw/vigs/vigs_qt5_stub.c new file mode 100644 index 0000000000..94bf46d666 --- /dev/null +++ b/hw/vigs/vigs_qt5_stub.c @@ -0,0 +1,71 @@ +/* + * vigs stub + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Kitae Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +/* + * This is just a temporary implemention to fix compilation errors + * in case of "disable-qt" configuration. We should consider it later. + */ + +#include "emulator_common.h" +#include "vigs_qt5.h" + +uint32_t qt5_window_width = 0; +uint32_t qt5_window_height = 0; +int qt5_window_angle = 0; + +bool vigs_qt5_onscreen_enabled(void) +{ + return false; +} + +void *vigs_qt5_display(void) +{ + return NULL; +} + +void *vigs_qt5_gl_context_create(bool is_gl2) +{ + return NULL; +} + +void vigs_qt5_register_capture_request_listener(void *listener, + void (*handler)(void *)) +{ + return; +} + +void vigs_qt5_unregister_capture_request_listener(void *listener) +{ + return; +} + +void vigs_qt5_process_captured(bool captured, void *pixels, + int width, int height) +{ + return; +} diff --git a/hw/vigs/vigs_server.c b/hw/vigs/vigs_server.c index 42124533fc..3c3b184409 100644 --- a/hw/vigs/vigs_server.c +++ b/hw/vigs/vigs_server.c @@ -438,6 +438,36 @@ static void vigs_server_work(struct work_queue_item *wq_item) g_free(item); } +static void vigs_server_capture_work(struct work_queue_item *wq_item) +{ + struct vigs_server_work_item *item = (struct vigs_server_work_item*)wq_item; + struct vigs_server *server = item->server; + struct vigs_surface *root_sfc = server->root_sfc; + bool captured = false; + void *pixels; + + if (!root_sfc) { + return; + } + + qemu_mutex_lock(&server->capture_mutex); + + pixels = vigs_server_get_capture_buffer(server, root_sfc); + + if (pixels) { + captured = server->capture(server, root_sfc, pixels); + } + + server->capture_ops->process_captured(captured, + pixels, + root_sfc->ws_sfc->width, + root_sfc->ws_sfc->height); + + qemu_mutex_unlock(&server->capture_mutex); + + g_free(item); +} + static void vigs_server_set_root_surface_work(struct work_queue_item *wq_item) { struct vigs_server_set_root_surface_work_item *item = @@ -486,111 +516,52 @@ out: g_free(item); } -static uint8_t *vigs_server_update_display_start_cb(void *user_data, - uint32_t width, - uint32_t height, - uint32_t stride, - vigsp_surface_format format) -{ - struct vigs_server *server = user_data; - - qemu_mutex_lock(&server->capture_mutex); - - if ((server->captured.stride != stride) || - (server->captured.height != height)) { - g_free(server->captured.data); - server->captured.data = g_malloc(stride * height); - } - - server->captured.width = width; - server->captured.height = height; - server->captured.stride = stride; - server->captured.format = format; - - return server->captured.data; -} - -static void vigs_server_update_display_end_cb(void *user_data, - bool was_started, - bool dirty) -{ - struct vigs_server *server = user_data; - uint32_t capture_fence_seq; - - if (!was_started) { - qemu_mutex_lock(&server->capture_mutex); - } - - if (dirty) { - server->captured.dirty = true; - } - - server->is_capturing = false; - capture_fence_seq = server->capture_fence_seq; - server->capture_fence_seq = 0; - - qemu_mutex_unlock(&server->capture_mutex); - - if (capture_fence_seq) { - server->display_ops->fence_ack(server->display_user_data, - capture_fence_seq); - } -} - static void vigs_server_update_display_work(struct work_queue_item *wq_item) { struct vigs_server_work_item *item = (struct vigs_server_work_item*)wq_item; struct vigs_server *server = item->server; struct vigs_surface *root_sfc = server->root_sfc; - int i; - bool planes_on = false; bool planes_dirty = false; + bool dirty = false; + bool composited = false; + int i, index; if (!root_sfc) { /* * If no root surface then this is a no-op. * TODO: Can planes be enabled without a root surface ? */ - vigs_server_update_display_end_cb(server, false, false); goto out; } for (i = 0; i < VIGS_MAX_PLANES; ++i) { - if (!planes_dirty) { - planes_dirty = vigs_plane_dirty(&server->planes[i]); - } - - if (!planes_on) { - planes_on = vigs_plane_enabled(&server->planes[i]); - } + planes_dirty |= vigs_plane_dirty(&server->planes[i]); } - if (root_sfc->ptr && !root_sfc->is_dirty && !planes_on) { - /* - * Root surface is scanout, it's not dirty and planes not on, - * finish immediately. - */ - uint8_t *buff = vigs_server_update_display_start_cb(server, - root_sfc->ws_sfc->width, - root_sfc->ws_sfc->height, - root_sfc->stride, - root_sfc->format); - - memcpy(buff, - root_sfc->ptr, - root_sfc->stride * root_sfc->ws_sfc->height); - - vigs_server_update_display_end_cb(server, true, true); - } else if (root_sfc->ptr || root_sfc->is_dirty || planes_dirty) { + if (root_sfc->ptr || root_sfc->is_dirty || planes_dirty) { /* * Composite root surface and planes. */ + composited = true; + + index = (&server->capture_buffers[0] == server->captured) ? 1 : 0; + + if ((server->capture_buffers[index].stride != root_sfc->stride) || + (server->capture_buffers[index].height != root_sfc->ws_sfc->height)) { + g_free(server->capture_buffers[index].data); + server->capture_buffers[index].data = g_malloc(root_sfc->stride * root_sfc->ws_sfc->height); + } + + server->capture_buffers[index].width = root_sfc->ws_sfc->width; + server->capture_buffers[index].height = root_sfc->ws_sfc->height; + server->capture_buffers[index].stride = root_sfc->stride; + server->capture_buffers[index].format = root_sfc->format; + server->backend->batch_start(server->backend); - server->backend->composite(root_sfc, - &server->planes[0], - &vigs_server_update_display_start_cb, - &vigs_server_update_display_end_cb, - server); + dirty = server->backend->composite(root_sfc, + &server->planes[0], + planes_dirty, + server->capture_buffers[index].data); server->backend->batch_end(server->backend); root_sfc->is_dirty = false; @@ -598,14 +569,11 @@ static void vigs_server_update_display_work(struct work_queue_item *wq_item) for (i = 0; i < VIGS_MAX_PLANES; ++i) { vigs_plane_reset_dirty(&server->planes[i]); } - } else { - /* - * No changes, no-op. - */ - vigs_server_update_display_end_cb(server, false, false); } out: + server->finish_update(server, composited, dirty); + g_free(item); } @@ -725,23 +693,36 @@ static struct vigs_comm_ops vigs_server_dispatch_ops = .batch = &vigs_server_dispatch_batch }; -struct vigs_server *vigs_server_create(uint8_t *vram_ptr, - uint8_t *ram_ptr, - struct vigs_display_ops *display_ops, - void *display_user_data, - struct vigs_backend *backend, - struct work_queue *render_queue) +static void vigs_server_capture(void *data) { - struct vigs_server *server = NULL; + struct vigs_server *server = (struct vigs_server*)data; + struct vigs_server_work_item *item; + + item = g_malloc(sizeof(*item)); - server = g_malloc0(sizeof(*server)); + work_queue_item_init(&item->base, &vigs_server_capture_work); + item->server = server; + + work_queue_add_item(server->capture_queue, &item->base); +} + +bool vigs_server_init(struct vigs_server *server, + uint8_t *vram_ptr, + uint8_t *ram_ptr, + struct vigs_display_ops *display_ops, + struct vigs_capture_ops *capture_ops, + void *display_user_data, + struct vigs_backend *backend, + struct work_queue *render_queue) +{ server->wsi.ws_info = backend->ws_info; server->wsi.acquire_surface = &vigs_server_acquire_surface; server->wsi.fence_ack = &vigs_server_fence_ack; server->vram_ptr = vram_ptr; server->display_ops = display_ops; + server->capture_ops = capture_ops; server->display_user_data = display_user_data; server->backend = backend; server->render_queue = render_queue; @@ -749,7 +730,7 @@ struct vigs_server *vigs_server_create(uint8_t *vram_ptr, server->comm = vigs_comm_create(ram_ptr); if (!server->comm) { - goto fail; + return false; } server->surfaces = g_hash_table_new_full(g_direct_hash, @@ -759,24 +740,28 @@ struct vigs_server *vigs_server_create(uint8_t *vram_ptr, qemu_mutex_init(&server->capture_mutex); - return server; + server->captured = &server->capture_buffers[0]; -fail: - g_free(server); + server->capture_queue = work_queue_create("capture_queue"); + server->capture_ops->register_listener(server, + vigs_server_capture); - return NULL; + return true; } -void vigs_server_destroy(struct vigs_server *server) +void vigs_server_cleanup(struct vigs_server *server) { vigs_server_reset(server); + server->capture_ops->unregister_listener(server); + g_hash_table_destroy(server->surfaces); vigs_comm_destroy(server->comm); server->backend->destroy(server->backend); qemu_mutex_destroy(&server->capture_mutex); - g_free(server->captured.data); - g_free(server); + g_free(server->capture_buffers[0].data); + g_free(server->capture_buffers[1].data); + g_free(server->capture_buffers[2].data); } void vigs_server_reset(struct vigs_server *server) @@ -812,88 +797,114 @@ void vigs_server_dispatch(struct vigs_server *server, } bool vigs_server_update_display(struct vigs_server *server, int invalidate_cnt) +{ + bool is_capturing = server->is_capturing; + + bool updated = server->begin_update(server, is_capturing, (invalidate_cnt > 0)); + + if (!is_capturing) { + struct vigs_server_work_item *item; + + item = g_malloc(sizeof(*item)); + + work_queue_item_init(&item->base, &vigs_server_update_display_work); + + item->server = server; + + server->is_capturing = true; + + work_queue_add_item(server->render_queue, &item->base); + } + + return updated; +} + +bool vigs_server_display(struct vigs_server *server, bool *displayed) +{ + return server->display(server, displayed); +} + +void *vigs_server_get_capture_buffer(struct vigs_server *server, + struct vigs_surface *sfc) +{ + const int index = 2; + + if ((server->capture_buffers[index].stride != sfc->stride) || + (server->capture_buffers[index].height != sfc->ws_sfc->height)) { + g_free(server->capture_buffers[index].data); + server->capture_buffers[index].data = g_malloc(sfc->stride * sfc->ws_sfc->height); + } + + server->capture_buffers[index].width = sfc->ws_sfc->width; + server->capture_buffers[index].height = sfc->ws_sfc->height; + server->capture_buffers[index].stride = sfc->stride; + server->capture_buffers[index].format = sfc->format; + + return server->capture_buffers[index].data; +} + +bool vigs_server_process_captured(struct vigs_server *server, bool force) { bool updated = false; - uint32_t sfc_bpp; uint32_t display_stride, display_bpp; uint8_t *display_data; qemu_mutex_lock(&server->capture_mutex); - if (!server->captured.data || - (!server->captured.dirty && invalidate_cnt <= 0)) { + if (!server->captured->data || + (!server->captured->dirty && !force)) { goto out; } - server->captured.dirty = false; - updated = true; - - sfc_bpp = vigs_format_bpp(server->captured.format); + server->captured->dirty = false; server->display_ops->resize(server->display_user_data, - server->captured.width, - server->captured.height); + server->captured->width, + server->captured->height); display_stride = server->display_ops->get_stride(server->display_user_data); display_bpp = server->display_ops->get_bpp(server->display_user_data); display_data = server->display_ops->get_data(server->display_user_data); - if (sfc_bpp != display_bpp) { - VIGS_LOG_CRITICAL("bpp mismatch"); + if ((vigs_format_bpp(server->captured->format) != display_bpp) || + (server->captured->stride != display_stride)) { + VIGS_LOG_CRITICAL("bpp/format mismatch"); assert(false); - exit(1); - } - - if (display_stride == server->captured.stride) { - switch (server->captured.format) { - case vigsp_surface_bgrx8888: - case vigsp_surface_bgra8888: - memcpy(display_data, - server->captured.data, - server->captured.height * display_stride); - break; - default: - assert(false); - VIGS_LOG_CRITICAL("unknown format: %d", server->captured.format); - exit(1); - } - } else { - uint32_t i; - uint8_t *src = server->captured.data; - uint8_t *dst = display_data; - - for (i = 0; i < server->captured.height; ++i) { - switch (server->captured.format) { - case vigsp_surface_bgrx8888: - case vigsp_surface_bgra8888: - memcpy(dst, src, server->captured.width * sfc_bpp); - break; - default: - assert(false); - VIGS_LOG_CRITICAL("unknown format: %d", server->captured.format); - exit(1); - } - src += server->captured.stride; - dst += display_stride; - } + goto out; } + memcpy(display_data, + server->captured->data, + server->captured->stride * server->captured->height); + + updated = true; + out: qemu_mutex_unlock(&server->capture_mutex); - if (!server->is_capturing) { - struct vigs_server_work_item *item; + return updated; +} - item = g_malloc(sizeof(*item)); +void vigs_server_finish_update_display(struct vigs_server *server, bool dirty) +{ + uint32_t capture_fence_seq = 0; - work_queue_item_init(&item->base, &vigs_server_update_display_work); + qemu_mutex_lock(&server->capture_mutex); - item->server = server; + if (dirty) { + int index = (&server->capture_buffers[0] == server->captured) ? 1 : 0; + server->capture_buffers[index].dirty = true; + server->captured = &server->capture_buffers[index]; + } - server->is_capturing = true; + server->is_capturing = false; + capture_fence_seq = server->capture_fence_seq; + server->capture_fence_seq = 0; - work_queue_add_item(server->render_queue, &item->base); - } + qemu_mutex_unlock(&server->capture_mutex); - return updated; + if (capture_fence_seq) { + server->display_ops->fence_ack(server->display_user_data, + capture_fence_seq); + } } diff --git a/hw/vigs/vigs_server.h b/hw/vigs/vigs_server.h index 7bb902bd87..15f64e5e37 100644 --- a/hw/vigs/vigs_server.h +++ b/hw/vigs/vigs_server.h @@ -67,6 +67,17 @@ struct vigs_display_ops uint32_t /*fence_seq*/); }; +struct vigs_capture_ops +{ + void (*register_listener)(void */*listener*/, + void (*handler)(void */*listener*/)); + void (*unregister_listener)(void */*listener*/); + void (*process_captured)(bool /*captured*/, + void */*pixels*/, + uint32_t /*width*/, + uint32_t /*height*/); +}; + struct vigs_server { struct winsys_interface wsi; @@ -74,12 +85,16 @@ struct vigs_server uint8_t *vram_ptr; struct vigs_display_ops *display_ops; + struct vigs_capture_ops *capture_ops; + void *display_user_data; struct vigs_backend *backend; struct work_queue *render_queue; + struct work_queue *capture_queue; + struct vigs_comm *comm; /* @@ -110,21 +125,39 @@ struct vigs_server uint32_t stride; vigsp_surface_format format; bool dirty; - } captured; + } capture_buffers[3], *captured; /* * @} */ + + bool (*begin_update)(struct vigs_server */*server*/, + bool /*is_capturing*/, + bool /*force*/); + + void (*finish_update)(struct vigs_server */*server*/, + bool /*composited*/, + bool /*dirty*/); + + bool (*display)(struct vigs_server */*server*/, bool */*displayed*/); + + bool (*capture)(struct vigs_server */*server*/, + struct vigs_surface */*sfc*/, + void */*pixels*/); + + void (*destroy)(struct vigs_server */*server*/); }; -struct vigs_server *vigs_server_create(uint8_t *vram_ptr, - uint8_t *ram_ptr, - struct vigs_display_ops *display_ops, - void *display_user_data, - struct vigs_backend *backend, - struct work_queue *render_queue); +bool vigs_server_init(struct vigs_server *server, + uint8_t *vram_ptr, + uint8_t *ram_ptr, + struct vigs_display_ops *display_ops, + struct vigs_capture_ops *capture_ops, + void *display_user_data, + struct vigs_backend *backend, + struct work_queue *render_queue); -void vigs_server_destroy(struct vigs_server *server); +void vigs_server_cleanup(struct vigs_server *server); void vigs_server_reset(struct vigs_server *server); @@ -133,4 +166,22 @@ void vigs_server_dispatch(struct vigs_server *server, bool vigs_server_update_display(struct vigs_server *server, int invalidate_cnt); +bool vigs_server_display(struct vigs_server *server, bool *displayed); + +void *vigs_server_get_capture_buffer(struct vigs_server *server, + struct vigs_surface *sfc); + +/* + * For internal use only. + * @{ + */ + +bool vigs_server_process_captured(struct vigs_server *server, bool force); + +void vigs_server_finish_update_display(struct vigs_server *server, bool dirty); + +/* + * @} + */ + #endif diff --git a/hw/vigs/vigs_sw_backend.c b/hw/vigs/vigs_sw_backend.c index ee3869d1ad..2261ebcb71 100644 --- a/hw/vigs/vigs_sw_backend.c +++ b/hw/vigs/vigs_sw_backend.c @@ -377,39 +377,48 @@ static struct vigs_surface *vigs_sw_backend_create_surface(struct vigs_backend * return &sw_sfc->base; } -static void vigs_sw_backend_composite(struct vigs_surface *surface, +static bool vigs_sw_backend_composite(struct vigs_surface *surface, const struct vigs_plane *planes, - vigs_composite_start_cb start_cb, - vigs_composite_end_cb end_cb, - void *user_data) + bool planes_dirty, + uint8_t *display_data) { struct vigs_sw_surface *sw_sfc = (struct vigs_sw_surface*)surface; - uint8_t *buff; /* * TODO: Render planes. */ - buff = start_cb(user_data, surface->ws_sfc->width, surface->ws_sfc->height, - surface->stride, surface->format); - if (surface->ptr) { - memcpy(buff, + memcpy(display_data, surface->ptr, surface->stride * surface->ws_sfc->height); - } else if (surface->is_dirty) { - memcpy(buff, + } else { + memcpy(display_data, sw_sfc->data, surface->stride * surface->ws_sfc->height); } - end_cb(user_data, true, true); + return true; +} + +static bool vigs_sw_backend_capture(struct vigs_surface *surface, + void *pixels) +{ + vigs_sw_backend_composite(surface, NULL, false, pixels); + + return true; } static void vigs_sw_backend_batch_end(struct vigs_backend *backend) { } +static bool vigs_sw_backend_display(struct vigs_backend *backend, + uint8_t *display_data) +{ + return false; +} + static void vigs_sw_backend_destroy(struct vigs_backend *backend) { struct vigs_sw_backend *sw_backend = (struct vigs_sw_backend*)backend; @@ -429,7 +438,9 @@ struct vigs_backend *vigs_sw_backend_create(void) backend->base.batch_start = &vigs_sw_backend_batch_start; backend->base.create_surface = &vigs_sw_backend_create_surface; backend->base.composite = &vigs_sw_backend_composite; + backend->base.capture = &vigs_sw_backend_capture; backend->base.batch_end = &vigs_sw_backend_batch_end; + backend->base.display = &vigs_sw_backend_display; backend->base.destroy = &vigs_sw_backend_destroy; return &backend->base; diff --git a/hw/yagl/Makefile.objs b/hw/yagl/Makefile.objs index 2453ae9f4f..fcd358f7d2 100644 --- a/hw/yagl/Makefile.objs +++ b/hw/yagl/Makefile.objs @@ -1,5 +1,3 @@ -QEMU_CFLAGS += -I$(SRC_PATH)/hw/yagl -I$(SRC_PATH)/hw/yagl/yagl_inc - obj-y += yagl_device.o obj-y += yagl_log.o obj-y += yagl_process.o @@ -29,3 +27,5 @@ obj-y += yagl_egl_surface_attribs.o obj-y += yagl_apis/ obj-y += yagl_backends/ obj-y += yagl_drivers/ + +$(obj)/%.o: QEMU_CFLAGS += -I$(SRC_PATH)/hw/yagl -I$(SRC_PATH)/hw/yagl/yagl_inc diff --git a/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c b/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c index 31bf8d63c2..8e242556a6 100644 --- a/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c +++ b/hw/yagl/yagl_drivers/egl_cgl/yagl_egl_cgl.c @@ -55,7 +55,6 @@ static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] = kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFANoRecovery, kCGLPFAPBuffer, 0 }; @@ -68,7 +67,6 @@ static const CGLPixelFormatAttribute pixel_format_3_2_core_attrs[] = kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFANoRecovery, kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, 0 }; diff --git a/hw/yagl/yagl_drivers/egl_glx/yagl_egl_glx.c b/hw/yagl/yagl_drivers/egl_glx/yagl_egl_glx.c index e73af91726..08afac4892 100644 --- a/hw/yagl/yagl_drivers/egl_glx/yagl_egl_glx.c +++ b/hw/yagl/yagl_drivers/egl_glx/yagl_egl_glx.c @@ -123,6 +123,16 @@ struct yagl_egl_glx PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB; }; +static const char *gl_3_2_check_funcs[] = +{ + "glGenTransformFeedbacks", + "glBindTransformFeedback", + "glPauseTransformFeedback", + "glResumeTransformFeedback", + "glDeleteTransformFeedbacks", + "glVertexAttribDivisor" +}; + static bool yagl_egl_glx_get_gl_version(struct yagl_egl_glx *egl_glx, yagl_gl_version *version) { @@ -172,6 +182,7 @@ static bool yagl_egl_glx_get_gl_version(struct yagl_egl_glx *egl_glx, const GLubyte *(GLAPIENTRY *GetStringi)(GLenum, GLuint) = NULL; void (GLAPIENTRY *GetIntegerv)(GLenum, GLint*) = NULL; GLint i, num_extensions = 0; + unsigned int j; YAGL_EGL_GLX_ENTER(yagl_egl_glx_get_gl_version, NULL); @@ -239,6 +250,19 @@ static bool yagl_egl_glx_get_gl_version(struct yagl_egl_glx *egl_glx, goto out; } + for (j = 0; + j < sizeof(gl_3_2_check_funcs)/sizeof(gl_3_2_check_funcs[0]); + ++j) { + if (!yagl_dyn_lib_get_ogl_procaddr(egl_glx->base.dyn_lib, + gl_3_2_check_funcs[j])) { + YAGL_LOG_INFO("Failed to find function \"%s\", using OpenGL 2.1", + gl_3_2_check_funcs[j]); + *version = yagl_gl_2; + res = true; + goto out; + } + } + GetStringi = yagl_dyn_lib_get_ogl_procaddr(egl_glx->base.dyn_lib, "glGetStringi"); diff --git a/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c b/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c index c900234a14..dd62b5e30b 100644 --- a/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c +++ b/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c @@ -126,6 +126,16 @@ static inline HWND yagl_egl_wgl_dummy_win_create(void) WS_DISABLED | WS_POPUP, 0, 0, 1, 1, NULL, NULL, 0, 0); } +static const char *gl_3_2_check_funcs[] = +{ + "glGenTransformFeedbacks", + "glBindTransformFeedback", + "glPauseTransformFeedback", + "glResumeTransformFeedback", + "glDeleteTransformFeedbacks", + "glVertexAttribDivisor" +}; + static bool yagl_egl_wgl_get_gl_version(YaglEglWglDriver *egl_wgl, yagl_gl_version *version) { @@ -178,6 +188,7 @@ static bool yagl_egl_wgl_get_gl_version(YaglEglWglDriver *egl_wgl, const GLubyte *(GLAPIENTRY *GetStringi)(GLenum, GLuint) = NULL; void (GLAPIENTRY *GetIntegerv)(GLenum, GLint*) = NULL; GLint i, num_extensions = 0; + unsigned int j; YAGL_EGL_WGL_ENTER(yagl_egl_wgl_get_gl_version, NULL); @@ -275,6 +286,19 @@ static bool yagl_egl_wgl_get_gl_version(YaglEglWglDriver *egl_wgl, goto out6; } + for (j = 0; + j < sizeof(gl_3_2_check_funcs)/sizeof(gl_3_2_check_funcs[0]); + ++j) { + if (!yagl_dyn_lib_get_ogl_procaddr(egl_wgl->base.dyn_lib, + gl_3_2_check_funcs[j])) { + YAGL_LOG_INFO("Failed to find function \"%s\", using OpenGL 2.1", + gl_3_2_check_funcs[j]); + *version = yagl_gl_2; + res = true; + goto out7; + } + } + GetStringi = yagl_dyn_lib_get_ogl_procaddr(egl_wgl->base.dyn_lib, "glGetStringi"); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 22e66cb10d..57b31073ad 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -103,6 +103,7 @@ typedef enum DisplayType #ifdef CONFIG_MARU DT_MARU_SDL, DT_MARU_SHM, + DT_MARU_QT, #endif DT_NONE, } DisplayType; diff --git a/include/ui/console.h b/include/ui/console.h index 0433b2e4f0..28986208d6 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -1,7 +1,9 @@ #ifndef CONSOLE_H #define CONSOLE_H +#ifndef __cplusplus #include "ui/qemu-pixman.h" +#endif #include "qom/object.h" #include "qapi/qmp/qdict.h" #include "qemu/notify.h" @@ -369,5 +371,4 @@ int index_from_key(const char *key); /* gtk.c */ void early_gtk_display_init(void); void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover); - #endif diff --git a/tizen/emulator_configure.sh b/tizen/emulator_configure.sh index b9f59d405a..e045a00ec9 100755 --- a/tizen/emulator_configure.sh +++ b/tizen/emulator_configure.sh @@ -199,6 +199,7 @@ echo "##### QEMU configuring for emulator" echo "##### QEMU configure append:" $CONFIGURE_APPEND exec ./configure \ --enable-werror \ + --extra-ldflags=-Wl,--export-dynamic \ --audio-drv-list=alsa \ --disable-vnc \ --disable-pie \ @@ -217,6 +218,7 @@ exec ./configure \ --extra-cflags=-Wno-error=format-extra-args \ --extra-cflags=-Wno-error=redundant-decls \ --extra-ldflags=-Wl,--large-address-aware \ + --extra-ldflags=-Wl,--export-all-symbols \ --cc=gcc \ --audio-drv-list=winwave \ --enable-hax \ @@ -224,6 +226,7 @@ exec ./configure \ $CONFIGURE_APPEND \ ;; Darwin*) +# FIXME: "-export_dynamic" causes error on old version clang cd .. echo "" echo "##### QEMU configuring for emulator" @@ -238,5 +241,7 @@ echo "##### QEMU configure append:" $CONFIGURE_APPEND --disable-cocoa \ --disable-sdl \ $CONFIGURE_APPEND \ + +# --extra-ldflags="-Xlinker -export_dynamic" \ ;; esac diff --git a/tizen/src/Makefile b/tizen/src/Makefile index 78ca6b33af..97058f1c8e 100644 --- a/tizen/src/Makefile +++ b/tizen/src/Makefile @@ -337,6 +337,14 @@ ifdef CONFIG_DARWIN install_name_tool -change /opt/local/lib/libcurl.4.dylib @loader_path/libcurl.4.dylib $(DIBS_X86_DIR)/bin/emulator-x86 ;\ install_name_tool -change /opt/local/lib/libpixman-1.0.dylib @loader_path/libpixman-1.0.dylib $(DIBS_X86_DIR)/bin/emulator-x86 ;\ install_name_tool -change /opt/local/lib/libpng16.16.dylib @loader_path/libpng16.dylib $(DIBS_X86_DIR)/bin/emulator-x86; \ +ifdef CONFIG_QT + install_name_tool -change /opt/local/Library/Frameworks/QtQml.framework/Versions/5/QtQml @loader_path/QtQml $(DIBS_X86_DIR)/bin/emulator-x86; \ + install_name_tool -change /opt/local/Library/Frameworks/QtNetwork.framework/Versions/5/QtNetwork @loader_path/QtNetwork $(DIBS_X86_DIR)/bin/emulator-x86; \ + install_name_tool -change /opt/local/Library/Frameworks/QtOpenGL.framework/Versions/5/QtOpenGL @loader_path/QtOpenGL $(DIBS_X86_DIR)/bin/emulator-x86; \ + install_name_tool -change /opt/local/Library/Frameworks/QtWidgets.framework/Versions/5/QtWidgets @loader_path/QtWidgets $(DIBS_X86_DIR)/bin/emulator-x86; \ + install_name_tool -change /opt/local/Library/Frameworks/QtGui.framework/Versions/5/QtGui @loader_path/QtGui $(DIBS_X86_DIR)/bin/emulator-x86; \ + install_name_tool -change /opt/local/Library/Frameworks/QtCore.framework/Versions/5/QtCore @loader_path/QtCore $(DIBS_X86_DIR)/bin/emulator-x86; \ +endif ;; \ arm-softmmu) \ ;; \ diff --git a/tizen/src/Makefile.objs b/tizen/src/Makefile.objs index c3127b7e92..14a547a2f8 100644 --- a/tizen/src/Makefile.objs +++ b/tizen/src/Makefile.objs @@ -8,6 +8,9 @@ obj-y += emulator.o emulator_legacy.o emulator_options.o emul_state.o # utils obj-y += util/ +# ui +obj-y += ui/ + # maru display obj-y += display/ diff --git a/tizen/src/display/Makefile.objs b/tizen/src/display/Makefile.objs index 796f50862d..b8e49dceb6 100644 --- a/tizen/src/display/Makefile.objs +++ b/tizen/src/display/Makefile.objs @@ -4,4 +4,9 @@ obj-$(CONFIG_USE_SHM) += maru_shm.o obj-$(CONFIG_SDL) += maru_sdl.o maru_sdl_processing.o maru_finger.o +obj-$(CONFIG_QT) += qt5.o +obj-$(CONFIG_QT) += qt5_supplement.o + $(obj)/maru_display.o $(obj)/maru_sdl.o $(obj)/maru_sdl_processing.o $(obj)/maru_finger.o: QEMU_CFLAGS += $(SDL_CFLAGS) + +$(obj)/qt5_supplement.o: QEMU_CFLAGS += $(QT_CFLAGS) diff --git a/tizen/src/display/maru_display.c b/tizen/src/display/maru_display.c index ddc34cdc11..b3aa9c2c6c 100644 --- a/tizen/src/display/maru_display.c +++ b/tizen/src/display/maru_display.c @@ -36,7 +36,7 @@ MULTI_DEBUG_CHANNEL(tizen, display); -MaruScreenShot* screenshot = NULL; +MaruScreenShot *screenshot; static MaruDisplayChangeListener *mdcl; @@ -53,16 +53,32 @@ static void maru_display_fini(void) g_free(mdcl); } -static void maru_display_notify_exit(Notifier *notifier, void *data) { +static void maru_display_notify_exit(Notifier *notifier, void *data) +{ maru_display_fini(); } + static Notifier maru_display_exit = { .notify = maru_display_notify_exit }; -void maru_display_init(DisplayState *ds, DisplayType display_type, int full_screen) +void maru_display_early_init(DisplayType display_type) +{ + switch (display_type) { +#ifdef CONFIG_QT + case DT_MARU_QT: + maru_qt5_display_early_init(); + break; +#endif + default: + break; + } +} + +void maru_display_init(DisplayState *ds, DisplayType display_type, + int full_screen) { INFO("init qemu display\n"); - mdcl = g_malloc0(sizeof(MaruDisplayChangeListener)); + mdcl = g_new0(MaruDisplayChangeListener, 1); switch (display_type) { #ifdef CONFIG_SDL @@ -74,14 +90,19 @@ void maru_display_init(DisplayState *ds, DisplayType display_type, int full_scre case DT_MARU_SHM: maru_shm_pre_init(mdcl); break; +#endif +#ifdef CONFIG_QT + case DT_MARU_QT: + maru_qt5_display_init(mdcl, full_screen); + break; #endif default: ERR("can not enter here.\n"); - // can not enter here... + /* can not enter here... */ break; } - screenshot = g_malloc0(sizeof(MaruScreenShot)); + screenshot = g_new0(MaruScreenShot, 1); screenshot->pixels = NULL; screenshot->request = false; screenshot->ready = false; @@ -118,12 +139,13 @@ void maru_display_set_interpolation(bool on) } void maru_ds_surface_init(uint64 swt_handle, - unsigned int display_width, unsigned int display_height, - bool blank_guide) + unsigned int display_width, + unsigned int display_height, + bool blank_guide) { if (mdcl->surface_init) { mdcl->surface_init(swt_handle, display_width, - display_height, blank_guide); + display_height, blank_guide); } } diff --git a/tizen/src/display/maru_display.h b/tizen/src/display/maru_display.h index 8c746f26cd..c58a4aff5b 100644 --- a/tizen/src/display/maru_display.h +++ b/tizen/src/display/maru_display.h @@ -52,7 +52,9 @@ typedef struct MaruScreenShot { bool ready; } MaruScreenShot; -void maru_display_init(DisplayState *ds, DisplayType display_type, int full_screen); +void maru_display_early_init(DisplayType display_type); +void maru_display_init(DisplayState *ds, DisplayType display_type, + int full_screen); void maru_display_resize(void); void maru_display_update(void); void maru_display_set_invalidate(bool on); @@ -65,10 +67,16 @@ void maru_ds_surface_init(uint64 swt_handle, MaruScreenShot *get_screenshot(void); void save_screenshot(DisplaySurface *surface); -// maru_sdl +/* maru_sdl */ void maru_sdl_pre_init(MaruDisplayChangeListener *mdcl); -// maru_shm +/* maru_shm */ void maru_shm_pre_init(MaruDisplayChangeListener *mdcl); +/* maru_qt */ +void maru_qt5_display_early_init(void); + +void maru_qt5_display_init(MaruDisplayChangeListener *mdcl, int full_screen); + +void maru_qt5_display_quit(void); #endif /* __MARU_DISPLAY_H__ */ diff --git a/tizen/src/display/maru_finger.c b/tizen/src/display/maru_finger.c index e628b5dbb5..05b7943809 100644 --- a/tizen/src/display/maru_finger.c +++ b/tizen/src/display/maru_finger.c @@ -230,16 +230,6 @@ void init_multi_touch_state(void) mts->finger_point_surface = (void *)point; } -void set_multi_touch_enable(int enable) -{ - get_emul_multi_touch_state()->multitouch_enable = enable; -} - -int get_multi_touch_enable(void) -{ - return get_emul_multi_touch_state()->multitouch_enable; -} - int add_finger_point(int origin_x, int origin_y, int x, int y) { MultiTouchState *mts = get_emul_multi_touch_state(); diff --git a/tizen/src/display/maru_finger.h b/tizen/src/display/maru_finger.h index d5f071e326..3815d3a61f 100644 --- a/tizen/src/display/maru_finger.h +++ b/tizen/src/display/maru_finger.h @@ -62,8 +62,6 @@ typedef struct MultiTouchState { void init_multi_touch_state(void); -void set_multi_touch_enable(int enable); -int get_multi_touch_enable(void); FingerPoint *get_finger_point_from_slot(int index); FingerPoint *get_finger_point_search(int x, int y); int add_finger_point(int origin_x, int origin_y, int x, int y); diff --git a/tizen/src/display/maru_shm.c b/tizen/src/display/maru_shm.c index 2b0079481e..ef7fc6dbb9 100644 --- a/tizen/src/display/maru_shm.c +++ b/tizen/src/display/maru_shm.c @@ -289,7 +289,6 @@ static void maru_shm_init(uint64 swt_handle, INFO("Memory attached at 0x%X\n", (int)shared_memory); } - void maru_shm_pre_init(MaruDisplayChangeListener *mdcl) { dcl = g_malloc0(sizeof(DisplayChangeListener)); diff --git a/tizen/src/display/qt5.c b/tizen/src/display/qt5.c new file mode 100644 index 0000000000..495a17d5e9 --- /dev/null +++ b/tizen/src/display/qt5.c @@ -0,0 +1,184 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "ui/console.h" +#include "emul_state.h" +#include "maru_display.h" +#include "qt5_supplement.h" + +extern QemuMutex sdl_mutex; +extern QemuCond sdl_cond; + +/* static Notifier mouse_mode_notifier; */ +static int qt5_num_outputs; + +static struct qt5_state { + DisplayChangeListener dcl; + DisplaySurface *surface; + + int idx; +} *qt5_console; + +void qt5_graphic_hw_invalidate(void) +{ + graphic_hw_invalidate(NULL); +} + +int qt5_graphic_hw_display(void) +{ + console_ch_t displayed = 0; + graphic_hw_text_update(NULL, &displayed); + return displayed; +} + +static void qt5_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) +{ + DisplaySurface *surf = qemu_console_surface(dcl->con); + if (!surf) { + return; + } + + qt5_update_internal(surface_data(surf), + surface_width(surf), + surface_height(surf)); +} + +static void qt5_switch(DisplayChangeListener *dcl, + DisplaySurface *new_surface) +{ +} + +static void qt5_refresh(DisplayChangeListener *dcl) +{ + graphic_hw_update(dcl->con); + qt5_refresh_internal(); +} + +static void qt5_mouse_warp(DisplayChangeListener *dcl, + int x, int y, int on) +{ +} + +static void qt5_mouse_define(DisplayChangeListener *dcl, + QEMUCursor *c) +{ +} + +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "qt5", + .dpy_gfx_update = qt5_update, + .dpy_gfx_switch = qt5_switch, + .dpy_refresh = qt5_refresh, + .dpy_mouse_set = qt5_mouse_warp, + .dpy_cursor_define = qt5_mouse_define, +}; + +#ifdef CONFIG_DARWIN +void ns_run_in_event_loop(void (*func)()); +void set_application_icon(char *path); +#endif + +void maru_qt5_display_early_init(void) +{ +#ifdef CONFIG_DARWIN + ns_run_in_event_loop(&qt5_early_prepare); + + /* set emulator icon */ +#define ICON_RESOURCE_PATH "../icons/" +#define ICON_FILE_NAME "emulator_icon.ico" + const int path_len = strlen(get_bin_path()) + + strlen(ICON_RESOURCE_PATH) + strlen(ICON_FILE_NAME) + 1; + + char *icon_path = g_malloc0(sizeof(char) * path_len); + snprintf(icon_path, path_len, "%s%s%s", + get_bin_path(), ICON_RESOURCE_PATH, ICON_FILE_NAME); + fprintf(stdout, "application icon path : %s\n", icon_path); + + set_application_icon(icon_path); + g_free(icon_path); +#else + qt5_early_prepare(); +#endif +} + +void maru_qt5_display_quit(void) +{ + qt5_destroy(); + + if (qt5_console) { + g_free(qt5_console); + qt5_console = NULL; + } +} + +void maru_qt5_display_init(MaruDisplayChangeListener *mdcl, int full_screen) +{ + int i; + +#ifdef SDL_THREAD + qemu_mutex_init(&sdl_mutex); + qemu_cond_init(&sdl_cond); +#endif + + /* prepare gui */ +#ifdef CONFIG_DARWIN + ns_run_in_event_loop(&qt5_prepare); +#else + qt5_prepare(); +#endif + + for (i = 0;; i++) { + QemuConsole *con = qemu_console_lookup_by_index(i); + if (!con || !qemu_console_is_graphic(con)) { + break; + } + } + qt5_num_outputs = i; + qt5_console = g_new0(struct qt5_state, qt5_num_outputs); + for (i = 0; i < qt5_num_outputs; i++) { + QemuConsole *con = qemu_console_lookup_by_index(i); + qt5_console[i].dcl.ops = &dcl_ops; + qt5_console[i].dcl.con = con; + register_displaychangelistener(&qt5_console[i].dcl); + qt5_console[i].idx = i; + } + mdcl->fini = maru_qt5_display_quit; + + if (full_screen) { + /* TODO */ + } + + /* TODO + mouse_mode_notifier.notify = qt2_mouse_mode_change; + qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier); + */ + + /* TODO: cursor control */ +} diff --git a/tizen/src/display/qt5_supplement.cpp b/tizen/src/display/qt5_supplement.cpp new file mode 100644 index 0000000000..34906e1489 --- /dev/null +++ b/tizen/src/display/qt5_supplement.cpp @@ -0,0 +1,546 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * SeokYeon Hwang + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include +#include +#include + +#include "qt5_supplement.h" +#include "mainwindow.h" +#include "uiinformation.h" +#include "hardwarekey.h" +#include "floatingcontroller.h" +#include "ui/xml/emulatoruitype.h" +#include "uiutil.h" + +extern "C" { +#include "emul_state.h" +} + +//using namespace std; +void qMessageOutput(QtMsgType, const QMessageLogContext &, const QString &); +void loadMainFormFromXML(QFile *, UIInformation *); +void loadConFormFromXML(QFile *, UIInformation *); + +QApplication *qt5App = NULL; + +static int argc = 0; +static char *argv[0]; + +static void *captureRequestListener; +static void (*captureRequestHandler)(void *); + +static MainWindow *mainwindow; +static UIInformation *uiInfo; + +#define SKIN_PROPERTIES_FILE_NAME ".skin.properties" +#define SKIN_PROPERTY_WINDOW_X "window.x" +#define SKIN_PROPERTY_WINDOW_Y "window.y" +#define SKIN_PROPERTY_WINDOW_SCALE "window.scale" +#define SKIN_PROPERTY_WINDOW_TOPMOST "window.ontop" +#define SKIN_PROPERTY_CONTROLLER_INDEX "controller.index" +#define SKIN_PROPERTY_CONTROLLER_DOCK "controller.dock" + +#define SKIN_INFO_FILE_NAME "info.ini" +#define FORM_FILE_NAME "layout.qml" +#define CON_FORM_SUBPATH "controller" + +class ConFile { +public: + QFile *formFile; + int priority; +}; + +void qt5_gui_init(void) +{ + QCoreApplication::setApplicationName("Tizen Emulator"); + + qDebug() << "* Qt version :" << QT_VERSION_STR; + qDebug() << "* working path :" << QDir::currentPath(); + qDebug() << "* binary path :" << QCoreApplication::applicationDirPath(); + + uiInfo = new UIInformation(); + + /* parameter parsing */ + // TODO: + + uiInfo->vmName = QString(get_emul_vm_name()).trimmed(); + uiInfo->resolution.setWidth(get_emul_resolution_width()); + uiInfo->resolution.setHeight(get_emul_resolution_height()); + uiInfo->basePort = get_emul_vm_base_port(); + + uiInfo->vmDataPath = get_emul_vm_data_path(); + if (uiInfo->vmDataPath.endsWith(QDir::separator()) == false) { + uiInfo->vmDataPath += QDir::separator(); + } + + uiInfo->skinPath = QDir(get_emul_skin_path()).canonicalPath(); + if (uiInfo->skinPath.endsWith(QDir::separator()) == false) { + uiInfo->skinPath += QDir::separator(); + } + + /* read skin information */ + QSettings skinInfo(uiInfo->skinPath + SKIN_INFO_FILE_NAME, + QSettings::IniFormat); + QString skinName = skinInfo.value("skin.name").toString(); + if (skinName.isEmpty() == true) { + skinName = "Undefined"; + } + uiInfo->skinName = skinName; + + /* read MRU information */ + QSettings mruInfo(uiInfo->vmDataPath + SKIN_PROPERTIES_FILE_NAME, + QSettings::IniFormat); + int scale = mruInfo.value(SKIN_PROPERTY_WINDOW_SCALE).toInt(); + qDebug("previous scale value is %d", scale); + + if (scale <= 0) { + scale = 50; /* default scale */ + } + uiInfo->uiState.mainFormScale = scale; + + /* XML */ + // TODO: convert QML to XML + + /* Register custom QML elements */ + qmlRegisterType("EmulatorComponent", 1, 0, "Region"); + qmlRegisterType("EmulatorComponent", 1, 0, "Key"); + qmlRegisterType("EmulatorComponent", 1, 0, "KeyList"); + + /* load main form */ + QFile mainXMLFile(uiInfo->skinPath + FORM_FILE_NAME); + loadMainFormFromXML(&mainXMLFile, uiInfo); + + /* load controller forms */ + QDir skinDir(uiInfo->skinPath + CON_FORM_SUBPATH); + QFileInfoList entries = skinDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + + if (entries.isEmpty() == false) { + /* sort by priority */ + QList conFileList; + + for (int i = 0; i < entries.size(); i++) { + ConFile *conFile = new ConFile(); + + QString conPath = entries.at(i).filePath() + QDir::separator(); + conFile->formFile = new QFile(conPath + FORM_FILE_NAME); + QSettings conInfo(conPath + SKIN_INFO_FILE_NAME, QSettings::IniFormat); + conFile->priority = conInfo.value("priority").toInt(); + + int j = 0; + for ( ; j < conFileList.size(); j++) { + if (conFileList.at(j)->priority > conFile->priority) { + break; + } + } + conFileList.insert(j, conFile); + } + + /* loading */ + for (int i = 0; i < conFileList.size(); i++) { + loadConFormFromXML(conFileList.at(i)->formFile, uiInfo); + delete conFileList.at(i)->formFile; + delete conFileList.at(i); + } + } + + /* GUI */ + qDebug("start!"); + + mainwindow = new MainWindow(uiInfo); + mainwindow->setCaptureRequestHandler(captureRequestListener, captureRequestHandler); + + /* position */ + QRect hostBounds = UIUtil::getHostScreenBounds(); + qDebug() << "host geometry : " << hostBounds; + + int defaultValueX = hostBounds.x() - 1; + int defaultValueY = hostBounds.y() - 1; + int xx = mruInfo.value(SKIN_PROPERTY_WINDOW_X, defaultValueX).toInt(); + int yy = mruInfo.value(SKIN_PROPERTY_WINDOW_Y, defaultValueY).toInt(); + + if (xx == defaultValueX || yy == defaultValueY) { + xx = yy = 80 + (uiInfo->basePort % 100); /* default position */ + } else { + qDebug("previous position value : (%d, %d)", xx, yy); + + xx = qMax(xx, hostBounds.x()); + xx = qMin(xx, hostBounds.x() + hostBounds.width() - 100); + yy = qMax(yy, hostBounds.y()); + yy = qMin(yy, hostBounds.y() + hostBounds.height() - 100); + } + + mainwindow->move(xx, yy); + qDebug("current position value : (%d, %d)", xx, yy); + + bool onTop = mruInfo.value(SKIN_PROPERTY_WINDOW_TOPMOST).toBool(); + if (onTop == true) { + mainwindow->setTopMost(true); + } + + mainwindow->show(); + + /* controller */ + const int defaultDockPos = Qt::AlignRight | Qt::AlignCenter; + mainwindow->getUIState()->conState.recentlyDockPos = defaultDockPos; + + int conIndex = mruInfo.value(SKIN_PROPERTY_CONTROLLER_INDEX).toInt(); + if (conIndex >= 0 && conIndex < uiInfo->conFormList.count()) { + int conDockPos = mruInfo.value(SKIN_PROPERTY_CONTROLLER_DOCK).toInt(); + if (conDockPos <= 0) { + conDockPos = defaultDockPos; + } + + mainwindow->openController(conIndex, conDockPos); + } + + mainwindow->startSwapper(); +} + +void qt5_destroy() +{ + qDebug("qt5 destroy"); + + /* write MRU information */ + QSettings mruInfo(uiInfo->vmDataPath + SKIN_PROPERTIES_FILE_NAME, + QSettings::IniFormat); + mruInfo.setValue(SKIN_PROPERTY_WINDOW_X, mainwindow->pos().x()); + mruInfo.setValue(SKIN_PROPERTY_WINDOW_Y, mainwindow->pos().y()); + mruInfo.setValue(SKIN_PROPERTY_WINDOW_SCALE, uiInfo->uiState.mainFormScale); + mruInfo.setValue(SKIN_PROPERTY_WINDOW_TOPMOST, uiInfo->uiState.isOnTop()); + mruInfo.setValue(SKIN_PROPERTY_CONTROLLER_INDEX, uiInfo->uiState.conState.conFormIndex); + + DockingController *con = uiInfo->uiState.conState.dockingCon; + if (con != NULL) { + mruInfo.setValue(SKIN_PROPERTY_CONTROLLER_DOCK, con->getDockPos()); + } else { + mruInfo.setValue(SKIN_PROPERTY_CONTROLLER_DOCK, 0); + } + + /* clean up */ + mainwindow->terminateSwapper(); + + mainwindow->closeController(); + + /* TODO : destroy mainwindow and qt5App */ + + delete uiInfo; +} + +void qt5_early_prepare(void) +{ + Q_INIT_RESOURCE(resource); + qInstallMessageHandler(qMessageOutput); + +#ifdef CONFIG_DARWIN +#define LIBQCOCOA "libqcocoa.dylib" + /* load libqcocoa.dylib */ + QStringList libPaths = QCoreApplication::libraryPaths(); + qDebug() << "default Qt plugin library path : " << libPaths; + + int i = 0; + for ( ; i < libPaths.count(); i++) { + QFileInfo libFileInfo(libPaths.at(i) + QDir::separator() + + "platforms" + QDir::separator() + LIBQCOCOA); + if (libFileInfo.exists() == true) { + break; + } + } + + if (i >= libPaths.count()) { + qDebug() << LIBQCOCOA << " file not found. " << + "Qt plugin library path is converted to current path."; + QCoreApplication::setLibraryPaths(QStringList(QDir::currentPath())); + } +#endif + + qt5App = new QApplication(argc, argv); +} + +void qt5_prepare(void) +{ + qt5_gui_init(); +} + +void qt5_update_internal(void *data, int width, int height) +{ + QPixmap pixmap = QPixmap(); + QLabel *screenWidget = mainwindow->getScreenWidget(); + + /* + * TODO: support rotation. + */ + + QImage image = QImage((uchar *)data, width, height, QImage::Format_RGB32); + pixmap.convertFromImage(image); + screenWidget->setPixmap(pixmap.scaled(screenWidget->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation)); +} + +void qt5_switch_internal(void) +{ +} + +void qt5_refresh_internal(void) +{ + qt5App->processEvents(); +} + +void qt5_register_capture_request_listener(void *listener, void (*handler)(void *)) +{ + if (mainwindow) { + mainwindow->setCaptureRequestHandler(listener, handler); + } + + captureRequestListener = listener; + captureRequestHandler = handler; +} + +void qt5_unregister_capture_request_listener(void *listener) +{ + if (mainwindow) { + mainwindow->unsetCaptureRequestHandler(listener); + } + + captureRequestListener = NULL; + captureRequestHandler = NULL; +} + +void qt5_process_captured(bool captured, void *pixels, int width, int height) +{ + if (mainwindow) { + mainwindow->processCaptured(captured, pixels, width, height); + } +} + +void qMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + QByteArray localMsg = msg.toLocal8Bit(); + QByteArray dateMsg = QDateTime::currentDateTime().toString("hh:mm:ss").toLocal8Bit(); + + switch (type) { + case QtDebugMsg: + fprintf(stdout, "%s [Debug:%s:%u] %s\n", dateMsg.constData(), + context.category, context.line, localMsg.trimmed().constData()); + break; + case QtWarningMsg: + fprintf(stdout, "%s [Warning:%s:%u] %s\n", dateMsg.constData(), + context.category, context.line, localMsg.trimmed().constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "%s [Critical:%s:%u] %s\n", dateMsg.constData(), + context.category, context.line, localMsg.trimmed().constData()); + break; + case QtFatalMsg: + fprintf(stderr, "%s [Fatal:%s:%u] %s\n", dateMsg.constData(), + context.category, context.line, localMsg.trimmed().constData()); + + QString err; + QMessageBox::critical(0, "Emulator", + QString("An internal error occurred.\n: ") + + err.sprintf("%s", (localMsg.trimmed()).constData()) + + "\n\nEmulator will now exit."); + abort(); + } +} + +void loadMainFormFromXML(QFile *file, UIInformation *uiInfo/* out */) +{ + if (file->exists() == false) { + qFatal("%s is not found", qPrintable(file->fileName())); + } + + qDebug("main form is loaded from %s", qPrintable(file->fileName())); + + qmlRegisterType("EmulatorComponent", 1, 0, "EmulatorUI"); + qmlRegisterType("EmulatorComponent", 1, 0, "FormList"); + qmlRegisterType("EmulatorComponent", 1, 0, "Form"); + + /* QML */ + QQmlEngine *engine = new QQmlEngine(); + QQmlComponent *component = new QQmlComponent(engine); + + component->loadUrl(QUrl::fromLocalFile(file->fileName())); + if (!component->isReady()) { + qWarning("%s", qPrintable(component->errorString())); + } + + QObject *object = component->create(); + if (object != NULL) { + QFileInfo fileInfo(*file); + qDebug() << "xml version :" << QQmlProperty::read(object, "version").toString(); + + EmulatorUIType *uiType = (EmulatorUIType *)object; + FormType *formType = NULL; + KeyListType *keyListType = NULL; + HardwareKeyType *hwKeyType = NULL; + + FormListType *formListType = uiType->formListType(); + for (int index = 0; index < formListType->getFormList()->count(); index++) { + MainForm *mainForm = new MainForm(); /* dst */ + + formType = (FormType *)formListType->getFormList()->at(index); /* src */ + + mainForm->displayRegion = formType->getDisplayRegion(); + mainForm->skinImg[MainForm::normal].load(fileInfo.absolutePath() + + QDir::separator() + formType->mainImageName()); + mainForm->skinImg[MainForm::pressed].load(fileInfo.absolutePath() + + QDir::separator() + formType->pressedImageName()); + + keyListType = formType->keyListType(); + if (keyListType != NULL) { + for (int i = 0; i < keyListType->getKeyList()->count(); i++) { + hwKeyType = keyListType->getKeyList()->at(i); + if (hwKeyType != NULL) { + mainForm->keyList.append(new HardwareKey(hwKeyType->objectName(), + hwKeyType->keycode(), hwKeyType->region(), hwKeyType->tooltip())); + } + } + } + + uiInfo->mainFormList.append(mainForm); + } + + delete object; + } + + delete component; + delete engine; +} + +void loadConFormFromXML(QFile *file, UIInformation *uiInfo/* out */) +{ + if (file->exists() == false) { + qWarning("%s is not found", qPrintable(file->fileName())); + return; + } + + qDebug("controller form is loaded from %s", qPrintable(file->fileName())); + + /* QML */ + QQmlEngine *engine = new QQmlEngine(); + QQmlComponent *component = new QQmlComponent(engine); + + component->loadUrl(QUrl::fromLocalFile(file->fileName())); + if (!component->isReady()) { + qWarning("%s", qPrintable(component->errorString())); + } + + QObject *object = component->create(); + if (object != NULL) { + QFileInfo fileInfo(*file); + qDebug() << "xml version :" << QQmlProperty::read(object, "version").toString(); + + FormType *formType = (FormType *)object; + KeyListType *keyListType = NULL; + HardwareKeyType *hwKeyType = NULL; + + QString conName = QQmlProperty::read(object, "name").toString(); + ControllerForm *conForm = new ControllerForm( + conName.isEmpty() ? fileInfo.dir().dirName() : conName); + + conForm->conImg[ControllerForm::normal].load(fileInfo.absolutePath() + + QDir::separator() + formType->mainImageName()); + conForm->conImg[ControllerForm::pressed].load(fileInfo.absolutePath() + + QDir::separator() + formType->pressedImageName()); + + keyListType = formType->keyListType(); + if (keyListType != NULL) { + for (int i = 0; i < keyListType->getKeyList()->count(); i++) { + hwKeyType = keyListType->getKeyList()->at(i); + if (hwKeyType != NULL) { + conForm->keyList.append(new HardwareKey(hwKeyType->objectName(), + hwKeyType->keycode(), hwKeyType->region(), hwKeyType->tooltip())); + } + } + } + + uiInfo->conFormList.append(conForm); + + delete object; + } + + delete component; + delete engine; +} + +#if 0 +#define CONTROL_PRIORITY_MAX 10 + +int getControlIndex() +{ + int controlIndex = 0; + int controlPriority = 0; + int priority = CONTROL_PRIORITY_MAX; + + if (!uiInfo) { + return controlIndex; + } + + /* find high priority*/ + QString line; + QDir skinDir(uiInfo->skinPath + CON_FORM_SUBPATH); + QFileInfoList entries = skinDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int i = 0; i < entries.size(); i++) { + QFile iniFile(entries.at(i).filePath() + QDir::separator() + "info.ini"); + if (iniFile.exists()) { + controlPriority = getPriority(&iniFile); + if (controlPriority < priority) { + controlIndex = i; + priority = controlPriority; + } + } + } + + return controlIndex; +} + +int getPriority(QFile *file) +{ + int priority = CONTROL_PRIORITY_MAX; + QRegExp rx("="); + + /* read priority in info.ini file */ + if (file->open(QFile::ReadOnly)) { + QTextStream in(file); + do { + QString line = in.readLine(); + QStringList list = line.split(rx, QString::SkipEmptyParts); + if (QString::compare(list.at(0), "priority", Qt::CaseInsensitive) == 0) { + priority = list.at(1).toInt(); + } + } while(!in.atEnd()); + file->close(); + } + + return priority; +} +#endif diff --git a/tizen/src/display/qt5_supplement.h b/tizen/src/display/qt5_supplement.h new file mode 100644 index 0000000000..74b96a8c41 --- /dev/null +++ b/tizen/src/display/qt5_supplement.h @@ -0,0 +1,50 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * SeokYeon Hwang + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef __QT5_INTERNAL_H__ +#define __QT5_INTERNAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif +void qt5_graphic_hw_invalidate(void); +int qt5_graphic_hw_display(void); +void qt5_early_prepare(void); +void qt5_prepare(void); +void qt5_destroy(void); + +void qt5_update_internal(void *data, int width, int height); +void qt5_switch_internal(void); +void qt5_refresh_internal(void); +#ifdef __cplusplus +} +#endif + +#endif // __QT5_INTERNAL_H__ diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index 1d9e4c6351..21dbe7c402 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -36,8 +36,12 @@ #if defined(CONFIG_LINUX) #include -#elif defined (CONFIG_WIN32) +extern bool kvm_allowed; +#elif defined(CONFIG_WIN32) #include +extern bool hax_allowed; +#elif defined(CONFIG_DARWIN) +extern bool hax_allowed; #endif DECLARE_DEBUG_CHANNEL(emul_state); @@ -321,6 +325,16 @@ MultiTouchState *get_emul_multi_touch_state(void) return &(_emul_state.qemu_mts); } +void set_multi_touch_enable(int enable) +{ + _emul_state.qemu_mts.multitouch_enable = enable; +} + +int get_multi_touch_enable(void) +{ + return _emul_state.qemu_mts.multitouch_enable; +} + /* retrieves the status of the host lock key */ int get_host_lock_key_state(int key) { @@ -457,3 +471,71 @@ bool get_sdb_connection(void) return _emul_state.sdb_connection; } +/* emualtor skin path */ +void set_emul_skin_path(char *path) +{ + _emul_info.skin_path = path; + + LOG_INFO("skin path : %s\n", _emul_info.skin_path); +} + +char* get_emul_skin_path(void) +{ + return _emul_info.skin_path; +} + +/* GPU virtualization */ +void set_emul_gpu_accel(bool enable) +{ + _emul_info.gpu_accel_enable = enable; +} + +bool get_emul_gpu_accel(void) +{ + return _emul_info.gpu_accel_enable; +} + +/* CPU virtualization */ +bool get_emul_cpu_accel(void) +{ +#ifdef CONFIG_LINUX + return kvm_allowed; +#else + return hax_allowed; +#endif + + return false; +} + +/* VM ram size */ +void set_emul_ram_size(const char *size) +{ + _emul_info.vm_ram_size = size; +} + +const char* get_emul_ram_size(void) +{ + return _emul_info.vm_ram_size; +} + +/* file sharing path */ +void set_emul_file_sharing_path(const char *path) +{ + _emul_info.file_sharing_path = path; +} + +const char* get_emul_file_sharing_path(void) +{ + return _emul_info.file_sharing_path; +} + +/* VM data path */ +void set_emul_vm_data_path(const char *path) +{ + _emul_info.vm_data_path = path; +} + +const char* get_emul_vm_data_path(void) +{ + return _emul_info.vm_data_path; +} diff --git a/tizen/src/emul_state.h b/tizen/src/emul_state.h index 904f269a47..88ef3c7722 100644 --- a/tizen/src/emul_state.h +++ b/tizen/src/emul_state.h @@ -103,8 +103,13 @@ typedef struct EmulatorConfigInfo { int spice_port; int websocket_port; char *vm_name; - /* add here */ + char *skin_path; + bool gpu_accel_enable; + const char *file_sharing_path; + const char *vm_ram_size; int serial_port; + const char *vm_data_path; + /* add here */ } EmulatorConfigInfo; typedef struct EmulatorConfigState { @@ -146,6 +151,11 @@ void set_emul_vm_base_port(int port); void set_emul_ecs_port(int port); void set_emul_guest_ip(char *ip); void set_emul_vm_name(char *vm_name); +void set_emul_skin_path(char *path); +void set_emul_gpu_accel(bool enable); +void set_emul_file_sharing_path(const char *path); +void set_emul_ram_size(const char *size); +void set_emul_vm_data_path(const char *path); void set_emulator_condition(int state); void set_emul_rotation(short rotation_type); @@ -175,10 +185,15 @@ int get_emul_serial_port(void); char* get_emul_vm_name(void); int get_emul_spice_port(void); int get_emul_websocket_port(void); +char* get_emul_skin_path(void); +bool get_emul_gpu_accel(void); +bool get_emul_cpu_accel(void); +const char* get_emul_file_sharing_path(void); +const char* get_emul_ram_size(void); +const char* get_emul_vm_data_path(void); int get_emulator_condition(void); short get_emul_rotation(void); -MultiTouchState *get_emul_multi_touch_state(void); int get_host_lock_key_state(int key); int get_host_lock_key_state_darwin(int key); int get_emul_caps_lock_state(void); @@ -193,4 +208,9 @@ char* get_emul_profile(void); bool get_emuld_connection(void); bool get_sdb_connection(void); +/* multi-touch */ +MultiTouchState *get_emul_multi_touch_state(void); +void set_multi_touch_enable(int enable); +int get_multi_touch_enable(void); + #endif /* __EMUL_STATE_H__ */ diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 14642f636f..5b6ff90a86 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -279,7 +279,7 @@ static int emulator_main(int argc, char *argv[], char **envp) } #endif -#ifdef CONFIG_WIN32 +#if defined(CONFIG_WIN32) && defined(CONFIG_SDL) // SDL_init() routes stdout and stderr to the respective files in win32. // So we revert it. freopen("CON", "w", stdout); @@ -395,7 +395,7 @@ static int emulator_main(int argc, char *argv[], char **envp) return 0; } -#ifdef CONFIG_DARWIN +#if defined(CONFIG_DARWIN) && !defined(CONFIG_QT) int g_argc; static void* main_thread(void* args) @@ -430,7 +430,9 @@ int main(int argc, char *argv[], char **envp) #else // WIN32 int main(int argc, char *argv[]) { +#ifndef CONFIG_DARWIN maru_register_exception_handler(); +#endif return emulator_main(argc, argv, NULL); } #endif diff --git a/tizen/src/emulator_legacy.c b/tizen/src/emulator_legacy.c index 5786038b7a..0bbb00c882 100644 --- a/tizen/src/emulator_legacy.c +++ b/tizen/src/emulator_legacy.c @@ -64,6 +64,7 @@ MULTI_DEBUG_CHANNEL(qemu, main); #define LOGFILE "emulator.log" #define DISPLAY_WIDTH_PREFIX "width=" #define DISPLAY_HEIGHT_PREFIX "height=" +#define SKIN_PATH_PREFIX "skin.path=" #define INPUT_TOUCH_PARAMETER "virtio-touchscreen-pci" #define MIDBUF 128 @@ -142,7 +143,9 @@ static void set_image_and_log_path(char *qemu_argv) strcpy(tizen_target_path, g_path_get_dirname(path)); } + set_emul_vm_data_path(tizen_target_path); set_emul_vm_name(g_path_get_basename(tizen_target_path)); + strcpy(tizen_target_img_path, path); free(path); @@ -232,11 +235,14 @@ static void extract_skin_info(int skin_argc, char **skin_argv) h = atoi(height_arg); INFO("display height option : %d\n", h); + } else if (strstr(skin_argv[i], SKIN_PATH_PREFIX) != NULL) { + char *path = skin_argv[i] + strlen(SKIN_PATH_PREFIX); + + set_emul_skin_path(path); } if (w != 0 && h != 0) { set_emul_resolution(w, h); - break; } } } diff --git a/tizen/src/ns_event.h b/tizen/src/ns_event.h index 54655c9006..e277ee4ed0 100644 --- a/tizen/src/ns_event.h +++ b/tizen/src/ns_event.h @@ -3,4 +3,8 @@ void ns_event_loop(int* keepRunning); +void ns_run_in_event_loop(void (*func)()); + +void set_application_icon(char *path); + #endif /* _NS_EVENT_H_ */ diff --git a/tizen/src/ns_event.m b/tizen/src/ns_event.m index 69928df519..62a097c8eb 100644 --- a/tizen/src/ns_event.m +++ b/tizen/src/ns_event.m @@ -13,3 +13,35 @@ void ns_event_loop(int* keepRunning) while (*keepRunning && [theRunLoop runMode:NSDefaultRunLoopMode beforeDate:distantFuture]); // return [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1]]; } + +@interface Runner : NSObject +{ + @public void (*func)(); +} +- (void)run; +@end + +@implementation Runner +- (void)run; +{ + self->func(); +} +@end + +void ns_run_in_event_loop(void (*func)()) +{ + Runner *runner = [[Runner alloc] init]; + runner->func = func; + [runner performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES]; + [runner release]; +} + +void set_application_icon(char *path) +{ + NSString *iconPath = [[NSString alloc] initWithUTF8String:path]; + NSImage *iconImage = [[NSImage alloc] initWithContentsOfFile:iconPath]; + [[NSApplication sharedApplication] setApplicationIconImage:iconImage]; + + [iconImage release]; + [iconPath release]; +} diff --git a/tizen/src/skin/maruskin_keymap.h b/tizen/src/skin/maruskin_keymap.h index 96f9719107..77beb6393b 100644 --- a/tizen/src/skin/maruskin_keymap.h +++ b/tizen/src/skin/maruskin_keymap.h @@ -85,7 +85,6 @@ enum JAVA_KEYCODE { JAVA_KEY_DELETE = 127 }; - #define KEY_MAX 0777 #define KEY_F0 0410 @@ -102,8 +101,9 @@ enum JAVA_KEYCODE { #define KEY_BTAB 0541 - #define SHIFT 0 + +/* for Java skin*/ static const int vkkey2scancode[KEY_MAX] = { [0 ... (KEY_MAX - 1)] = -1, diff --git a/tizen/src/skin/maruskin_operation.c b/tizen/src/skin/maruskin_operation.c index 0d5378c94e..6d255c820e 100644 --- a/tizen/src/skin/maruskin_operation.c +++ b/tizen/src/skin/maruskin_operation.c @@ -185,6 +185,21 @@ void do_mouse_event(int button_type, int event_type, } } +void do_qt_keyboard_key_event(int event_type, int keycode) { + if (is_host_keyboard_attached() == false) { + TRACE("ignore key event because keyboard device was dettached\n"); + return; + } + + if (KEY_PRESSED == event_type) { + TRACE("key pressed: %d\n", keycode); + virtio_keyboard_event(keycode); + } else if (KEY_RELEASED == event_type) { + TRACE("key released: %d\n", keycode); + virtio_keyboard_event(keycode | 0x80); + } +} + void do_keyboard_key_event(int event_type, int keycode, int state_mask, int key_location) { diff --git a/tizen/src/skin/maruskin_operation.h b/tizen/src/skin/maruskin_operation.h index b434f6c324..d4470f9c26 100644 --- a/tizen/src/skin/maruskin_operation.h +++ b/tizen/src/skin/maruskin_operation.h @@ -51,6 +51,7 @@ void start_display(uint64_t handle_id, void do_grabbing_enable(bool on); void do_mouse_event(int button_type, int event_type, int origin_x, int origin_y, int x, int y, int z); +void do_qt_keyboard_key_event(int event_type, int keycode); void do_keyboard_key_event(int event_type, int keycode, int state_mask, int key_location); void do_hw_key_event(int event_type, int keycode); diff --git a/tizen/src/skin/maruskin_server.c b/tizen/src/skin/maruskin_server.c index fcc7b8df1a..359028eeb5 100644 --- a/tizen/src/skin/maruskin_server.c +++ b/tizen/src/skin/maruskin_server.c @@ -132,7 +132,6 @@ static uint16_t svr_port = 0; static int server_sock = 0; static int client_sock = 0; static int stop_server = 0; -static int is_sdbd_initialized = 0; static int ready_server = 0; static int ignore_heartbeat = 0; static int is_force_close_client = 0; @@ -141,6 +140,8 @@ static int is_started_heartbeat = 0; static int stop_heartbeat = 0; static int recv_heartbeat_count = 0; +int is_sdbd_initialized = 0; + /* 0: not drawing, 1: drawing */ int draw_display_state = 0; diff --git a/tizen/src/skin/maruskin_server.h b/tizen/src/skin/maruskin_server.h index 0db67fc05d..5d0a4c1bf1 100644 --- a/tizen/src/skin/maruskin_server.h +++ b/tizen/src/skin/maruskin_server.h @@ -30,6 +30,8 @@ #ifndef MARUSKIN_SERVER_H_ #define MARUSKIN_SERVER_H_ +extern int is_sdbd_initialized; + int start_skin_server(int argc, char** argv, int qemu_argc, char** qemu_argv); void notify_draw_frame(void); diff --git a/tizen/src/ui/Makefile.objs b/tizen/src/ui/Makefile.objs new file mode 100644 index 0000000000..417087ecd8 --- /dev/null +++ b/tizen/src/ui/Makefile.objs @@ -0,0 +1,49 @@ +TIZEN_UI = $(SRC_PATH)/tizen/src/ui +QEMU_CFLAGS += $(QT_CFLAGS) -I$(TIZEN_UI) + +$(obj)/qrc_resource.o: $(obj)/qrc_resource.cpp +$(obj)/qrc_resource.cpp: $(TIZEN_UI)/resource/resource.qrc + rcc -name resource $< -o $@ + +obj-$(CONFIG_QT) += controllerform.o +obj-$(CONFIG_QT) += dockingcontroller.o moc_dockingcontroller.o +obj-$(CONFIG_QT) += dockingconview.o +obj-$(CONFIG_QT) += floatingcontroller.o moc_floatingcontroller.o +obj-$(CONFIG_QT) += floatingconview.o +obj-$(CONFIG_QT) += displaybase.o +obj-$(CONFIG_QT) += displayglwidget.o moc_displayglwidget.o +obj-$(CONFIG_QT) += displayswwidget.o moc_displayswwidget.o +obj-$(CONFIG_QT) += hardwarekey.o +obj-$(CONFIG_QT) += mainwindow.o moc_mainwindow.o +obj-$(CONFIG_QT) += skinbezelitem.o +obj-$(CONFIG_QT) += skinkeyitem.o moc_skinkeyitem.o +obj-$(CONFIG_QT) += mainform.o +obj-$(CONFIG_QT) += keyboardhelper.o +obj-$(CONFIG_QT) += skinview.o +obj-$(CONFIG_QT) += uiinformation.o +obj-$(CONFIG_QT) += uistate.o +obj-$(CONFIG_QT) += uiutil.o +obj-$(CONFIG_QT) += qrc_resource.o + +obj-$(CONFIG_QT) += xml/ + +obj-$(CONFIG_QT) += menu/ + +$(obj)/moc_dockingcontroller.o: $(obj)/moc_dockingcontroller.cpp +$(obj)/moc_dockingcontroller.cpp: $(obj)/dockingcontroller.h + moc $< -o $@ +$(obj)/moc_floatingcontroller.o: $(obj)/moc_floatingcontroller.cpp +$(obj)/moc_floatingcontroller.cpp: $(obj)/floatingcontroller.h + moc $< -o $@ +$(obj)/moc_displayglwidget.o: $(obj)/moc_displayglwidget.cpp +$(obj)/moc_displayglwidget.cpp: $(obj)/displayglwidget.h + moc $< -o $@ +$(obj)/moc_displayswwidget.o: $(obj)/moc_displayswwidget.cpp +$(obj)/moc_displayswwidget.cpp: $(obj)/displayswwidget.h + moc $< -o $@ +$(obj)/moc_mainwindow.o: $(obj)/moc_mainwindow.cpp +$(obj)/moc_mainwindow.cpp: $(obj)/mainwindow.h + moc $< -o $@ +$(obj)/moc_skinkeyitem.o: $(obj)/moc_skinkeyitem.cpp +$(obj)/moc_skinkeyitem.cpp: $(obj)/skinkeyitem.h + moc $< -o $@ diff --git a/tizen/src/ui/controllerform.cpp b/tizen/src/ui/controllerform.cpp new file mode 100644 index 0000000000..808d119d4c --- /dev/null +++ b/tizen/src/ui/controllerform.cpp @@ -0,0 +1,40 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "controllerform.h" + +ControllerForm::ControllerForm(QString name) +{ + this->name = name; +} + +ControllerForm::~ControllerForm() +{ + qDebug("destroy con layout"); +} diff --git a/tizen/src/ui/controllerform.h b/tizen/src/ui/controllerform.h new file mode 100644 index 0000000000..02c9b7393f --- /dev/null +++ b/tizen/src/ui/controllerform.h @@ -0,0 +1,55 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef CONTROLLERFORM_H +#define CONTROLLERFORM_H + +#include + +#include "hardwarekey.h" + +class ControllerForm +{ + Q_ENUMS(ConImgType) + +public: + ControllerForm(QString name); + ~ControllerForm(); + + QString name; + QImage conImg[2]; + QList keyList; + + enum ConImgType { + normal = 0, + pressed = 1 + }; +}; + +#endif // CONTROLLERFORM_H diff --git a/tizen/src/ui/displaybase.cpp b/tizen/src/ui/displaybase.cpp new file mode 100644 index 0000000000..344a165432 --- /dev/null +++ b/tizen/src/ui/displaybase.cpp @@ -0,0 +1,190 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "displaybase.h" +#include "mainwindow.h" + +uint32_t qt5_window_width = 0; +uint32_t qt5_window_height = 0; +int qt5_window_angle = 0; + +DisplayBase::DisplayBase(QSize resolution, QWidget *w) +: resolution(resolution), + widget(w), + isDragging(false) +{ + /* initialize */ + // TODO: compare display region with resolution + + MainWindow *win = ((MainWindow *)w->parent()->parent()); + rotateAngle = win->getUIState()->mainFormAngle; + scaleFactor = win->getUIState()->getScaleFactor(); +} + +DisplayBase::~DisplayBase() +{ + qDebug("destory display"); +} + +void DisplayBase::rotate(int angle) +{ + qDebug("display rotate : %d", angle); + + rotateAngle = angle; + + qt5_window_angle = angle; + + /* adjustSize() doesn't work */ + widget->resize(0, 0); + + widget->repaint(); +} + +void DisplayBase::scale(int scale) +{ + qDebug("display scale : %d", scale); + + scaleFactor = ((qreal)scale) / 100; + + /* adjustSize() doesn't work */ + widget->resize(0, 0); + + widget->repaint(); +} + +void DisplayBase::update() +{ + qt5_graphic_hw_invalidate(); +} + +void DisplayBase::handlePaint(QPaintEvent *event) +{ +} + +void DisplayBase::handleResize(QResizeEvent *event) +{ + qDebug("resize display"); + + MainWindow *win = ((MainWindow *)widget->parent()->parent()); + MainForm *form = win->uiInfo->getMainForm(); + + const qreal sx = scaleFactor; + const qreal sy = scaleFactor; + + widget->setGeometry(form->displayRegion.x() * sx, + form->displayRegion.y() * sy, + form->displayRegion.width() * sx, + form->displayRegion.height() * sy); + + qt5_window_width = widget->width(); + qt5_window_height = widget->height(); + + qt5_graphic_hw_invalidate(); +} + +void DisplayBase::handleMousePress(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + isDragging = true; + + sendTouchEvent(TOUCH_PRESS, event->x(), event->y()); + } +} + +void DisplayBase::handleMouseRelease(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (isDragging) { + isDragging = false; + } + + sendTouchEvent(TOUCH_RELEASE, event->x(), event->y()); + } +} + +void DisplayBase::handleMouseMove(QMouseEvent *event) +{ + if (isDragging == true) { + int event_type = TOUCH_PRESS; + int clientX = event->x(); + int clientY = event->y(); + + if (clientX < 0) { + event_type = TOUCH_RELEASE; + clientX = 0; + isDragging = false; + } else if (clientX >= widget->width()) { + event_type = TOUCH_RELEASE; + clientX = widget->width() - 1; + isDragging = false; + } + + if (clientY < 0) { + event_type = TOUCH_RELEASE; + clientY = 0; + isDragging = false; + } else if (clientY >= widget->height()) { + event_type = TOUCH_RELEASE; + clientY = widget->height() - 1; + isDragging = false; + } + + sendTouchEvent(event_type, clientX, clientY); + } +} + +void DisplayBase::sendTouchEvent(int eventType, int clientX, int clientY) +{ + int xx = clientX / scaleFactor; + int yy = clientY / scaleFactor; + int absX = xx; + int absY = yy; + + /* TODO: x*cos(rad)-y*sin(rad) */ + switch(rotateAngle) { + case 90: /* Reverse Landscape */ + absX = yy; + absY = resolution.height() - xx; + break; + case 180: /* Reverse Portrait */ + absX = resolution.width() - xx; + absY = resolution.height() - yy; + break; + case 270: /* Landscape */ + absX = resolution.width() - yy; + absY = xx; + break; + case 0: + default: + break; + } + + do_mouse_event(0, eventType, clientX, clientY, absX, absY, 0); +} diff --git a/tizen/src/ui/displaybase.h b/tizen/src/ui/displaybase.h new file mode 100644 index 0000000000..2ca4ec872f --- /dev/null +++ b/tizen/src/ui/displaybase.h @@ -0,0 +1,77 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef DISPLAYBASE_H +#define DISPLAYBASE_H + +#include + +extern "C" { +void qt5_graphic_hw_invalidate(void); +} + +enum { + TOUCH_PRESS = 1, + TOUCH_RELEASE = 2, +}; + +class DisplayBase +{ +public: + void rotate(int angle); + void scale(int scale); + void update(); + +protected: + DisplayBase(QSize resolution, QWidget *w); + virtual ~DisplayBase(); + + void setRotate(int angle); + void setScale(int scale); + + void handlePaint(QPaintEvent *event); + void handleResize(QResizeEvent *event); + + void handleMousePress(QMouseEvent *event); + void handleMouseRelease(QMouseEvent *event); + void handleMouseMove(QMouseEvent *event); + +private: + void sendTouchEvent(int eventType, int clientX, int clientY); + + QSize resolution; + QWidget *widget; + int rotateAngle; + qreal scaleFactor; + + bool isDragging; +}; + +#endif diff --git a/tizen/src/ui/displayglwidget.cpp b/tizen/src/ui/displayglwidget.cpp new file mode 100644 index 0000000000..1198fe0b6f --- /dev/null +++ b/tizen/src/ui/displayglwidget.cpp @@ -0,0 +1,86 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include + +#include "displayglwidget.h" + +DisplayGLWidget::DisplayGLWidget(QSize resolution, QGLContext *context, QWidget *parent) : + QGLWidget(context, parent), + DisplayBase(resolution, this) +{ + setAutoBufferSwap(false); +} + +void DisplayGLWidget::initializeGL() +{ + qDebug("initialize GL"); +} + +void DisplayGLWidget::paintEvent(QPaintEvent *event) +{ + /* + * We offload rendering to separate thread, this must be + * a no-op, see: http://qt-project.org/doc/qt-5/QGLWidget.html: + * "3. Using QPainter to draw into a QGLWidget in a thread" + */ + + handlePaint(event); +} + +void DisplayGLWidget::resizeEvent(QResizeEvent *event) +{ + /* + * We offload rendering to separate thread, this must be + * a no-op, see: http://qt-project.org/doc/qt-5/QGLWidget.html: + * "3. Using QPainter to draw into a QGLWidget in a thread" + */ + + handleResize(event); +} + +void DisplayGLWidget::mousePressEvent(QMouseEvent *event) +{ + handleMousePress(event); +} + +void DisplayGLWidget::mouseReleaseEvent(QMouseEvent *event) +{ + handleMouseRelease(event); +} + +void DisplayGLWidget::mouseMoveEvent(QMouseEvent *event) +{ + handleMouseMove(event); +} + +DisplayGLWidget::~DisplayGLWidget() +{ +} diff --git a/tizen/src/ui/displayglwidget.h b/tizen/src/ui/displayglwidget.h new file mode 100644 index 0000000000..9a1b8d88b0 --- /dev/null +++ b/tizen/src/ui/displayglwidget.h @@ -0,0 +1,57 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef DISPLAYGLWIDGET_H +#define DISPLAYGLWIDGET_H + +#include "displaybase.h" +#include + +class DisplayGLWidget : public QGLWidget, + public DisplayBase +{ + Q_OBJECT + +public: + DisplayGLWidget(QSize resolution, QGLContext *context, QWidget *parent = 0); + ~DisplayGLWidget(); + +protected: + void initializeGL(); + + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); +}; + +#endif // DISPLAYGLWIDGET_H diff --git a/tizen/src/ui/displayswwidget.cpp b/tizen/src/ui/displayswwidget.cpp new file mode 100644 index 0000000000..3cb3b2331a --- /dev/null +++ b/tizen/src/ui/displayswwidget.cpp @@ -0,0 +1,70 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include + +#include "displayswwidget.h" + +DisplaySWWidget::DisplaySWWidget(QSize resolution, QWidget *parent) : + QLabel(parent), + DisplayBase(resolution, this) +{ +} + +void DisplaySWWidget::paintEvent(QPaintEvent *event) +{ + QLabel::paintEvent(event); + handlePaint(event); +} + +void DisplaySWWidget::resizeEvent(QResizeEvent *event) +{ + QLabel::resizeEvent(event); + handleResize(event); +} + +void DisplaySWWidget::mousePressEvent(QMouseEvent *event) +{ + handleMousePress(event); +} + +void DisplaySWWidget::mouseReleaseEvent(QMouseEvent *event) +{ + handleMouseRelease(event); +} + +void DisplaySWWidget::mouseMoveEvent(QMouseEvent *event) +{ + handleMouseMove(event); +} + +DisplaySWWidget::~DisplaySWWidget() +{ +} diff --git a/tizen/src/ui/displayswwidget.h b/tizen/src/ui/displayswwidget.h new file mode 100644 index 0000000000..69454eb1e3 --- /dev/null +++ b/tizen/src/ui/displayswwidget.h @@ -0,0 +1,55 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef DISPLAYSWWIDGET_H +#define DISPLAYSWWIDGET_H + +#include "displaybase.h" +#include + +class DisplaySWWidget : public QLabel, + public DisplayBase +{ + Q_OBJECT + +public: + DisplaySWWidget(QSize resolution, QWidget *parent = 0); + ~DisplaySWWidget(); + +protected: + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); +}; + +#endif // DISPLAYSWWIDGET_H diff --git a/tizen/src/ui/dockingcontroller.cpp b/tizen/src/ui/dockingcontroller.cpp new file mode 100644 index 0000000000..283e6babde --- /dev/null +++ b/tizen/src/ui/dockingcontroller.cpp @@ -0,0 +1,92 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "dockingcontroller.h" +#include "mainwindow.h" + +DockingController::DockingController(ControllerForm *conForm, + QAction *menu, int dockPos, QWidget *parent) : QWidget(parent) +{ + this->conForm = conForm; + this->menu = menu; + this->dockPos = dockPos; + + setStyleSheet("border-style: none"); + setAttribute(Qt::WA_DeleteOnClose); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + + if (dockPos & Qt::AlignCenter) { + layout->setAlignment(Qt::AlignCenter); + } else if (dockPos & Qt::AlignTop) { + layout->setAlignment(Qt::AlignTop); + } else if (dockPos & Qt::AlignBottom) { + layout->setAlignment(Qt::AlignBottom); + } + + QGraphicsScene *conScene = new QGraphicsScene(this); + conScene->setBackgroundBrush(Qt::black); + + conView = new DockingConView(conForm, conScene, this); + conView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + layout->addWidget(conView); +} + +DockingConView *DockingController::getConView() +{ + return conView; +} + +int DockingController::getDockPos() +{ + return dockPos; +} + +void DockingController::showEvent(QShowEvent *event) +{ + if (menu != NULL) { + menu->setChecked(true); + } +} + +void DockingController::closeEvent(QCloseEvent *event) { + if (menu != NULL) { + menu->setChecked(false); + } + + MainWindow *win = ((MainWindow *)this->parent()); + win->getUIState()->conState.dockingCon = NULL; +} + +DockingController::~DockingController() +{ + qDebug("destroy docking contoller"); +} diff --git a/tizen/src/ui/dockingcontroller.h b/tizen/src/ui/dockingcontroller.h new file mode 100644 index 0000000000..a388030f56 --- /dev/null +++ b/tizen/src/ui/dockingcontroller.h @@ -0,0 +1,61 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef DOCKINGCONTROLLER_H +#define DOCKINGCONTROLLER_H + +#include + +#include "controllerform.h" +#include "dockingconview.h" + +class DockingController : public QWidget +{ + Q_OBJECT + +public: + explicit DockingController(ControllerForm *conForm, + QAction *menu, int dockPos, QWidget *parent = 0); + ~DockingController(); + + DockingConView *getConView(); + int getDockPos(); + +protected: + void showEvent(QShowEvent *event); + void closeEvent(QCloseEvent *event); + +private: + DockingConView *conView; + ControllerForm *conForm; + QAction *menu; + int dockPos; +}; + +#endif // DOCKINGCONTROLLER_H diff --git a/tizen/src/ui/dockingconview.cpp b/tizen/src/ui/dockingconview.cpp new file mode 100644 index 0000000000..dee2b3f1b5 --- /dev/null +++ b/tizen/src/ui/dockingconview.cpp @@ -0,0 +1,152 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "dockingconview.h" +#include "mainwindow.h" +#include "skinkeyitem.h" + +DockingConView::DockingConView(ControllerForm *conForm, QGraphicsScene *scene, QWidget *parent) + : QGraphicsView(scene, parent) +{ + this->parent = (DockingController *)parent; + + setStyleSheet("background: transparent"); + setStyleSheet("border-style: none"); + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setAlignment(Qt::AlignLeft | Qt::AlignTop); + + rubberPos = QPoint(-1, -1); + grabPos = QPoint(-1, -1); + rubberBand = new QRubberBand(QRubberBand::Rectangle, NULL); + + createItems(conForm); +} + +void DockingConView::createItems(ControllerForm *conForm) +{ + /* bezel */ + bezelItem = new SkinBezelItem(conForm->conImg[ControllerForm::normal]); + scene()->addItem(bezelItem); + + /* HW keys */ + QList keyList = conForm->keyList; + + HardwareKey *hwKey = NULL; + for (int i = 0; i < keyList.count(); i++) { + hwKey = keyList.at(i); + if (hwKey != NULL) { + new SkinKeyItem(conForm->conImg[ControllerForm::pressed].copy(hwKey->region), + hwKey, bezelItem); + } + } +} + +void DockingConView::resizeEvent(QResizeEvent *event) +{ + //qDebug("resize con view"); + + Q_UNUSED(event) +} + +void DockingConView::mousePressEvent(QMouseEvent *event) +{ + QGraphicsView::mousePressEvent(event); + + if (bezelItem->isKeyHandling() == true) { + /* do nothing */ + return; + } + + if (event->button() == Qt::LeftButton) { + QWidget *win = ((QWidget *)parent->parent()); + + grabPos = event->globalPos(); + eventPos = event->pos(); + rubberPos.setX(win->pos().x() + parent->pos().x()); + rubberPos.setY(win->pos().y() + pos().y()); + + if (rubberBand != NULL) { + rubberBand->setGeometry(QRect(rubberPos, size())); + rubberBand->show(); + } + } +} + +void DockingConView::mouseReleaseEvent(QMouseEvent *event) +{ + QGraphicsView::mouseReleaseEvent(event); + + if (bezelItem->isKeyHandling() == true) { + /* do nothing */ + return; + } + + if (event->button() == Qt::LeftButton) { + if (grabPos != QPoint(-1, -1)) { + if (rubberBand != NULL) { + rubberBand->hide(); + } + + /* toggle */ + MainWindow *win = ((MainWindow *)parent->parent()); + win->getUIState()->conState.recentlyFloatPos = event->globalPos() - eventPos; + + win->openController(win->getUIState()->conState.conFormIndex, -1); + return; + } + } +} + +void DockingConView::mouseMoveEvent(QMouseEvent *event) +{ + QGraphicsView::mouseMoveEvent(event); + + if (bezelItem->isKeyHandling() == true) { + /* do nothing */ + return; + } + + if (grabPos != QPoint(-1, -1) && rubberBand != NULL) { + rubberBand->setGeometry( + QRect(rubberPos + (event->globalPos() - grabPos), size())); + } +} + +DockingConView::~DockingConView() +{ + qDebug("destroy docking controller view"); + + if (rubberBand != NULL) { + rubberBand->close(); + delete rubberBand; + rubberBand = NULL; + } +} diff --git a/tizen/src/ui/dockingconview.h b/tizen/src/ui/dockingconview.h new file mode 100644 index 0000000000..691400da41 --- /dev/null +++ b/tizen/src/ui/dockingconview.h @@ -0,0 +1,65 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef DOCKINGCONVIEW_H +#define DOCKINGCONVIEW_H + +#include + +#include "skinview.h" +#include "skinbezelitem.h" +#include "controllerform.h" + +class DockingController; + +class DockingConView : public QGraphicsView +{ +public: + DockingConView(ControllerForm *conForm, QGraphicsScene *scene, QWidget *parent = 0); + ~DockingConView(); + +protected: + void resizeEvent(QResizeEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + + QPoint grabPos; + QPoint eventPos; + QPoint rubberPos; + +private: + void createItems(ControllerForm *conForm); + + DockingController *parent; + SkinBezelItem *bezelItem; + QRubberBand *rubberBand; +}; + +#endif // DOCKINGCONVIEW_H diff --git a/tizen/src/ui/floatingcontroller.cpp b/tizen/src/ui/floatingcontroller.cpp new file mode 100644 index 0000000000..0616eff4e7 --- /dev/null +++ b/tizen/src/ui/floatingcontroller.cpp @@ -0,0 +1,95 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "floatingcontroller.h" +#include "mainwindow.h" + +FloatingController::FloatingController(ControllerForm *conForm, + QAction *menu, QWidget *parent) : QDialog(parent) +{ + this->conForm = conForm; + this->menu = menu; + + setStyleSheet("border-style: none"); + setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); + setAttribute(Qt::WA_DeleteOnClose); + + setWindowTitle(conForm->name); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + + QGraphicsScene *conScene = new QGraphicsScene(this); + conScene->setBackgroundBrush(Qt::black); + + conView = new FloatingConView(conForm, conScene, this); + conView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + layout->addWidget(conView); +} + +FloatingConView *FloatingController::getConView() +{ + return conView; +} + +void FloatingController::showEvent(QShowEvent *event) +{ + if (menu != NULL) { + menu->setChecked(true); + } + + setRegion(&(conForm->conImg[ControllerForm::normal])); +} + +void FloatingController::closeEvent(QCloseEvent *event) { + if (menu != NULL) { + menu->setChecked(false); + } + + MainWindow *win = ((MainWindow *)this->parent()); + win->getUIState()->conState.floatingCon = NULL; +} + +void FloatingController::setRegion(QImage *baseImage) +{ + qDebug("set region"); + + if (baseImage->isNull() == true) { + qWarning("invalid image for region"); + return; + } + + setMask(QRegion(QBitmap::fromImage(baseImage->createAlphaMask()))); +} + +FloatingController::~FloatingController() +{ + qDebug("destroy floating contoller"); +} diff --git a/tizen/src/ui/floatingcontroller.h b/tizen/src/ui/floatingcontroller.h new file mode 100644 index 0000000000..d9e7bf50c0 --- /dev/null +++ b/tizen/src/ui/floatingcontroller.h @@ -0,0 +1,60 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef FLOATINGCONTROLLER_H +#define FLOATINGCONTROLLER_H + +#include + +#include "controllerform.h" +#include "floatingconview.h" + +class FloatingController : public QDialog +{ + Q_OBJECT + +public: + explicit FloatingController(ControllerForm *conForm, QAction *menu, QWidget *parent = 0); + ~FloatingController(); + + FloatingConView *getConView(); + +protected: + void showEvent(QShowEvent *event); + void closeEvent(QCloseEvent *event); + + void setRegion(QImage *baseImage); + +private: + FloatingConView *conView; + ControllerForm *conForm; + QAction *menu; +}; + +#endif // FLOATINGCONTROLLER_H diff --git a/tizen/src/ui/floatingconview.cpp b/tizen/src/ui/floatingconview.cpp new file mode 100644 index 0000000000..a6572dcbad --- /dev/null +++ b/tizen/src/ui/floatingconview.cpp @@ -0,0 +1,229 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "floatingconview.h" +#include "mainwindow.h" +#include "skinkeyitem.h" + +#define DOCKABLE_AREA_WIDTH 30 + +FloatingConView::FloatingConView(ControllerForm *conForm, QGraphicsScene *scene, QWidget *parent) + : QGraphicsView(scene, parent) +{ + this->parent = (FloatingController *)parent; + + setStyleSheet("background: transparent"); + setStyleSheet("border-style: none"); + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setAlignment(Qt::AlignLeft | Qt::AlignTop); + + conPos = QPoint(-1, -1); + grabPos = QPoint(-1, -1); + rubberBand = new QRubberBand(QRubberBand::Rectangle, NULL); + + createItems(conForm); +} + +void FloatingConView::createItems(ControllerForm *conForm) +{ + /* bezel */ + bezelItem = new SkinBezelItem(conForm->conImg[ControllerForm::normal]); + scene()->addItem(bezelItem); + + /* HW keys */ + QList keyList = conForm->keyList; + + HardwareKey *hwKey = NULL; + for (int i = 0; i < keyList.count(); i++) { + hwKey = keyList.at(i); + if (hwKey != NULL) { + new SkinKeyItem(conForm->conImg[ControllerForm::pressed].copy(hwKey->region), + hwKey, bezelItem); + } + } +} + +void FloatingConView::resizeEvent(QResizeEvent *event) +{ + //qDebug("resize con view"); + + Q_UNUSED(event) +} + +int FloatingConView::isDockable(QWidget *object, QWidget *subject) +{ + const int heightOneThird = object->size().height() / 3; + + /* MainWindow */ + QRect rectDockableRC(object->pos().x() + object->size().width() - 1, + object->pos().y() + heightOneThird, + DOCKABLE_AREA_WIDTH, + heightOneThird); + + QRect rectDockableRT(object->pos().x() + object->size().width() - 1, + object->pos().y(), + DOCKABLE_AREA_WIDTH, + heightOneThird); + + QRect rectDockableRB(object->pos().x() + object->size().width() - 1, + object->pos().y() + (heightOneThird * 2), + DOCKABLE_AREA_WIDTH, + heightOneThird); + + /* ControllerWidget */ + QRect rectTarget(subject->pos().x() - 1, + subject->pos().y(), + DOCKABLE_AREA_WIDTH, + subject->size().height()); + + // TODO: define recursive function + QRect interRC = rectTarget.intersected(rectDockableRC); + QRect interRT = rectTarget.intersected(rectDockableRT); + QRect interRB = rectTarget.intersected(rectDockableRB); + + QRect *interBiggest = NULL; + + if ((interRC.width() * interRC.height()) < (interRT.width() * interRT.height())) { + interBiggest = &interRT; + } else { + interBiggest = &interRC; + } + + if ((interBiggest->width() * interBiggest->height()) < (interRB.width() * interRB.height())) { + interBiggest = &interRB; + } + + if (interBiggest != NULL && + interBiggest->isNull() == false && interBiggest->isEmpty() == false) { + if (interBiggest == &interRC) { + return Qt::AlignRight | Qt::AlignCenter; + } else if (interBiggest == &interRT) { + return Qt::AlignRight | Qt::AlignTop; + } else if (interBiggest == &interRB) { + return Qt::AlignRight | Qt::AlignBottom; + } + } + + return -1; +} + +void FloatingConView::mousePressEvent(QMouseEvent *event) +{ + QGraphicsView::mousePressEvent(event); + + if (bezelItem->isKeyHandling() == true) { + /* do nothing */ + return; + } + + if (event->button() == Qt::LeftButton) { + grabPos = event->globalPos(); + conPos = parent->pos(); + } +} + +void FloatingConView::mouseReleaseEvent(QMouseEvent *event) +{ + QGraphicsView::mouseReleaseEvent(event); + + if (bezelItem->isKeyHandling() == true) { + /* do nothing */ + return; + } + + if (event->button() == Qt::LeftButton) { + grabPos = QPoint(-1, -1); + if (rubberBand != NULL) { + rubberBand->hide(); + } + } + + const FloatingController *con = parent; + MainWindow *win = ((MainWindow *)con->parent()); + + int dockPos = isDockable((QWidget *)win, (QWidget *)parent); + if (dockPos != -1) { + /* toggle */ + win->openController(win->getUIState()->conState.conFormIndex, dockPos); + return; + } +} + +void FloatingConView::mouseMoveEvent(QMouseEvent *event) +{ + QGraphicsView::mouseMoveEvent(event); + + if (bezelItem->isKeyHandling() == true) { + /* do nothing */ + return; + } + + if (grabPos != QPoint(-1, -1)) { + /* draw guide for dockable position */ + const FloatingController *con = parent; + MainWindow *win = ((MainWindow *)con->parent()); + + if (rubberBand != NULL) { + int dockPos = isDockable((QWidget *)win, (QWidget *)con); + if (dockPos != -1) { + int vShift = 0; + + if (win->size().height() > size().height()) { + if (dockPos & Qt::AlignCenter) { + vShift = (win->size().height() / 2) - (size().height() / 2); + } else if (dockPos & Qt::AlignBottom) { + vShift = win->size().height() - size().height(); + } + } + + QPoint rubberPos(win->pos().x() + win->size().width(), + win->pos().y() + vShift); + rubberBand->setGeometry(QRect(rubberPos, size())); + rubberBand->show(); + } else { + rubberBand->hide(); + } + } + + parent->move(conPos + (event->globalPos() - grabPos)); + } +} + +FloatingConView::~FloatingConView() +{ + qDebug("destroy floating controller view"); + + if (rubberBand != NULL) { + rubberBand->close(); + delete rubberBand; + rubberBand = NULL; + } +} diff --git a/tizen/src/ui/floatingconview.h b/tizen/src/ui/floatingconview.h new file mode 100644 index 0000000000..f2e996f468 --- /dev/null +++ b/tizen/src/ui/floatingconview.h @@ -0,0 +1,66 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef FLOATINGCONVIEW_H +#define FLOATINGCONVIEW_H + +#include + +#include "skinview.h" +#include "skinbezelitem.h" +#include "controllerform.h" + +class FloatingController; + +class FloatingConView : public QGraphicsView +{ +public: + FloatingConView(ControllerForm *conForm, QGraphicsScene *scene, QWidget *parent = 0); + ~FloatingConView(); + +protected: + void resizeEvent(QResizeEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + + int isDockable(QWidget *object, QWidget *subject); + + QPoint grabPos; + QPoint conPos; + +private: + void createItems(ControllerForm *conForm); + + FloatingController *parent; + SkinBezelItem *bezelItem; + QRubberBand *rubberBand; +}; + +#endif // FLOATINGCONVIEW_H diff --git a/tizen/src/ui/hardwarekey.cpp b/tizen/src/ui/hardwarekey.cpp new file mode 100644 index 0000000000..336f27734f --- /dev/null +++ b/tizen/src/ui/hardwarekey.cpp @@ -0,0 +1,43 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "hardwarekey.h" + +HardwareKey::HardwareKey(QString name, int keycode, QRect region, QString tooltip) +{ + this->name = name; + this->keycode = keycode; + this->region = region; + this->tooltip = tooltip; +} + +HardwareKey::~HardwareKey() +{ + qDebug("destroy HW key"); +} diff --git a/tizen/src/ui/hardwarekey.h b/tizen/src/ui/hardwarekey.h new file mode 100644 index 0000000000..6fabe427b4 --- /dev/null +++ b/tizen/src/ui/hardwarekey.h @@ -0,0 +1,47 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef HARDWAREKEY_H +#define HARDWAREKEY_H + +#include + +class HardwareKey +{ +public: + HardwareKey(QString name, int keycode, QRect region, QString tooltip); + ~HardwareKey(); + + QString name; + int keycode; + QRect region; + QString tooltip; +}; + +#endif // HARDWAREKEY_H diff --git a/tizen/src/ui/keyboardhelper.cpp b/tizen/src/ui/keyboardhelper.cpp new file mode 100644 index 0000000000..37ac16e6be --- /dev/null +++ b/tizen/src/ui/keyboardhelper.cpp @@ -0,0 +1,464 @@ +/* + * Qt keyboard helper + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Sungmin Ha + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include + +#include "keyboardhelper.h" + +extern "C" { +#include "emul_state.h" +#include "skin/maruskin_operation.h" + +void virtio_keyboard_event(int keycode); +} + +KeyboardHelper::KeyboardHelper() +{ + createKeyMap(); + createKeypadMap(); + + this->numLockState = false; + this->capsLockState = false; +} + +void KeyboardHelper::createKeypadMap() +{ + keypadMap.insert(48, Qt::Key_Insert); + keypadMap.insert(49, Qt::Key_End); + keypadMap.insert(50, Qt::Key_Down); + keypadMap.insert(51, Qt::Key_PageDown); + keypadMap.insert(52, Qt::Key_Left); + keypadMap.insert(53, Qt::Key_Clear); + keypadMap.insert(54, Qt::Key_Right); + keypadMap.insert(55, Qt::Key_Home); + keypadMap.insert(56, Qt::Key_Up); + keypadMap.insert(57, Qt::Key_PageUp); + keypadMap.insert(46, Qt::Key_Delete); + keypadMap.insert(42, 106); /* * */ + keypadMap.insert(45, 109); /* - */ + + keypadMap.insert(Qt::Key_Insert, 48); + keypadMap.insert(Qt::Key_End, 49); + keypadMap.insert(Qt::Key_Down, 50); + keypadMap.insert(Qt::Key_PageDown, 51); + keypadMap.insert(Qt::Key_Left, 52); + keypadMap.insert(Qt::Key_Clear, 53); + keypadMap.insert(Qt::Key_Right, 54); + keypadMap.insert(Qt::Key_Home, 55); + keypadMap.insert(Qt::Key_Up, 56); + keypadMap.insert(Qt::Key_PageUp, 57); + keypadMap.insert(Qt::Key_Delete, 46); +} + +void KeyboardHelper::createKeyMap() +{ + /* characters */ + /* q ~ p */ + keyMap.insert(81, 16); + keyMap.insert(87, 17); + keyMap.insert(69, 18); + keyMap.insert(82, 19); + keyMap.insert(84, 20); + keyMap.insert(89, 21); + keyMap.insert(85, 22); + keyMap.insert(73, 23); + keyMap.insert(79, 24); + keyMap.insert(80, 25); + + /* a ~ l */ + keyMap.insert(65, 30); + keyMap.insert(83, 31); + keyMap.insert(68, 32); + keyMap.insert(70, 33); + keyMap.insert(71, 34); + keyMap.insert(72, 35); + keyMap.insert(74, 36); + keyMap.insert(75, 37); + keyMap.insert(76, 38); + + /* z ~ m */ + keyMap.insert(90, 44); + keyMap.insert(88, 45); + keyMap.insert(67, 46); + keyMap.insert(86, 47); + keyMap.insert(66, 48); + keyMap.insert(78, 49); + keyMap.insert(77, 50); + + /* signs */ + keyMap.insert(32, 57); /* space */ + keyMap.insert(44, 51); /* , */ + keyMap.insert(46, 52); /* . */ + keyMap.insert(59, 39); /* ; */ + keyMap.insert(47, 53); /* / */ + keyMap.insert(42, 55); /* * */ + keyMap.insert(106, 55); /* * */ + keyMap.insert(45, 12); /* - */ + keyMap.insert(109, 74); /* - */ + keyMap.insert(61, 13); /* = */ + keyMap.insert(91, 26); /* [ */ + keyMap.insert(93, 27); /* ] */ + keyMap.insert(92, 43); /* \ */ + keyMap.insert(43, 78); /* + */ + keyMap.insert(39, 40); /* Single quote */ + keyMap.insert(96, 41); /* ` */ + + /* special keys */ + keyMap.insert(Qt::Key_Return, 28); /* return */ + keyMap.insert(Qt::Key_Enter, 28); /* enter */ + keyMap.insert(Qt::Key_Escape, 1); /* escape */ + keyMap.insert(Qt::Key_Tab, 15); /* tab */ + keyMap.insert(Qt::Key_Backtab, 15); /* shift tab */ + keyMap.insert(Qt::Key_Backspace, 14); /* backspace */ + keyMap.insert(Qt::Key_Pause, 198); /* pause/break */ + keyMap.insert(Qt::Key_PageUp, 73); /* PgUp */ + keyMap.insert(Qt::Key_PageDown, 81); /* PgDn */ + keyMap.insert(Qt::Key_Home, 71); /* Home */ + keyMap.insert(Qt::Key_End, 79); /* End */ + keyMap.insert(Qt::Key_Insert, 82); /* Insert */ + keyMap.insert(Qt::Key_Delete, 83); /* delete */ + + /* arrow keys */ + keyMap.insert(Qt::Key_Up, 72); /* up arrow */ + keyMap.insert(Qt::Key_Down, 80); /* down arrow */ + keyMap.insert(Qt::Key_Left, 75); /* left arrow */ + keyMap.insert(Qt::Key_Right, 77); /* right arrow */ + + /* modifiers */ + keyMap.insert(Qt::Key_Shift, 42); /* shift */ + keyMap.insert(Qt::Key_Control, 29); /* ctrl */ + keyMap.insert(Qt::Key_Alt, 56); /* alt */ + + /* numbers */ + keyMap.insert(48, 11); /* 0 */ + keyMap.insert(49, 2); /* 1 */ + keyMap.insert(50, 3); /* 2 */ + keyMap.insert(51, 4); /* 3 */ + keyMap.insert(52, 5); /* 4 */ + keyMap.insert(53, 6); /* 5 */ + keyMap.insert(54, 7); /* 6 */ + keyMap.insert(55, 8); /* 7 */ + keyMap.insert(56, 9); /* 8 */ + keyMap.insert(57, 10); /* 9 */ + + /* shift + numbers */ + keyMap.insert(126, 41); /* ~ */ + keyMap.insert(33, 2); /* ! */ + keyMap.insert(64, 3); /* @ */ + keyMap.insert(35, 4); /* # */ + keyMap.insert(36, 5); /* $ */ + keyMap.insert(37, 6); /* % */ + keyMap.insert(94, 7); /* ^ */ + keyMap.insert(38, 8); /* & */ + keyMap.insert(40, 10); /* ( */ + keyMap.insert(41, 11); /* ) */ + + /* shift + signs */ + keyMap.insert(95, 12); /* _ */ + keyMap.insert(124, 43); /* | */ + keyMap.insert(123, 26); /* { */ + keyMap.insert(125, 27); /* } */ + keyMap.insert(58, 39); /* : */ + keyMap.insert(34, 40); /* " */ + keyMap.insert(60, 51); /* < */ + keyMap.insert(62, 52); /* > */ + keyMap.insert(63, 53); /* ? */ + + /* function keys */ + keyMap.insert(Qt::Key_F1, 59); /* f1 */ + keyMap.insert(Qt::Key_F2, 60); /* f2 */ + keyMap.insert(Qt::Key_F3, 61); /* f3 */ + keyMap.insert(Qt::Key_F4, 62); /* f4 */ + keyMap.insert(Qt::Key_F5, 63); /* f5 */ + keyMap.insert(Qt::Key_F6, 64); /* f6 */ + keyMap.insert(Qt::Key_F7, 65); /* f7 */ + keyMap.insert(Qt::Key_F8, 66); /* f8 */ + keyMap.insert(Qt::Key_F9, 67); /* f9 */ + keyMap.insert(Qt::Key_F10, 68); /* f10 */ + keyMap.insert(Qt::Key_F11, 87); /* f11 */ + keyMap.insert(Qt::Key_F12, 88); /* f12 */ +} + +void KeyboardHelper::autoKeyRelease(void) +{ + while (!this->keyCodeList.isEmpty()) { + qDebug() << "auto release scancode: " << this->keyCodeList.last(); + do_qt_keyboard_key_event(KEY_RELEASED, this->keyCodeList.last()); + this->keyCodeList.removeLast(); + } + +#if 0 + clear_finger_slot(false); + qDebug() << "disable multi-touch"; +#endif +} + +int KeyboardHelper::keyCodeOperation(QKeyEvent *event, int keyCode) +{ + /* keypad and specialKey translation */ + if (!this->numLockState && (event->modifiers() == (Qt::KeypadModifier | Qt::ShiftModifier))) { + QMap::iterator keypadIter = this->keypadMap.find(keyCode); + while (keypadIter != this->keypadMap.end()) { + if (keypadIter.key() == keyCode) { + keyCode = keypadIter.value(); + break; + } + } + } + + if (this->isSpecialKey(keyCode)) { + virtio_keyboard_event(224); + } + + QMap::iterator keyMapIter = this->keyMap.find(keyCode); + while (keyMapIter != this->keyMap.end()) { + if (keyMapIter.key() == keyCode) { + break; + } + } + + if (keyMapIter == this->keyMap.end()) { + qDebug() << "unsupported keycode pressed: " << keyCode; + return -1; + } + + return keyMapIter.value(); +} + +bool KeyboardHelper::isSpecialKey(int keyCode) +{ + switch(keyCode) { + case Qt::Key_PageDown: + case Qt::Key_PageUp: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Insert: + case Qt::Key_Delete: + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Left: + case Qt::Key_Right: + return true; + default: + break; + } + + return false; +} + +void KeyboardHelper::keyPressed(QKeyEvent *event) +{ + int keyCode = event->key(); + qDebug() << "key pressed :" << event->key() << event->text() << event->nativeScanCode() << event->modifiers() << event->nativeModifiers(); + +#if 0 + /* TODO: multi-touch */ + if (get_emul_max_touch_point() > 1) { + /* multi-touch checking */ + if (event->modifiers() == (Qt::ShiftModifier|Qt::ControlModifier)) { + get_emul_multi_touch_state()->multitouch_enable = 2; + /* add a finger before start the multi-touch processing + if already exist the pressed touch in display */ + qDebug() << "enable multi-touch = mode 2"; + } else if (event->modifiers() == Qt::ShiftModifier || + event->modifiers() == Qt::ControlModifier) { + get_emul_multi_touch_state()->multitouch_enable = 1; + qDebug() << "enable multi-touch = mode 1"; + } + } +#endif + + /* NumLock or CapsLock key */ + if (keyCode == Qt::Key_NumLock) { +#ifdef CONFIG_WIN32 + if (event->nativeModifiers() == 0x1000200) { + this->numLockState = ON; + } else if (event->nativeModifiers() == 0x1000000) { + this->numLockState = OFF; + } +#else + if (event->nativeModifiers() == 0) { + this->numLockState = ON; + } else if (event->nativeModifiers() == 16) { + this->numLockState = OFF; + } +#endif + qDebug() << "num_lock state: " << this->numLockState << "pressed"; + return; + } else if (keyCode == Qt::Key_CapsLock) { +#ifdef CONFIG_WIN32 + if (event->nativeModifiers() == 256) { + this->capsLockState = ON; + } else if (event->nativeModifiers() == 0) { + this->capsLockState = OFF; + } +#else + if (event->nativeModifiers() == 18) { + this->capsLockState = ON; + } else if (event->nativeModifiers() == 16) { + this->capsLockState = OFF; + } +#endif + qDebug() << "caps_lock state: " << this->capsLockState << "pressed"; + return; + } + + /* host numlock check for sync */ + if ((event->modifiers() & Qt::KeypadModifier)) { + if (this->isSpecialKey(keyCode) || keyCode == Qt::Key_Clear) { + if (!(event->modifiers() & Qt::ShiftModifier)) { + this->numLockState = OFF; + } else { + this->numLockState = ON; + } + } else { + if (!(event->modifiers() & Qt::ShiftModifier || keyCode == 42 || keyCode == 43 || keyCode == 45 || keyCode == 47)) { /* (42 = *, 43 = +, 45 = -, 47 = /) on keypad */ + this->numLockState = ON; + } else { + this->numLockState = OFF; + } + } + } + if (event->key() >= 65 && event->key() <= 90) { +#ifdef CONFIG_WIN32 + if (event->nativeModifiers() & 256) { +#else + if (event->nativeModifiers() & 0x02) { +#endif + this->capsLockState = ON; + } else { + this->capsLockState = OFF; + } + } + + if (get_emul_caps_lock_state() != this->capsLockState) { + virtio_keyboard_event(58); + virtio_keyboard_event(58 | 0x80); + set_emul_caps_lock_state(get_emul_caps_lock_state() ^ 1); + qDebug() << "qemu CapsLock state was synchronized with host key value (" << + get_emul_caps_lock_state() << ")"; + } + if (get_emul_num_lock_state() != this->numLockState) { + virtio_keyboard_event(69); + virtio_keyboard_event(69 | 0x80); + set_emul_num_lock_state(get_emul_num_lock_state() ^ 1); + qDebug() << "qemu NumLock state was synchronized with host key value (" << + get_emul_num_lock_state() << ")"; + } + + int ret = this->keyCodeOperation(event, keyCode); + if (ret != -1) { + /* for auto release */ + this->keyCodeList.append(ret); + do_qt_keyboard_key_event(KEY_PRESSED, ret); + } +} + +void KeyboardHelper::keyReleased(QKeyEvent *event) +{ + int keyCode = event->key(); + qDebug() << "key released :" << event->key() << event->text() << event->nativeScanCode() << event->modifiers() << event->nativeModifiers(); + +#if 0 + /* TODO: multi-touch */ + if (event->key() == Qt::Key_Shift && event->modifiers() == Qt::ControlModifier) { + get_emul_multi_touch_state()->multitouch_enable = 1; + qDebug() << "enabled multi-touch = mode 1"; + } else if (event->key() == Qt::Key_Shift || event->key() == Qt::Key_Control) { + clear_finger_slot(false); + qDebug() << "disable multi-touch"; + } +#endif + + if (keyCode == Qt::Key_NumLock) { + qDebug() << "num_lock state: " << this->numLockState << "released"; + return; + } else if (keyCode == Qt::Key_CapsLock) { + qDebug() << "caps_lock state: " << this->capsLockState << "released"; + return; + } + +#ifdef CONFIG_LINUX + /* for keypad keycode translation */ + if (this->numLockState && event->modifiers() == Qt::KeypadModifier) { + if (this->isSpecialKey(keyCode) || keyCode == Qt::Key_Clear) { + switch(keyCode) { + case Qt::Key_Delete: + keyCode = 46; /* . */ + break; + case Qt::Key_Insert: + keyCode = 48; /* 0 */ + break; + case Qt::Key_End: + keyCode = 49; /* 1 */ + break; + case Qt::Key_Down: + keyCode = 50; /* 2 */ + break; + case Qt::Key_PageDown: + keyCode = 51; /* 3 */ + break; + case Qt::Key_Left: + keyCode = 52; /* 4 */ + break; + case Qt::Key_Clear: + keyCode = 53; /* 5 */ + break; + case Qt::Key_Right: + keyCode = 54; /* 6 */ + break; + case Qt::Key_Home: + keyCode = 55; /* 7 */ + break; + case Qt::Key_Up: + keyCode = 56; /* 8 */ + break; + case Qt::Key_PageUp: + keyCode = 57; /* 9 */ + break; + default: + break; + } + } + } +#endif + + int ret = this->keyCodeOperation(event, keyCode); + if (ret != -1) { + do_qt_keyboard_key_event(KEY_RELEASED, ret); + /* remove keycode from list */ + this->keyCodeList.removeOne(ret); + } +} + +KeyboardHelper::~KeyboardHelper() +{ + qDebug("destroy keyboard helper"); +} diff --git a/tizen/src/ui/keyboardhelper.h b/tizen/src/ui/keyboardhelper.h new file mode 100644 index 0000000000..7eef329712 --- /dev/null +++ b/tizen/src/ui/keyboardhelper.h @@ -0,0 +1,64 @@ +/* + * Qt keyboard helper + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Sungmin Ha + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef KEYBOARDHELPER_H +#define KEYBOARDHELPER_H + +#include + +enum KbdLedState { + OFF, + ON +}; + +class KeyboardHelper +{ +public: + KeyboardHelper(); + ~KeyboardHelper(); + + void keyPressed(QKeyEvent *event); + void keyReleased(QKeyEvent *event); + void autoKeyRelease(void); + bool isSpecialKey(int keyCode); + int keyCodeOperation(QKeyEvent *event, int keyCode); + +protected: + QList keyCodeList; + QMap keyMap; + QMap keypadMap; + bool numLockState; + bool capsLockState; + +private: + void createKeyMap(); + void createKeypadMap(); +}; + +#endif // KEYBOARDHELPER_H diff --git a/tizen/src/ui/mainform.cpp b/tizen/src/ui/mainform.cpp new file mode 100644 index 0000000000..c707786292 --- /dev/null +++ b/tizen/src/ui/mainform.cpp @@ -0,0 +1,45 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "mainform.h" + +MainForm::MainForm() : + displayRegion(0, 0, 0, 0) +{ +} + +MainForm::~MainForm() +{ + qDebug("destroy main form"); + + for (int i = 0; i < keyList.count(); i++) { + delete keyList.at(i); + } + keyList.clear(); +} diff --git a/tizen/src/ui/mainform.h b/tizen/src/ui/mainform.h new file mode 100644 index 0000000000..28bcede54b --- /dev/null +++ b/tizen/src/ui/mainform.h @@ -0,0 +1,55 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef MAINFORM_H +#define MAINFORM_H + +#include + +#include "hardwarekey.h" + +class MainForm +{ + Q_ENUMS(SkinImgType) + +public: + MainForm(); + ~MainForm(); + + QImage skinImg[2]; + QRect displayRegion; + QList keyList; + + enum SkinImgType { + normal = 0, + pressed = 1 + }; +}; + +#endif // MAINFORM_H diff --git a/tizen/src/ui/mainwindow.cpp b/tizen/src/ui/mainwindow.cpp new file mode 100644 index 0000000000..2646346ebb --- /dev/null +++ b/tizen/src/ui/mainwindow.cpp @@ -0,0 +1,406 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Hyunjin Lee + * SungMin Ha + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "mainwindow.h" +#include "mainform.h" +#include "displayglwidget.h" +#include "displayswwidget.h" + +extern "C" { +int qt5_graphic_hw_display(void); +} + +QOpenGLContext *qt5GLContext = NULL; +QSurfaceFormat qt5GLFormat; + +DisplaySwapper::DisplaySwapper(QGLContext* context, QObject* parent) + : QObject(parent), context(context), terminating(false) +{ + /* do nothing */ +} + +void DisplaySwapper::display() +{ + /* + * TODO: Currently qt5 skin doesn't terminate properly, + * check this once proper termination is implemented. + */ + + if (context) { + while (!terminating) { + context->makeCurrent(); + if (qt5_graphic_hw_display()) { + context->swapBuffers(); + } + context->doneCurrent(); + } + } else { + while (!terminating) { + qt5_graphic_hw_display(); + } + } +} + +MainWindow::MainWindow(UIInformation *uiInfo, QWidget *parent) + : QWidget(parent) +{ + /* initialize */ + this->uiInfo = uiInfo; + this->popupMenu = NULL; + this->skinView = NULL; + this->display = NULL; + this->screenWidget = NULL; + + captureRequestHandler = NULL; + captureRequestData = NULL; + + /* windowing */ + setWindowTitle("Emulator"); + setWindowIcon(QIcon(QPixmap(":/icons/emulator_icon.ico"))); + + //setStyleSheet("background:transparent;"); + //setAttribute(Qt::WA_TranslucentBackground); + setWindowFlags(Qt::FramelessWindowHint); + + winLayout = new QHBoxLayout(this); + winLayout->setMargin(0); + winLayout->setSpacing(0); + + /* scene */ + skinScene = new QGraphicsScene(this); + skinScene->setBackgroundBrush(Qt::black); + + /* view */ + skinView = new SkinView(skinScene, this); + winLayout->addWidget(skinView); + + /* display */ + QGLContext *context = NULL; + if (qt5GLContext) { /* on-screen rendering */ + QGLContext *wrapperContext = QGLContext::fromOpenGLContext(qt5GLContext); + + /* + * Qt5 bug, wrapperContext->requestedFormat() doesn't return + * originating format, it returns actual format, this may result + * in wrong OpenGL context version here. + */ + + QGLFormat format = QGLFormat::fromSurfaceFormat(qt5GLFormat); + + /* + * Qt5 bug, format set here doesn't always have effect, must + * set it after QGLWidget is created. + */ + context = new QGLContext(format); + + display = new DisplayGLWidget(uiInfo->resolution, context, skinView); + + context->setFormat(format); + + context->create(wrapperContext); + } else { /* off-screen rendering */ + DisplaySWWidget *w = new DisplaySWWidget(uiInfo->resolution, skinView); + + display = w; + screenWidget = w; + } + + /* popup menu */ + popupMenu = new ContextMenu(this); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), + SLOT(showContextMenu(const QPoint&))); + + /* swapper */ + swapperThread = new QThread(this); + + if (context) { + context->doneCurrent(); + context->moveToThread(swapperThread); + } + + swapper = new DisplaySwapper(context); + swapper->moveToThread(swapperThread); + connect(swapperThread, &QThread::finished, swapper, &QObject::deleteLater); + + swapperThread->start(); +} + +void MainWindow::startSwapper() +{ + QMetaObject::invokeMethod(swapper, "display", Qt::QueuedConnection); +} + +void MainWindow::terminateSwapper() +{ + swapper->setTerminating(); + qt5_graphic_hw_invalidate(); +} + +QLabel *MainWindow::getScreenWidget() +{ + return screenWidget; +} + +void MainWindow::showContextMenu(const QPoint& pos) +{ + QAction* selectedItem = 0; + popupMenu->popup(mapToGlobal(pos), selectedItem); + if (selectedItem) { + //qDebug("%s", selectedItem->text().toLocal8Bit().data()); + } else { + qDebug("do nothing"); + } +} + +UIState *MainWindow::getUIState() +{ + return &(uiInfo->uiState); +} + +DockingController *MainWindow::getDockingCon() +{ + return getUIState()->conState.dockingCon; +} + +FloatingController *MainWindow::getFloatingCon() +{ + return getUIState()->conState.floatingCon; +} + +void MainWindow::openController(int index, int dockPos) +{ + if (dockPos == (Qt::AlignRight | Qt::AlignCenter)) { + qDebug("open right-center docking controller %d", index); + } else if (dockPos == (Qt::AlignRight | Qt::AlignTop)) { + qDebug("open right-top docking controller %d", index); + } else if (dockPos == (Qt::AlignRight | Qt::AlignBottom)) { + qDebug("open right-bottom docking controller %d", index); + } else if (dockPos == -1) { + qDebug("open floating controller %d", index); + } else { + qDebug("invalid dock position : %d", dockPos); + dockPos = -1; + } + + closeController(); + + if (uiInfo->conFormList.count() <= index) { + qWarning("controller index out of range"); + return; + } + + ControllerForm *conForm = uiInfo->conFormList.at(index); + if (conForm == NULL) { + qWarning("controller is null"); + return; + } + + QAction *action = NULL; + if (popupMenu != NULL) { + action = (QAction *)popupMenu->getControllerMapper()->mapping(index); + } + + /* create */ + if (dockPos == -1) { + getUIState()->conState.floatingCon = + new FloatingController(conForm, action, this); + } else { + getUIState()->conState.dockingCon = + new DockingController(conForm, action, dockPos, this); + getUIState()->conState.recentlyDockPos = dockPos; + } + + /* update layout */ + getUIState()->conState.conFormIndex = index; + adjustSize(); + + /* arrange */ + if (dockPos == -1) { + if (getUIState()->conState.recentlyFloatPos == QPoint(-1, -1)) { + QPoint globalPos = mapToGlobal(QPoint(0, 0)); + getFloatingCon()->move(globalPos.x() + size().width(), globalPos.y()); + } else { + getFloatingCon()->move(getUIState()->conState.recentlyFloatPos); + getUIState()->conState.recentlyFloatPos = QPoint(-1, -1); + } + + getFloatingCon()->show(); + } else { + winLayout->addWidget(getDockingCon()); + } + + /* Some part of QGLWidget's surface might be lost on Windows when view changing. + * So, we need an additional updating for display. */ + display->update(); +} + +void MainWindow::closeController() +{ + if (getDockingCon() != NULL) { + qDebug("close docking controller"); + + getUIState()->conState.recentlyDockPos = -1; + winLayout->removeWidget(getDockingCon()); + getDockingCon()->close(); + + getUIState()->conState.dockingCon = NULL; + + adjustSize(); + } + + if (getFloatingCon() != NULL) { + qDebug("close floating controller"); + + getUIState()->conState.recentlyFloatPos = getFloatingCon()->pos(); + getFloatingCon()->close(); + + getUIState()->conState.floatingCon = NULL; + } + + /* Some part of QGLWidget's surface might be lost on Windows when view changing. + * So, we need an additional updating for display. */ + display->update(); +} + +void MainWindow::resizeEvent(QResizeEvent *event) +{ + qDebug("resize main window"); + + resize(uiInfo->getUiSize()); + + setRegion(); +} + +void MainWindow::setRegion() +{ + //qDebug("set region"); + + setMask(uiInfo->getUiRegion()); +} + +void MainWindow::rotate(int angle) +{ + qDebug("window rotate : %d", angle); + + getUIState()->mainFormAngle = angle; + + skinView->rotate(); + display->rotate(getUIState()->mainFormAngle); + + adjustSize(); +} + +void MainWindow::scale(int scale) +{ + qDebug("window scale : %d", scale); + + getUIState()->mainFormScale = scale; + + skinView->adjustSize(); + display->scale(getUIState()->mainFormScale); + + adjustSize(); +} + +void MainWindow::capture(void) +{ + qDebug("window screen capture: handler(%p), data(%p)", + captureRequestHandler, captureRequestData); + + if (captureRequestHandler && captureRequestData) { + captureRequestHandler(captureRequestData); + } +} + +void MainWindow::setCaptureRequestHandler(void *data, void (*handler)(void *)) +{ + captureRequestHandler = handler; + captureRequestData = data; +} + +void MainWindow::unsetCaptureRequestHandler(void *data) +{ + captureRequestHandler = NULL; + captureRequestData = NULL; +} + +void MainWindow::processCaptured(bool captured, void *pixels, + int width, int height) +{ + qDebug("window process captured: %d pixel: %p [%dx%d]", + captured, pixels, width, height); + + if (captured) { + QImage image = QImage((uchar *)pixels, width, height, QImage::Format_RGB32); + QPixmap pixmap = QPixmap::fromImage(image); /* deep copy the data */ + + QMetaObject::invokeMethod(popupMenu, "slotShowScreenshot", + Qt::QueuedConnection, + Q_ARG(QPixmap, pixmap)); + qDebug("Image saved: %p", pixels); + } else { + QPixmap pixmap(uiInfo->resolution.width(), uiInfo->resolution.height()); + QMetaObject::invokeMethod(popupMenu, "slotShowScreenshot", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap)); + qDebug("Blank Image saved"); + } + +} + +void MainWindow::setTopMost(bool on) +{ + popupMenu->slotTopMost(on); +} + +MainWindow::~MainWindow() +{ + qDebug("destory main window"); + + swapperThread->quit(); + swapperThread->wait(); +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + int r = QMessageBox::warning(this, + "Emulator", + "Do you really want to quit this program?", + QMessageBox::Yes | QMessageBox::Default, + QMessageBox::No); + if (r == QMessageBox::Yes) { + /* force close */ + shutdown_qemu_gracefully(); + } else { + event->ignore(); + } +} diff --git a/tizen/src/ui/mainwindow.h b/tizen/src/ui/mainwindow.h new file mode 100644 index 0000000000..6fa2563c88 --- /dev/null +++ b/tizen/src/ui/mainwindow.h @@ -0,0 +1,118 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Hyunjin Lee + * SungMin Ha + * GiWoong Kim + * Sangho Park + * Stanislav Vorobiov + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +#include "menu/contextmenu.h" +#include "skinview.h" +#include "displaybase.h" +#include "skinbezelitem.h" +#include "uiinformation.h" +#include "dockingcontroller.h" +#include "floatingcontroller.h" + +extern "C" { +#include "skin/maruskin_operation.h" +} + +class DisplaySwapper : public QObject +{ + Q_OBJECT + +public: + DisplaySwapper(QGLContext* context, QObject* parent = 0); + + inline void setTerminating() { terminating = true; } + +public slots: + void display(); + +private: + QGLContext *context; + bool terminating; +}; + +class MainWindow : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindow(UIInformation *uiInfo, QWidget *parent = 0); + ~MainWindow(); + + UIState *getUIState(void); + QLabel *getScreenWidget(); + void rotate(int angle); + void scale(int scale); + void capture(void); + void setCaptureRequestHandler(void *data, void (*handler)(void *)); + void unsetCaptureRequestHandler(void *data); + void processCaptured(bool captured, void *pixels, int width, int height); + void setTopMost(bool on); + DockingController *getDockingCon(); + FloatingController *getFloatingCon(); + void openController(int index, int dockPos); + void closeController(); + void startSwapper(); + void terminateSwapper(); + + UIInformation *uiInfo; + +public slots: + void showContextMenu(const QPoint& pos); + +protected: + void resizeEvent(QResizeEvent *event); + void closeEvent(QCloseEvent *); + + void setRegion(); + QLabel *screenWidget; + +private: + /* windowing */ + QHBoxLayout *winLayout; + QGraphicsScene *skinScene; + SkinView* skinView; + DisplayBase *display; + ContextMenu *popupMenu; + QThread *swapperThread; + DisplaySwapper *swapper; + + void (*captureRequestHandler)(void *data); + void *captureRequestData; +}; + +#endif // MAINWINDOW_H diff --git a/tizen/src/ui/menu/Makefile.objs b/tizen/src/ui/menu/Makefile.objs new file mode 100644 index 0000000000..7e5454e15d --- /dev/null +++ b/tizen/src/ui/menu/Makefile.objs @@ -0,0 +1,18 @@ +obj-$(CONFIG_QT) += aboutdialog.o moc_aboutdialog.o +obj-$(CONFIG_QT) += screenshot.o moc_screenshot.o +obj-$(CONFIG_QT) += detailedinfodialog.o moc_detailedinfodialog.o +obj-$(CONFIG_QT) += contextmenu.o moc_contextmenu.o +obj-$(CONFIG_QT) += screenshotview.o + +$(obj)/moc_aboutdialog.o: $(obj)/moc_aboutdialog.cpp +$(obj)/moc_aboutdialog.cpp: $(obj)/aboutdialog.h + moc $< -o $@ +$(obj)/moc_detailedinfodialog.o: $(obj)/moc_detailedinfodialog.cpp +$(obj)/moc_detailedinfodialog.cpp: $(obj)/detailedinfodialog.h + moc $< -o $@ +$(obj)/moc_contextmenu.o: $(obj)/moc_contextmenu.cpp +$(obj)/moc_contextmenu.cpp: $(obj)/contextmenu.h + moc $< -o $@ +$(obj)/moc_screenshot.o: $(obj)/moc_screenshot.cpp +$(obj)/moc_screenshot.cpp: $(obj)/screenshot.h + moc $< -o $@ diff --git a/tizen/src/ui/menu/aboutdialog.cpp b/tizen/src/ui/menu/aboutdialog.cpp new file mode 100644 index 0000000000..14f5d165b5 --- /dev/null +++ b/tizen/src/ui/menu/aboutdialog.cpp @@ -0,0 +1,120 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "aboutdialog.h" +#include "build_info.h" + +#define SDK_NAME "Tizen SDK" +#define URL_TIZEN_ORG "https://developer.tizen.org"; + +AboutDialog::AboutDialog(QWidget *parent) : + QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint) +{ + setWindowTitle("About Emulator"); + + QVBoxLayout *baseLayout = new QVBoxLayout(this); + baseLayout->setMargin(0); + baseLayout->setSpacing(5); + + /* upside */ + QHBoxLayout *upsideLayout = new QHBoxLayout(); + upsideLayout->setMargin(0); + upsideLayout->setSpacing(0); + + QLabel *imageLabel = new QLabel(this); + imageLabel->setPixmap(QPixmap(":about.png")); + upsideLayout->addWidget(imageLabel); + + QSettings sdkVersion("../../../sdk.version", QSettings::IniFormat); + QString version = sdkVersion.value("TIZEN_SDK_VERSION").toString(); + if (version.isEmpty() == true) { + qWarning("failed to load SDK version"); + version = "Undefined"; + } + + QString SnapshotName = "Undefined"; + QFile file("../../../install-manager/installmanager.conf"); + if (file.open(QIODevice::ReadOnly | QIODevice::Text) == true) { + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine(); + if (line.startsWith("Snapshot-Path", Qt::CaseInsensitive) == true) { + QStringList snapshotPath = line.split(":", QString::SkipEmptyParts)[1].split("/"); + SnapshotName = snapshotPath.last().trimmed(); + qDebug() << "Snapshot Name :" << SnapshotName; + } + } + + file.close(); + } else { + qWarning("failed to load snapshot name"); + } + + QString aboutText = QString(SDK_NAME) + "

" + + "Version : " + version + "
" + + "Snapshot : " + SnapshotName + "
" + + "Build Date : " + QString(build_date) + "


" + + "Visit " + URL_TIZEN_ORG; + + QLabel *textLabel = new QLabel(this); + textLabel->setStyleSheet("background-color: white"); + textLabel->setTextFormat(Qt::RichText); + //textLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + textLabel->setOpenExternalLinks(true); + textLabel->setMargin(10); + textLabel->setText(aboutText); + upsideLayout->addWidget(textLabel); + + baseLayout->addLayout(upsideLayout); + + /* downside */ + QHBoxLayout *downsideLayout = new QHBoxLayout(); + downsideLayout->setAlignment(Qt::AlignRight); + downsideLayout->setMargin(10); + + QPushButton *okBtn = new QPushButton("OK", this); + connect(okBtn, SIGNAL(clicked()), this, SLOT(close())); + downsideLayout->addWidget(okBtn); + + baseLayout->addLayout(downsideLayout); +} + +void AboutDialog::showEvent(QShowEvent *event) +{ + Q_UNUSED(event) + + QWidget *win = ((QWidget *)this->parent()); + move(win->geometry().center().x() - (geometry().size().width() / 2), + win->geometry().center().y() - (geometry().size().height() / 2)); +} + +AboutDialog::~AboutDialog() +{ + qDebug("destroy about dialog"); +} diff --git a/tizen/src/ui/menu/aboutdialog.h b/tizen/src/ui/menu/aboutdialog.h new file mode 100644 index 0000000000..f81c96de68 --- /dev/null +++ b/tizen/src/ui/menu/aboutdialog.h @@ -0,0 +1,47 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include + +class AboutDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AboutDialog(QWidget *parent = 0); + ~AboutDialog(); + +protected: + void showEvent(QShowEvent *event); +}; + +#endif // ABOUTDIALOG_H diff --git a/tizen/src/ui/menu/contextmenu.cpp b/tizen/src/ui/menu/contextmenu.cpp new file mode 100644 index 0000000000..85f40024a1 --- /dev/null +++ b/tizen/src/ui/menu/contextmenu.cpp @@ -0,0 +1,663 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SungMin Ha + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include + +#include "contextmenu.h" +#include "mainwindow.h" + +#ifdef CONFIG_WIN32 +#include +#elif defined (CONFIG_LINUX) +#include +#include +#endif + +ContextMenu::ContextMenu(QWidget *parent) : QMenu(parent) +{ + this->parent = (MainWindow *)parent; + this->infoDialog = NULL; + this->aboutDialog = NULL; + this->screenshotDialog = NULL; + this->vmName = ((MainWindow *)parent)->uiInfo->vmName + " : " + + QString::number(get_device_serial_number()); + + actionDetailedInfo = NULL; + actionTopMost = NULL; + actionShell = NULL; + actionControlPanel = NULL; + actionAbout = NULL; + actionForceClose = NULL; + actionClose = NULL; + + longPressTimer = new QTimer(this); + + createItems(); + + installEventFilter(this); +} + +void ContextMenu::createItems() { + MainWindow *win = parent; + QAction *action = NULL; + + /* Detailed Info menu */ + actionDetailedInfo = addAction(vmName); + actionDetailedInfo->setIcon(QIcon(QPixmap(":/icons/detailed_info.png"))); + connect(actionDetailedInfo, SIGNAL(triggered()), this, SLOT(slotDetailedInfo())); + + addSeparator(); + + /* Always On Top menu */ + actionTopMost = addAction("&Always on Top"); + actionTopMost->setCheckable(true); + connect(actionTopMost, SIGNAL(triggered(bool)), this, SLOT(slotTopMost(bool))); + + /* = Rotate menu = */ + if (win->uiInfo->mainFormList.count() > 1) { + QMenu *rotateMenu = addMenu(QIcon(QPixmap(":/icons/rotate.png")), "&Rotate"); + QActionGroup *rotateGroup = new QActionGroup(this); + rotateMapper = new QSignalMapper(this); + connect(rotateMapper, SIGNAL(mapped(int)), this, SLOT(slotRotate(int))); + + action = rotateMenu->addAction("Portrait"); + action->setActionGroup(rotateGroup); + action->setCheckable(true); + rotateMapper->setMapping(action, 0); + connect(action, SIGNAL(triggered()), rotateMapper, SLOT(map())); + + action = rotateMenu->addAction("Landscape"); + action->setActionGroup(rotateGroup); + action->setCheckable(true); + rotateMapper->setMapping(action, 270); + connect(action, SIGNAL(triggered()), rotateMapper, SLOT(map())); + + action = rotateMenu->addAction("Reverse Portrait"); + action->setActionGroup(rotateGroup); + action->setCheckable(true); + rotateMapper->setMapping(action, 180); + connect(action, SIGNAL(triggered()), rotateMapper, SLOT(map())); + + action = rotateMenu->addAction("Reverse Landscape"); + action->setActionGroup(rotateGroup); + action->setCheckable(true); + rotateMapper->setMapping(action, 90); + connect(action, SIGNAL(triggered()), rotateMapper, SLOT(map())); + + action = (QAction *)rotateMapper->mapping(win->getUIState()->mainFormAngle); + action->setChecked(true); + } + /* =============== */ + + /* = Scale menu = */ + QMenu *scaleMenu = addMenu(QIcon(QPixmap(":/icons/scale.png")), "&Scale"); + QActionGroup *scaleGroup = new QActionGroup(this); + scaleMapper = new QSignalMapper(this); + connect(scaleMapper, SIGNAL(mapped(int)), this, SLOT(slotScale(int))); + + action = scaleMenu->addAction("1x"); + action->setActionGroup(scaleGroup); + action->setCheckable(true); + scaleMapper->setMapping(action, 100); + connect(action, SIGNAL(triggered()), scaleMapper, SLOT(map())); + + action = scaleMenu->addAction("3/4x"); + action->setActionGroup(scaleGroup); + action->setCheckable(true); + scaleMapper->setMapping(action, 75); + connect(action, SIGNAL(triggered()), scaleMapper, SLOT(map())); + + action = scaleMenu->addAction("1/2x"); + action->setActionGroup(scaleGroup); + action->setCheckable(true); + scaleMapper->setMapping(action, 50); + connect(action, SIGNAL(triggered()), scaleMapper, SLOT(map())); + + action = scaleMenu->addAction("1/4x"); + action->setActionGroup(scaleGroup); + action->setCheckable(true); + scaleMapper->setMapping(action, 25); + connect(action, SIGNAL(triggered()), scaleMapper, SLOT(map())); + + // TODO: interpolation + + action = (QAction *)scaleMapper->mapping(win->getUIState()->mainFormScale); + action->setChecked(true); + /* ============== */ + + /* = Controller menu = */ + QMenu *controllerMenu = NULL; + if (win->uiInfo->conFormList.isEmpty() == false) { + controllerMenu = addMenu("Controller"); + QActionGroup *controllerGroup = new QActionGroup(this); + controllerMapper = new QSignalMapper(this); + connect(controllerMapper, SIGNAL(mapped(int)), this, SLOT(slotController(int))); + + action = controllerMenu->addAction("None"); + action->setActionGroup(controllerGroup); + action->setCheckable(true); + action->setChecked(true); + connect(action, SIGNAL(triggered()), this, SLOT(slotCloseCon())); + + for (int i = 0; i < win->uiInfo->conFormList.count(); i++) { + action = controllerMenu->addAction(win->uiInfo->conFormList.at(i)->name); + action->setActionGroup(controllerGroup); + action->setCheckable(true); + controllerMapper->setMapping(action, i); + connect(action, SIGNAL(triggered()), controllerMapper, SLOT(map())); + } + } + + addSeparator(); + + /* = Advanced menu = */ + QMenu *advancedMenu = addMenu(QIcon(QPixmap(":/icons/advanced.png")), "Ad&vanced"); + + /* Advanced > Screen Shot menu */ + action = advancedMenu->addAction("Screen Shot"); + action->setIcon(QIcon(QPixmap(":/icons/screen_shot.png"))); + connect(action, SIGNAL(triggered()), this, SLOT(slotRequestScreenshot())); + + /* = Host Keyboard menu = */ + QMenu *keyboardMenu = advancedMenu->addMenu( + QIcon(QPixmap(":/icons/host_keyboard.png")), "&Host Keyboard"); + QActionGroup *keyboardGroup = new QActionGroup(this); + + action = keyboardMenu->addAction("On"); + action->setActionGroup(keyboardGroup); + action->setCheckable(true); + connect(action, SIGNAL(toggled(bool)), this, SLOT(slotHostKeyboard(bool))); + + action = keyboardMenu->addAction("Off"); + action->setActionGroup(keyboardGroup); + action->setCheckable(true); + action->setChecked(true); + + advancedMenu->addSeparator(); + + /* Advanced > About menu */ + actionAbout = advancedMenu->addAction("&About"); + actionAbout->setIcon(QIcon(QPixmap(":/icons/about.png"))); + connect(actionAbout, SIGNAL(triggered()), this, SLOT(slotAbout())); + + /* Advanced > Force Close menu */ + actionForceClose = advancedMenu->addAction("&Force Close"); + actionForceClose->setIcon(QIcon(QPixmap(":/icons/force_close.png"))); + connect(actionForceClose, SIGNAL(triggered()), this, SLOT(slotForceClose())); + /* ================= */ + + /* Shell menu */ + actionShell = addAction("S&hell"); + actionShell->setIcon(QIcon(QPixmap(":/icons/shell.png"))); + connect(actionShell, SIGNAL(triggered()), this, SLOT(slotShell())); + + /* Control Panel menu */ + actionControlPanel = addAction("Control &Panel"); + actionControlPanel->setIcon(QIcon(QPixmap(":/icons/control_panel.png"))); + connect(actionControlPanel, SIGNAL(triggered()), this, SLOT(slotControlPanel())); + + addSeparator(); + + /* Close menu */ + actionClose = addAction("&Close"); + actionClose->setIcon(QIcon(QPixmap(":/icons/close.png"))); + connect(actionClose, SIGNAL(triggered()), this, SLOT(slotClose())); +} + +bool ContextMenu::eventFilter(QObject *obj, QEvent *event) +{ + ContextMenu *menu = dynamic_cast(obj); + + if (menu != NULL && + (event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseButtonRelease)) { + QMouseEvent *mouseEvent = dynamic_cast(event); + + if (mouseEvent != NULL && mouseEvent->button() == Qt::RightButton) { + mouseEvent->ignore(); /* filtering */ + return true; + } + } + + return QObject::eventFilter(obj, event); +} + +void ContextMenu::slotDetailedInfo() +{ + qDebug("VM info"); + + if (infoDialog == NULL) { + infoDialog = new DetailedInfoDialog((QWidget *)parent); + } + + infoDialog->show(); +} + +void ContextMenu::slotTopMost(bool on) +{ + qDebug("stays on top : %s", on? "on" : "off"); + +#ifdef CONFIG_WIN32 + HWND hWnd = (HWND)parent->winId(); + HWND hWndInsertAfter = ((on == true) ? HWND_TOPMOST : HWND_NOTOPMOST); + SetWindowPos(hWnd, hWndInsertAfter, parent->pos().x(), parent->pos().y(), 0, 0, SWP_NOSIZE); +#elif defined(CONFIG_LINUX) + Display* display = XOpenDisplay(NULL); + if (display == NULL) { + qDebug("Error: XOpenDisplay() Failed. Always on top failed."); + return; + } + + XClientMessageEvent event; + memset(&event, 0, sizeof(event)); + event.type = ClientMessage; + event.window = parent->winId(); + event.message_type = XInternAtom(display, "_NET_WM_STATE", False); + event.format = 32; + event.data.l[0] = on ? 1 : 0; /* 1:_NET_WM_STATE_ADD, 0:_NET_WM_STATE_REMOVE */ + event.data.l[1] = XInternAtom(display, "_NET_WM_STATE_ABOVE", False); + event.data.l[2] = 0; /* unused */ + event.data.l[3] = 0; + event.data.l[4] = 0; + + XSendEvent(display, DefaultRootWindow(display), False, + SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&event); + XFlush(display); + + XCloseDisplay(display); +#elif defined(CONFIG_DARWIN) + if (on == true) { + parent->setWindowFlags(parent->windowFlags() | Qt::WindowStaysOnTopHint); + } else { + parent->setWindowFlags(parent->windowFlags() & ~(Qt::WindowStaysOnTopHint)); + } + + parent->show(); +#endif + + actionTopMost->setChecked(on); + parent->getUIState()->setOnTop(on); +} + +void ContextMenu::slotRotate(int angle) +{ + qDebug("rotate : %d", angle); + + parent->rotate(angle); +} + +void ContextMenu::slotScale(int scale) +{ + qDebug("scale : %d", scale); + + parent->scale(scale); +} + +void ContextMenu::slotController(int index) +{ + qDebug("controller : %d", index); + + parent->openController(index, + parent->getUIState()->conState.recentlyDockPos); +} + +void ContextMenu::slotCloseCon() +{ + qDebug("controller : None"); + + parent->closeController(); + parent->getUIState()->conState.conFormIndex = -1; +} + +void ContextMenu::slotShell() +{ + qDebug("SDB shell"); + + if (is_sdbd_initialized == 0) { + QString msg = "SDB is not ready.\nPlease wait until the emulator is completely boot up."; + qDebug() << msg; + + QMessageBox *msgBox = new QMessageBox(QMessageBox::Information, + "Emulator", msg, QMessageBox::Ok, (QWidget*)parent); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setModal(false); + msgBox->show(); + + return; + } + + QString sdbPort = QString::number(get_device_serial_number()); + QString sdbSerialName = "emulator-" + sdbPort; + + QString sdbPath = QCoreApplication::applicationDirPath(); +#ifdef CONFIG_WIN32 + sdbPath += "\\..\\..\\ansicon.exe"; +#else + sdbPath += "/../../sdb"; +#endif + + QFileInfo sdbFileInfo(sdbPath); + if (sdbFileInfo.exists() == false) { + QString msg = "SDB file does not exist in the following path.\n" + + sdbFileInfo.absoluteFilePath(); + qWarning() << msg; + + QMessageBox *msgBox = new QMessageBox(QMessageBox::Warning, + "Emulator", msg, QMessageBox::Ok, (QWidget*)parent); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setModal(false); + msgBox->show(); + + return; + } + + QString command; + QStringList arguments; + +#ifdef CONFIG_WIN32 + command = "cmd.exe"; + arguments << "/c" << "start" << sdbPath << "sdb" << "-s" << sdbSerialName << "shell"; +#elif defined CONFIG_DARWIN + command = QCoreApplication::applicationDirPath() + "/sdbscript"; + arguments << sdbSerialName; +#else + command = "/usr/bin/gnome-terminal"; + QString title = "--title=" + vmName; + arguments << title << "-x" << sdbPath << "-s" << sdbSerialName << "shell"; +#endif + + qDebug() << command << arguments; + + try { + QProcess::startDetached(command, arguments); + } catch (QString error) { + QString msg = "Failed to open Shell : " + error; + qDebug() << msg; + + QMessageBox *msgBox = new QMessageBox(QMessageBox::Warning, + "Emulator", msg, QMessageBox::Ok ,(QWidget*)parent); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setModal(false); + msgBox->show(); + + return; + } +} + +#ifdef CONFIG_WIN32 +#define JAVA_MAX_COMMAND_LENGTH 1024 +#define MY_KEY_WOW64_64KEY 0x0100 + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +LPFN_ISWOW64PROCESS menu_fnIsWow64Process; + +static int menu_is_wow64(void) +{ + int result = 0; + + /* IsWow64Process is not available on all supported versions of Windows. + Use GetModuleHandle to get a handle to the DLL that contains the function + and GetProcAddress to get a pointer to the function if available. */ + + menu_fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( + GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); + + if (NULL != menu_fnIsWow64Process) { + if (!menu_fnIsWow64Process(GetCurrentProcess(),&result)) { + // handle error + //fprintf(stderr, "Cannot find 'IsWow64Process'\n"); + } + } + return result; +} + +static bool menu_get_java_path(char** java_path) +{ + HKEY hKeyNew; + HKEY hKey; + //char strJavaRuntimePath[JAVA_MAX_COMMAND_LENGTH] = {0}; + char strChoosenName[JAVA_MAX_COMMAND_LENGTH] = {0}; + char strSubKeyName[JAVA_MAX_COMMAND_LENGTH] = {0}; + char strJavaHome[JAVA_MAX_COMMAND_LENGTH] = {0}; + int index; + DWORD dwSubKeyNameMax = JAVA_MAX_COMMAND_LENGTH; + DWORD dwBufLen = JAVA_MAX_COMMAND_LENGTH; + + RegOpenKeyEx(HKEY_LOCAL_MACHINE, + "SOFTWARE\\JavaSoft\\Java Runtime Environment", + 0, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | MY_KEY_WOW64_64KEY, + &hKey); + RegEnumKeyEx(hKey, 0, (LPSTR)strSubKeyName, &dwSubKeyNameMax, + NULL, NULL, NULL, NULL); + strcpy(strChoosenName, strSubKeyName); + + index = 1; + while (ERROR_SUCCESS == + RegEnumKeyEx(hKey, index, (LPSTR)strSubKeyName, &dwSubKeyNameMax, + NULL, NULL, NULL, NULL)) { + if (strcmp(strChoosenName, strSubKeyName) < 0) { + strcpy(strChoosenName, strSubKeyName); + } + index++; + } + + RegOpenKeyEx(hKey, strChoosenName, 0, + KEY_QUERY_VALUE | MY_KEY_WOW64_64KEY, &hKeyNew); + RegQueryValueEx(hKeyNew, "JavaHome", NULL, + NULL, (LPBYTE)strJavaHome, &dwBufLen); + RegCloseKey(hKey); + + if (strJavaHome[0] != '\0') { + sprintf(*java_path, "%s\\bin\\javaw.exe", strJavaHome); + } else { + return false; + } + + return true; +} +#endif + +void ContextMenu::showPopup(QString msg) +{ + qDebug() << msg; + + QMessageBox *msgBox = new QMessageBox(QMessageBox::Warning, + "Emulator", msg, QMessageBox::Ok, (QWidget*)parent); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setModal(false); + msgBox->show(); +} + +void ContextMenu::slotControlPanel() +{ + qDebug("Control Panel"); + + MainWindow *win = (MainWindow *)parent; + QString basePortOpt = "base.port=" + QString::number(win->uiInfo->basePort); + QString vmNameOpt = "vmname=" + win->uiInfo->vmName; + + QString ecpPath = QCoreApplication::applicationDirPath(); +#ifdef CONFIG_WIN32 + ecpPath += "\\emulator-control-panel.jar"; +#else + ecpPath += "/emulator-control-panel.jar"; +#endif + + QFileInfo ecpFileInfo(ecpPath); + if (!ecpFileInfo.exists()) { + showPopup("Control Panel file does not exist in the following path.\n" + + ecpFileInfo.absoluteFilePath()); + return; + } + + QString command; + QStringList arguments; +#ifdef CONFIG_WIN32 + char* path = (char*)malloc(JAVA_MAX_COMMAND_LENGTH); + memset(path, 0, sizeof(char) * JAVA_MAX_COMMAND_LENGTH); + + if (menu_is_wow64()) { + arguments << "-d64"; + + if (menu_get_java_path(&path)) { + command = QString::fromLocal8Bit(path); + } else { + showPopup("Failed to get java path."); + free(path); + return; + } + } else { + command = "javaw.exe"; + } + free(path); +#else + command = "java"; +#endif + +#ifdef CONFIG_DARWIN + /* SWT Display must be created on main thread due to Cocoa restrictions */ + arguments << "-XstartOnFirstThread"; +#endif + arguments << "-jar" << ecpPath << vmNameOpt << basePortOpt; + + qDebug() << command << arguments; + + try { + QProcess::startDetached(command, arguments); + } catch (QString error) { + showPopup("Failed to open Control Panel : " + error); + return; + } +} + +void ContextMenu::slotRequestScreenshot() +{ + qDebug("request screenshot"); + + parent->capture(); +} + +void ContextMenu::slotShowScreenshot(const QPixmap &screenshot) +{ + qDebug("show screenshot"); + + if (screenshotDialog == NULL) { + screenshotDialog = new Screenshot(this, screenshot); + } + + screenshotDialog->refresh(screenshot); + screenshotDialog->show(); +} + +void ContextMenu::slotHostKeyboard(bool on) +{ + qDebug("host keyboard : %s", on? "on" : "off"); + + do_host_kbd_enable(on); +} + +void ContextMenu::slotAbout() +{ + qDebug("about"); + + if (aboutDialog == NULL) { + aboutDialog = new AboutDialog((QWidget *)parent); + } + + aboutDialog->show(); +} + +void ContextMenu::slotForceClose() +{ + qDebug("force close"); + + QMessageBox *msg = new QMessageBox((QWidget*)parent); + msg->setAttribute(Qt::WA_DeleteOnClose); + msg->setWindowTitle("Emulator"); + msg->setText("If you force stop an emulator, it may cause some problems.\n" + "Are you sure you want to continue?"); + msg->setStandardButtons(QMessageBox::Yes|QMessageBox::No); + msg->setDefaultButton(QMessageBox::Yes); + msg->setIcon(QMessageBox::Question); + msg->setModal(false); + msg->show(); + connect(msg, SIGNAL(buttonClicked(QAbstractButton *)), + this, SLOT(slotForceCloseSelected(QAbstractButton *))); +} + +void ContextMenu::slotForceCloseSelected(QAbstractButton *btn) +{ + if (btn->text().compare("&Yes") == 0) { + qDebug() << "exit!"; + /* force close */ + shutdown_qemu_gracefully(); + } else { + qDebug() << "cancel"; + } +} + +void ContextMenu::slotPwkeyRelease() +{ + do_hw_key_event(KEY_RELEASED, HARD_KEY_POWER); +} + +void ContextMenu::slotClose() +{ + qDebug("close"); + do_hw_key_event(KEY_PRESSED, HARD_KEY_POWER); + + longPressTimer->setInterval(CLOSE_POWER_KEY_INTERVAL); + longPressTimer->setSingleShot(true); + connect(longPressTimer, SIGNAL(timeout()), this, SLOT(slotPwkeyRelease())); + longPressTimer->start(); +} + +QSignalMapper *ContextMenu::getRotateMapper() +{ + return rotateMapper; +} + +QSignalMapper *ContextMenu::getScaleMapper() +{ + return scaleMapper; +} + +QSignalMapper *ContextMenu::getControllerMapper() +{ + return controllerMapper; +} + +ContextMenu::~ContextMenu() +{ + qDebug("destroy menu"); + + longPressTimer->stop(); +} diff --git a/tizen/src/ui/menu/contextmenu.h b/tizen/src/ui/menu/contextmenu.h new file mode 100644 index 0000000000..33a2b1d5d9 --- /dev/null +++ b/tizen/src/ui/menu/contextmenu.h @@ -0,0 +1,109 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SungMin Ha + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef CONTEXTMENU_H +#define CONTEXTMENU_H + +#include + +#include "detailedinfodialog.h" +#include "aboutdialog.h" +#include "screenshot.h" + +class MainWindow; + +extern "C" { +#include "skin/maruskin_operation.h" +#include "skin/maruskin_server.h" +#include "emul_state.h" +} + +#define CLOSE_POWER_KEY_INTERVAL 1200 /* milli-seconds */ + +class ContextMenu : public QMenu +{ + Q_OBJECT + +public: + explicit ContextMenu(QWidget *parent = 0); + ~ContextMenu(); + + QSignalMapper *getRotateMapper(); + QSignalMapper *getScaleMapper(); + QSignalMapper *getControllerMapper(); + Screenshot *screenshotDialog; + +signals: + +public slots: + void slotDetailedInfo(); + void slotTopMost(bool on); + void slotRotate(int angle); + void slotScale(int scale); + void slotController(int index); + void slotCloseCon(); + void slotShell(); + void slotControlPanel(); + void slotRequestScreenshot(); + void slotShowScreenshot(const QPixmap &); + void slotHostKeyboard(bool on); + void slotAbout(); + void slotForceClose(); + void slotForceCloseSelected(QAbstractButton *); + void slotClose(); + void slotPwkeyRelease(); + +protected: + void createItems(); + bool eventFilter(QObject *obj, QEvent *event); + +private: + MainWindow *parent; + + QString vmName; + DetailedInfoDialog *infoDialog; + AboutDialog *aboutDialog; + QTimer *longPressTimer; + + QSignalMapper *rotateMapper; + QSignalMapper *scaleMapper; + QSignalMapper *controllerMapper; + + QAction *actionDetailedInfo; + QAction *actionTopMost; + QAction *actionShell; + QAction *actionControlPanel; + QAction *actionAbout; + QAction *actionForceClose; + QAction *actionClose; + + void showPopup(QString msg); +}; +#endif // CONTEXTMENU_H diff --git a/tizen/src/ui/menu/detailedinfodialog.cpp b/tizen/src/ui/menu/detailedinfodialog.cpp new file mode 100644 index 0000000000..1650546a91 --- /dev/null +++ b/tizen/src/ui/menu/detailedinfodialog.cpp @@ -0,0 +1,241 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "detailedinfodialog.h" +#include "mainwindow.h" + +extern int _qemu_argc; +extern char **_qemu_argv; + +extern char tizen_target_img_path[]; //TODO: not legacy + +DetailedInfoDialog::DetailedInfoDialog(QWidget *parent) : + QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint) +{ + QStringList imagePathList = getImagePathList(); + MainWindow *win = ((MainWindow *)parent); + + setWindowTitle("Detailed Info"); + + baseLayout = new QVBoxLayout(this); + baseLayout->setMargin(10); + baseLayout->setSpacing(10); + + /* upside */ + upsideLayout = new QHBoxLayout(this); + upsideLayout->setMargin(0); + upsideLayout->setSpacing(0); + + /* VM information table */ + infoTable = new QTableWidget(this); + infoTable->setRowCount(11); + infoTable->setColumnCount(2); + infoTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + infoTable->setAlternatingRowColors(true); + + infoTable->verticalHeader()->hide(); + infoTable->resizeRowsToContents(); + infoTable->horizontalHeader()->setStretchLastSection(true); + infoTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + + QStringList header; + header << "Feature" << "Value"; + infoTable->setHorizontalHeaderLabels(header); + + /* table items */ + int index = 0; + item = new QTableWidgetItem("VM Name"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(win->uiInfo->vmName); + infoTable->setItem(index++, 1, item); + + item = new QTableWidgetItem("Skin Name"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(win->uiInfo->skinName); + infoTable->setItem(index++, 1, item); + + item = new QTableWidgetItem("CPU"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem("x86"); + infoTable->setItem(index++, 1, item); + + item = new QTableWidgetItem("Ram Size"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(QString(get_emul_ram_size()) + " MB"); + infoTable->setItem(index++, 1, item); + + item = new QTableWidgetItem("Display Resolution"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(QString::number(win->uiInfo->resolution.width()) + + "x" + QString::number(win->uiInfo->resolution.height())); + infoTable->setItem(index++, 1, item); + +#if 0 + item = new QTableWidgetItem("Display Density"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem("0"); // TODO: + infoTable->setItem(index++, 1, item); +#endif + + item = new QTableWidgetItem("File Sharing Path"); + infoTable->setItem(index, 0, item); + QString sharingPath(get_emul_file_sharing_path()); + item = new QTableWidgetItem((sharingPath.isEmpty()) ? "None" : sharingPath); + infoTable->setItem(index++, 1, item); + + item = new QTableWidgetItem("CPU Virtualization"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem((get_emul_cpu_accel()) ? "Enabled" : "Disabled"); + infoTable->setItem(index++, 1, item); + + item = new QTableWidgetItem("GPU Virtualization"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem((get_emul_gpu_accel()) ? "Enabled" : "Disabled"); + infoTable->setItem(index++, 1, item); + + for (int i = 0; i < imagePathList.size(); i++) { + item = new QTableWidgetItem("Image Path " + QString::number(i + 1)); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(imagePathList[i]); + item->setToolTip(imagePathList[i]); + infoTable->setItem(index++, 1, item); + } + item = new QTableWidgetItem("Log Path"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(get_log_path()); + item->setToolTip(get_log_path()); + infoTable->setItem(index++, 1, item); + + /* temp */ + item = new QTableWidgetItem("Logging Telnet Port"); + infoTable->setItem(index, 0, item); + item = new QTableWidgetItem(QString::number(get_emul_serial_port())); + infoTable->setItem(index++, 1, item); + + /* add double click event listener */ + connect(infoTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(slotDoubleClicked(int, int))); + + int tableHeight = infoTable->horizontalHeader()->height(); + for (int i = 0; i < infoTable->rowCount(); i++) { + tableHeight += infoTable->rowHeight(i); + } + infoTable->setMinimumWidth(200); + infoTable->setMinimumHeight(tableHeight + 2/*border*/); + upsideLayout->addWidget(infoTable); + + baseLayout->addLayout(upsideLayout); + + /* downside */ + downsideLayout = new QHBoxLayout(this); + downsideLayout->setAlignment(Qt::AlignRight); + downsideLayout->setMargin(0); + + okBtn = new QPushButton("OK", this); + connect(okBtn, SIGNAL(clicked()), this, SLOT(close())); + downsideLayout->addWidget(okBtn); + + baseLayout->addLayout(downsideLayout); +} + +QStringList DetailedInfoDialog::getImagePathList() +{ + QStringList imagePathList; + for (int i = 0; i <_qemu_argc; i++) { + if (QString(_qemu_argv[i]).compare("-drive") == 0) { + i += 1; + QStringList splitString = QString(_qemu_argv[i]).split(","); + QStringList splitString2 = splitString[0].split("="); + QString drivePath = splitString2[splitString2.length() -1]; + imagePathList << drivePath; + } + } + qDebug() << imagePathList; + return imagePathList; +} + +void DetailedInfoDialog::slotDoubleClicked(int nRow, int nCol) +{ + QTableWidgetItem *item; + QString string; + + /* Feature side double click event is occured, ignore it */ + if (nCol == 0) + return; + + item = infoTable->item(nRow, 0); + if (item->text().compare("File Sharing Path", Qt::CaseInsensitive) == 0 || + item->text().compare("Image Path", Qt::CaseInsensitive) == 0 || + item->text().compare("Log Path", Qt::CaseInsensitive) == 0) { + /* get path name */ + item = infoTable->item(nRow, nCol); + if (item->text().compare("None", Qt::CaseInsensitive) == 0 || + item->text().compare("", Qt::CaseInsensitive) == 0) { + /* ignore this event */ + return; + } + } else { + /* ignore this event */ + return; + } + + if (QFileInfo(item->text()).isDir() == true) { + /* path name is a directory name */ + QDesktopServices::openUrl(QUrl("file:///" + item->text(), QUrl::TolerantMode)); + } else if (QFileInfo(item->text()).isFile() == true) { + /* path name is a file name */ + QDesktopServices::openUrl(QUrl("file:///" + QFileInfo(item->text()).absolutePath(), QUrl::TolerantMode)); + } else { + qDebug("wrong path name"); + } + + return; +} + +void DetailedInfoDialog::showEvent(QShowEvent *event) +{ + Q_UNUSED(event) + + QWidget *win = ((QWidget *)this->parent()); + move(win->geometry().center().x() - (geometry().size().width() / 2), + win->geometry().center().y() - (geometry().size().height() / 2)); +} + +DetailedInfoDialog::~DetailedInfoDialog() +{ + QTableWidgetItem *item; + + for (int i = 0; i < infoTable->rowCount(); i++) { + for (int j = 0; j < infoTable->columnCount(); j++) { + item = infoTable->item(i, j); + delete item; + } + } + + qDebug("destroy detailed info dialog"); +} diff --git a/tizen/src/ui/menu/detailedinfodialog.h b/tizen/src/ui/menu/detailedinfodialog.h new file mode 100644 index 0000000000..d20d299293 --- /dev/null +++ b/tizen/src/ui/menu/detailedinfodialog.h @@ -0,0 +1,60 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef DETAILEDINFODIALOG_H +#define DETAILEDINFODIALOG_H + +#include +#include + +class DetailedInfoDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DetailedInfoDialog(QWidget *parent = 0); + ~DetailedInfoDialog(); + +protected: + void showEvent(QShowEvent *event); + +public slots: + void slotDoubleClicked(int nRow, int nCol); + +private: + QStringList getImagePathList(); + QVBoxLayout *baseLayout; + QHBoxLayout *upsideLayout; + QTableWidget *infoTable; + QTableWidgetItem *item; + QHBoxLayout *downsideLayout; + QPushButton *okBtn; +}; + +#endif // DETAILEDINFODIALOG_H diff --git a/tizen/src/ui/menu/screenshot.cpp b/tizen/src/ui/menu/screenshot.cpp new file mode 100644 index 0000000000..c672cd45de --- /dev/null +++ b/tizen/src/ui/menu/screenshot.cpp @@ -0,0 +1,240 @@ +/* + * Qt Screenshot + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Munkyu Im + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include +#include "screenshot.h" +#include "screenshotview.h" +#include "mainwindow.h" + +void Screenshot::copy() { + qDebug("copy"); + QClipboard* clipboard = QApplication::clipboard(); + QPixmap pixmap(screenshotPixmap); + clipboard->clear(); + clipboard->setPixmap(pixmap); +} + +QString Screenshot::getRatio() { + return ratioStr; +} + +void Screenshot::setRatio(int level) { + switch (level) { + case 0: + ratio = 0.125; + break; + case 1: + ratio = 0.25; + break; + case 2: + ratio = 0.50; + break; + case 3: + ratio = 1; + break; + case 4: + ratio = 2; + break; + case 5: + ratio = 4; + break; + } + ratioStr = QString::number(ratio * 100).append("%"); +} + +void Screenshot::scaleChanged(int level) { + qDebug("scale changed: %d", level); + sliderLevel = level; + QPixmap pixmap(screenshotPixmap); + setRatio(level); + scene->clear(); + scene->addPixmap(pixmap.scaled(pixmap.size() * ratio, Qt::KeepAspectRatio, Qt::FastTransformation)); + slider->setToolTip(ratioStr); + + updateStatusBar(); +} + +int Screenshot::getSliderLevel() { + return sliderLevel; +} + +void Screenshot::refresh(const QPixmap &pixmap) { + qDebug("refresh"); + + this->frameBuf = pixmap; + + ratioStr = "100%"; + sliderLevel = 3; + slider->setValue(3); + scene->clear(); + + QMatrix rm; + rm.rotate(getRotateAngle()); + screenshotPixmap = screenshotPixmap.transformed(rm); + scene->addPixmap(screenshotPixmap); + slider->setToolTip(ratioStr); +} + +void Screenshot::setStatusBar(qreal posX, qreal posY) { + this->posX = QString::number(posX); + this->posY = QString::number(posY); + + statusBar->showMessage("x: " + this->posX + ", y:" + this->posY + + " (Resolution: " + QString::number(screenshotPixmap.width()) + "x" + QString::number(screenshotPixmap.height()) + + ", " + qPrintable(getRatio()) + ")"); +} + +void Screenshot::updateStatusBar() { + statusBar->showMessage("x: " + this->posX + ", y:" + this->posY + + " (Resolution: " + QString::number(screenshotPixmap.width()) + "x" + QString::number(screenshotPixmap.height()) + + ", " + qPrintable(getRatio()) + ")"); +} + +bool Screenshot::save() { + qDebug("save"); + QString vmname = ((MainWindow *) this->parent()->parent())->uiInfo->vmName; + QDateTime currentDateTime = QDateTime::currentDateTime(); + QString date = currentDateTime.toString("yyyy-MM-dd-HHmmss"); + QString defaultFile = QDir::homePath() + QDir::separator() + vmname + "-" + date + ".png"; + QString filterName = "Image files (*.png *.jpg *.jpeg *.bmp)"; + QString filename = QFileDialog::getSaveFileName(this, "Save Image", defaultFile, filterName); + + if(filename.isEmpty()) { + qDebug("can not have file"); + return false; + } else { + QPixmap pixmap(screenshotPixmap); + qDebug() << filename; + pixmap.save(filename); + return true; + } +} + +int Screenshot::getRotateAngle() { + int rotateAngle = ((MainWindow *)(this->parent()->parent()))->getUIState()->mainFormAngle; + // Too many logs are printed while mouse is moved. + // Thus comment out this line. + //qDebug("rotatedAngle: %d", rotateAngle); + return rotateAngle; +} + +void Screenshot::makeWidgets() { + toolbar = new QToolBar(this); + + slider = new QSlider(Qt::Horizontal, this); + slider->setRange(0, 5); + slider->setValue(3); + sliderLevel = 3; + slider->setFixedWidth(100); + slider->setToolTip("100%"); + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(scaleChanged(int))); + + gridlayout = new QGridLayout; + gridlayout->setContentsMargins(0, 0, 0, 0); + + saveAct = new QAction(tr("&Save"), this); + saveAct->setShortcuts(QKeySequence::Save); + saveAct->setIcon(QIcon(":/icons/save_screenshot_dialog.png")); + saveAct->setToolTip("Save to file"); + connect(saveAct, SIGNAL(triggered()), this, SLOT(save())); + + copyAct = new QAction(tr("&Copy"), this); + copyAct->setShortcuts(QKeySequence::Copy); + copyAct->setIcon(QIcon(":/icons/copy_screenshot_dialog.png")); + copyAct->setToolTip("Copy to clipboard"); + connect(copyAct, SIGNAL(triggered()), this, SLOT(copy())); + + refreshAct = new QAction(tr("&Refresh"), this); + refreshAct->setShortcuts(QKeySequence::Refresh); + refreshAct->setIcon(QIcon(":/icons/refresh_screenshot_dialog.png")); + refreshAct->setToolTip("Refresh Image"); + connect(refreshAct, SIGNAL(triggered()), this->parent(), + SLOT(slotRequestScreenshot())); +} + +void Screenshot::setImage() { + scene = new QGraphicsScene(this); + + qDebug() << screenshotPixmap; + + QMatrix rm; + rm.rotate(getRotateAngle()); + screenshotPixmap = screenshotPixmap.transformed(rm); + scene->addPixmap(screenshotPixmap); + + view = new ScreenshotView(scene, this); + ratioStr = "100%"; + view->setScene(scene); + view->setMouseTracking(true); + + QScrollArea *area = new QScrollArea(this); + area->setFixedSize(screenshotPixmap.width(), screenshotPixmap.height()); + view->setCornerWidget(area); + view->verticalScrollBar()->setValue(1); + view->horizontalScrollBar()->setValue(1); +} + +Screenshot::Screenshot(QWidget *parent, const QPixmap &pixmap) : + QDialog(parent), screenshotPixmap(pixmap) { + QString vmname = ((MainWindow *) parent->parent())->uiInfo->vmName + " : " + + QString::number(get_device_serial_number()); + MainWindow *mainWindow = (MainWindow *) parent->parent(); + this->resize(mainWindow->uiInfo->getMainSize()); + setWindowTitle("Screen Shot - " + vmname); + + makeWidgets(); + + setImage(); + + statusBar = new QStatusBar; + + toolbar->addAction(saveAct); + toolbar->addAction(copyAct); + toolbar->addAction(refreshAct); + toolbar->addWidget(slider); + gridlayout->addWidget(toolbar, 0, 0); + gridlayout->addWidget(view, 1, 0); + gridlayout->addWidget(statusBar, 2, 0); + + this->setLayout(gridlayout); +} + +void Screenshot::showEvent(QShowEvent *event) { + Q_UNUSED(event) + + QWidget *win = ((QWidget *) this->parent()); + move(win->geometry().center().x(), + win->geometry().center().y() - (geometry().size().height() / 2)); +} + +Screenshot::~Screenshot() { + qDebug("distructor"); + ((ContextMenu *)this->parent())->screenshotDialog = NULL; +} diff --git a/tizen/src/ui/menu/screenshot.h b/tizen/src/ui/menu/screenshot.h new file mode 100644 index 0000000000..ff111af2f6 --- /dev/null +++ b/tizen/src/ui/menu/screenshot.h @@ -0,0 +1,87 @@ +/* + * Qt Screenshot + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Munkyu Im + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef SCREENSHOT_H +#define SCREENSHOT_H + +#include + +class Screenshot: public QDialog { +Q_OBJECT + +public: + explicit Screenshot(QWidget *me, const QPixmap &screenshot); + ~Screenshot(); + void setStatusBar(qreal posX, qreal poxY); + int getSliderLevel(); + int getRotateAngle(); + QString getRatio(); + QPixmap frameBuf; + +public slots: + void refresh(const QPixmap &); + +protected: + void showEvent(QShowEvent *event); + QGraphicsScene* scene; + +private slots: + bool save(); + void copy(); + void scaleChanged(int level); + +private: + void makeWidgets(); + void setImage(); + void setRatio(int level); + void updateStatusBar(); + + QString posX; + QString posY; + QGridLayout *gridlayout; + QGraphicsView* view; + int sliderLevel; + QLabel *label; + QSlider* slider; + QPixmap screenshotPixmap; + QToolBar *toolbar; + + QStatusBar *statusBar; + QMenu *fileMenu; + QMenu *editMenu; + QMenu *helpMenu; + QToolBar *toolBar; + float ratio; + QString ratioStr; + QAction *saveAct; + QAction *copyAct; + QAction *refreshAct; +}; + +#endif diff --git a/tizen/src/ui/menu/screenshotview.cpp b/tizen/src/ui/menu/screenshotview.cpp new file mode 100644 index 0000000000..bc06e84f04 --- /dev/null +++ b/tizen/src/ui/menu/screenshotview.cpp @@ -0,0 +1,103 @@ +/* + * Qt Screenshot + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Munkyu Im + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "screenshotview.h" +#include "screenshot.h" +#include + +ScreenshotView::ScreenshotView(QGraphicsScene *scene, QWidget *parent) : + QGraphicsView(scene, parent) { +} + +void ScreenshotView::mouseMoveEvent(QMouseEvent *event) { + int max_x; + int max_y; + Screenshot *screenshot = (Screenshot *)(this->parent()); + QPointF fixedPos = this->mapToScene(event->pos()); + int sliderLevel = screenshot->getSliderLevel(); + + switch (screenshot->getRotateAngle()) { + case 90: + case 270: + max_x = screenshot->frameBuf.size().height(); + max_y = screenshot->frameBuf.size().width(); + break; + case 0: + case 180: + default: + max_x = screenshot->frameBuf.size().width(); + max_y = screenshot->frameBuf.size().height(); + break; + } + + // Too many logs are printed while mouse is moved. + // Thus comment out this line. + //qDebug("sliderLevel: %d", sliderLevel); + int x; + int y; + float expo = 0; + switch (sliderLevel) { + case 0: + expo = 3; + break; + case 1: + expo = 2; + break; + case 2: + expo = 1; + break; + case 3: + expo = 0; + break; + case 4: + expo = -1; + break; + case 5: + expo = -2; + break; + default: + break; + } + + x = (int)(fixedPos.x() * pow(2, expo)); + y = (int)(fixedPos.y() * pow(2, expo)); + if(x > max_x) { + x = max_x; + } + if(y > max_y) { + y = max_y; + } + + if (scene()->sceneRect().contains(fixedPos)) { + screenshot->setStatusBar(x, y); + } +} + +ScreenshotView::~ScreenshotView() { +} diff --git a/tizen/src/ui/menu/screenshotview.h b/tizen/src/ui/menu/screenshotview.h new file mode 100644 index 0000000000..fda6a0b662 --- /dev/null +++ b/tizen/src/ui/menu/screenshotview.h @@ -0,0 +1,45 @@ +/* + * Qt Screenshot + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Munkyu Im + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef SCREENSHOTVIEW_H +#define SCREENSHOTVIEW_H + +#include + +class ScreenshotView: public QGraphicsView { + +public: + ScreenshotView(QGraphicsScene *scene, QWidget *parent); + ~ScreenshotView(); + +protected: + void mouseMoveEvent(QMouseEvent *event); + +}; +#endif diff --git a/tizen/src/ui/resource/about.png b/tizen/src/ui/resource/about.png new file mode 100644 index 0000000000..b276703a7a Binary files /dev/null and b/tizen/src/ui/resource/about.png differ diff --git a/tizen/src/ui/resource/icons/about.png b/tizen/src/ui/resource/icons/about.png new file mode 100644 index 0000000000..4f76588f80 Binary files /dev/null and b/tizen/src/ui/resource/icons/about.png differ diff --git a/tizen/src/ui/resource/icons/advanced.png b/tizen/src/ui/resource/icons/advanced.png new file mode 100644 index 0000000000..14cf9fae59 Binary files /dev/null and b/tizen/src/ui/resource/icons/advanced.png differ diff --git a/tizen/src/ui/resource/icons/close.png b/tizen/src/ui/resource/icons/close.png new file mode 100644 index 0000000000..a1395ce2c4 Binary files /dev/null and b/tizen/src/ui/resource/icons/close.png differ diff --git a/tizen/src/ui/resource/icons/control_panel.png b/tizen/src/ui/resource/icons/control_panel.png new file mode 100644 index 0000000000..3da7e80dfd Binary files /dev/null and b/tizen/src/ui/resource/icons/control_panel.png differ diff --git a/tizen/src/ui/resource/icons/copy_screenshot_dialog.png b/tizen/src/ui/resource/icons/copy_screenshot_dialog.png new file mode 100644 index 0000000000..a07a5f720b Binary files /dev/null and b/tizen/src/ui/resource/icons/copy_screenshot_dialog.png differ diff --git a/tizen/src/ui/resource/icons/detailed_info.png b/tizen/src/ui/resource/icons/detailed_info.png new file mode 100644 index 0000000000..149ffa263e Binary files /dev/null and b/tizen/src/ui/resource/icons/detailed_info.png differ diff --git a/tizen/src/ui/resource/icons/emulator_icon.ico b/tizen/src/ui/resource/icons/emulator_icon.ico new file mode 100644 index 0000000000..a170e86812 Binary files /dev/null and b/tizen/src/ui/resource/icons/emulator_icon.ico differ diff --git a/tizen/src/ui/resource/icons/force_close.png b/tizen/src/ui/resource/icons/force_close.png new file mode 100644 index 0000000000..a506b4d96d Binary files /dev/null and b/tizen/src/ui/resource/icons/force_close.png differ diff --git a/tizen/src/ui/resource/icons/host_keyboard.png b/tizen/src/ui/resource/icons/host_keyboard.png new file mode 100644 index 0000000000..69a87f3207 Binary files /dev/null and b/tizen/src/ui/resource/icons/host_keyboard.png differ diff --git a/tizen/src/ui/resource/icons/refresh_screenshot_dialog.png b/tizen/src/ui/resource/icons/refresh_screenshot_dialog.png new file mode 100644 index 0000000000..e1616d9bc2 Binary files /dev/null and b/tizen/src/ui/resource/icons/refresh_screenshot_dialog.png differ diff --git a/tizen/src/ui/resource/icons/rotate.png b/tizen/src/ui/resource/icons/rotate.png new file mode 100644 index 0000000000..b2fc00f1f5 Binary files /dev/null and b/tizen/src/ui/resource/icons/rotate.png differ diff --git a/tizen/src/ui/resource/icons/save_screenshot_dialog.png b/tizen/src/ui/resource/icons/save_screenshot_dialog.png new file mode 100644 index 0000000000..523fe9efd3 Binary files /dev/null and b/tizen/src/ui/resource/icons/save_screenshot_dialog.png differ diff --git a/tizen/src/ui/resource/icons/scale.png b/tizen/src/ui/resource/icons/scale.png new file mode 100644 index 0000000000..1f3f872b52 Binary files /dev/null and b/tizen/src/ui/resource/icons/scale.png differ diff --git a/tizen/src/ui/resource/icons/screen_shot.png b/tizen/src/ui/resource/icons/screen_shot.png new file mode 100644 index 0000000000..74c85152f2 Binary files /dev/null and b/tizen/src/ui/resource/icons/screen_shot.png differ diff --git a/tizen/src/ui/resource/icons/shell.png b/tizen/src/ui/resource/icons/shell.png new file mode 100644 index 0000000000..e89f1b1690 Binary files /dev/null and b/tizen/src/ui/resource/icons/shell.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default.dbi b/tizen/src/ui/resource/mobile-720x1280-3btn/default.dbi new file mode 100644 index 0000000000..1ba4d64679 --- /dev/null +++ b/tizen/src/ui/resource/mobile-720x1280-3btn/default.dbi @@ -0,0 +1,250 @@ + + + 2.2 + + + + + + + default_0.png + default_0_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + default_L90.png + default_L90_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + default_180.png + default_180_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + default_R90.png + default_R90_p.png + + + + + + 169 + Menu + + Menu + + + + + 139 + Home + + Home + + + + + 158 + Back + + Back + + + + + 116 + Power + + Power + + + + + 115 + Volume + + + Volume + + + + + + 114 + Volume - + + Volume - + + + + + + + + + + + + + diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_0.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_0.png new file mode 100644 index 0000000000..04e01d6e03 Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_0.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_0_p.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_0_p.png new file mode 100644 index 0000000000..4049ae29f6 Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_0_p.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_180.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_180.png new file mode 100644 index 0000000000..750d056fc6 Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_180.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_180_p.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_180_p.png new file mode 100644 index 0000000000..c3fefa649b Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_180_p.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_L90.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_L90.png new file mode 100644 index 0000000000..6d0724c950 Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_L90.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_L90_p.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_L90_p.png new file mode 100644 index 0000000000..babe9d452b Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_L90_p.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_R90.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_R90.png new file mode 100644 index 0000000000..462c544153 Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_R90.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/default_R90_p.png b/tizen/src/ui/resource/mobile-720x1280-3btn/default_R90_p.png new file mode 100644 index 0000000000..2d54428e19 Binary files /dev/null and b/tizen/src/ui/resource/mobile-720x1280-3btn/default_R90_p.png differ diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/info.ini b/tizen/src/ui/resource/mobile-720x1280-3btn/info.ini new file mode 100644 index 0000000000..efd4490dcf --- /dev/null +++ b/tizen/src/ui/resource/mobile-720x1280-3btn/info.ini @@ -0,0 +1,4 @@ +skin.name=Phone 720x1280 +resolution.width=720 +resolution.height=1280 +manager.priority=3 diff --git a/tizen/src/ui/resource/mobile-720x1280-3btn/layout.qml b/tizen/src/ui/resource/mobile-720x1280-3btn/layout.qml new file mode 100644 index 0000000000..012075db3d --- /dev/null +++ b/tizen/src/ui/resource/mobile-720x1280-3btn/layout.qml @@ -0,0 +1,147 @@ +import EmulatorComponent 1.0 + +EmulatorUI { + property string version: "1.0" + + FormList { + Form { + objectName: "portrait" + display: Region { left: 67; top: 116; width: 720; height: 1280 } + + mainImage: "default_0.png" + pressedImage: "default_0_p.png" + + KeyList { + Key { objectName: "Menu"; keycode: 169 + Region { left: 210; top: 1401; width: 84; height: 84 } + tooltip: "Menu" + } + Key { objectName: "Home"; keycode: 139 + Region { left: 390; top: 1401; width: 84; height: 84 } + tooltip: "Home" + } + Key { objectName: "Back"; keycode: 158 + Region { left: 570; top: 1401; width: 84; height: 84 } + tooltip: "Back" + } + Key { objectName: "Power"; keycode: 116 + Region { left: 841; top: 1309; width: 24; height: 96 } + tooltip: "Power" + } + Key { objectName: "Volume +"; keycode: 115 + Region { left: 841; top: 108; width: 24; height: 96 } + tooltip: "Volume +" + } + Key { objectName: "Volume -"; keycode: 114 + Region { left: 841; top: 219; width: 24; height: 96 } + tooltip: "Volume -" + } + } + } + + Form { + objectName: "landscape" + display: Region { left: 116; top: 78; width: 1280; height: 720 } + + mainImage: "default_L90.png" + pressedImage: "default_L90_p.png" + + KeyList { + Key { objectName: "Menu"; keycode: 169 + Region { left: 1400; top: 570; width: 84; height: 84 } + tooltip: "Menu" + } + Key { objectName: "Home"; keycode: 139 + Region { left: 1400; top: 392; width: 84; height: 84 } + tooltip: "Home" + } + Key { objectName: "Back"; keycode: 158 + Region { left: 1400; top: 210; width: 84; height: 84 } + tooltip: "Back" + } + Key { objectName: "Power"; keycode: 116 + Region { left: 1308; top: 2; width: 96; height: 24 } + tooltip: "Power" + } + Key { objectName: "Volume +"; keycode: 115 + Region { left: 108; top: 2; width: 96; height: 24 } + tooltip: "Volume +" + } + Key { objectName: "Volume -"; keycode: 114 + Region { left: 217; top: 2; width: 96; height: 24 } + tooltip: "Volume -" + } + } + } + + Form { + objectName: "reverse portrait" + display: Region { left: 78; top: 117; width: 720; height: 1280 } + + mainImage: "default_180.png" + pressedImage: "default_180_p.png" + + KeyList { + Key { objectName: "Menu"; keycode: 169 + Region { left: 570; top: 30; width: 84; height: 84 } + tooltip: "Menu" + } + Key { objectName: "Home"; keycode: 139 + Region { left: 390; top: 30; width: 84; height: 84 } + tooltip: "Home" + } + Key { objectName: "Back"; keycode: 158 + Region { left: 210; top: 30; width: 84; height: 84 } + tooltip: "Back" + } + Key { objectName: "Power"; keycode: 116 + Region { left: 2; top: 110; width: 24; height: 96 } + tooltip: "Power" + } + Key { objectName: "Volume +"; keycode: 115 + Region { left: 2; top: 1310; width: 24; height: 96 } + tooltip: "Volume +" + } + Key { objectName: "Volume -"; keycode: 114 + Region { left: 2; top: 1200; width: 24; height: 96 } + tooltip: "Volume -" + } + } + } + + Form { + objectName: "reverse landscape" + display: Region { left: 117; top: 67; width: 1280; height: 720 } + + mainImage: "default_R90.png" + pressedImage: "default_R90_p.png" + + KeyList { + Key { objectName: "Menu"; keycode: 169 + Region { left: 28; top: 209; width: 84; height: 84 } + tooltip: "Menu" + } + Key { objectName: "Home"; keycode: 139 + Region { left: 28; top: 391; width: 84; height: 84 } + tooltip: "Home" + } + Key { objectName: "Back"; keycode: 158 + Region { left: 28; top: 568; width: 84; height: 84 } + tooltip: "Back" + } + Key { objectName: "Power"; keycode: 116 + Region { left: 109; top: 841; width: 96; height: 24 } + tooltip: "Power" + } + Key { objectName: "Volume +"; keycode: 115 + Region { left: 1309; top: 841; width: 96; height: 24 } + tooltip: "Volume +" + } + Key { objectName: "Volume -"; keycode: 114 + Region { left: 1199; top: 841; width: 96; height: 24 } + tooltip: "Volume -" + } + } + } + } +} diff --git a/tizen/src/ui/resource/resource.qrc b/tizen/src/ui/resource/resource.qrc new file mode 100644 index 0000000000..74222f3dcc --- /dev/null +++ b/tizen/src/ui/resource/resource.qrc @@ -0,0 +1,20 @@ + + + about.png + icons/emulator_icon.ico + icons/shell.png + icons/about.png + icons/advanced.png + icons/close.png + icons/force_close.png + icons/rotate.png + icons/scale.png + icons/control_panel.png + icons/detailed_info.png + icons/screen_shot.png + icons/host_keyboard.png + icons/save_screenshot_dialog.png + icons/copy_screenshot_dialog.png + icons/refresh_screenshot_dialog.png + + diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default.dbi b/tizen/src/ui/resource/wearable-320x320-1btn/default.dbi new file mode 100644 index 0000000000..8ef39c04f1 --- /dev/null +++ b/tizen/src/ui/resource/wearable-320x320-1btn/default.dbi @@ -0,0 +1,91 @@ + + + 2.2 + + + + + + + default_0.png + default_0_p.png + + + + + + 116 + Power + + Power + + + + + + + + + default_L90.png + default_L90_p.png + + + + + + 116 + Power + + Power + + + + + + + + + default_180.png + default_180_p.png + + + + + + 116 + Power + + Power + + + + + + + + + default_R90.png + default_R90_p.png + + + + + + 116 + Power + + Power + + + + + + + + + + + + + + diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_0.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_0.png new file mode 100755 index 0000000000..cd23252ee7 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_0.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_0_p.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_0_p.png new file mode 100644 index 0000000000..4cfaf7874f Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_0_p.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_180.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_180.png new file mode 100644 index 0000000000..c641763f50 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_180.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_180_p.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_180_p.png new file mode 100644 index 0000000000..871720d0f3 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_180_p.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_L90.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_L90.png new file mode 100644 index 0000000000..e7f089b7a7 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_L90.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_L90_p.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_L90_p.png new file mode 100644 index 0000000000..4d00686f18 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_L90_p.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_R90.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_R90.png new file mode 100644 index 0000000000..349d8adb91 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_R90.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/default_R90_p.png b/tizen/src/ui/resource/wearable-320x320-1btn/default_R90_p.png new file mode 100644 index 0000000000..c5b5e6d422 Binary files /dev/null and b/tizen/src/ui/resource/wearable-320x320-1btn/default_R90_p.png differ diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/info.ini b/tizen/src/ui/resource/wearable-320x320-1btn/info.ini new file mode 100644 index 0000000000..91e5967ba4 --- /dev/null +++ b/tizen/src/ui/resource/wearable-320x320-1btn/info.ini @@ -0,0 +1,4 @@ +skin.name=Wearable 320x320 +resolution.width=320 +resolution.height=320 +manager.priority=1 diff --git a/tizen/src/ui/resource/wearable-320x320-1btn/layout.qml b/tizen/src/ui/resource/wearable-320x320-1btn/layout.qml new file mode 100644 index 0000000000..9fee04421d --- /dev/null +++ b/tizen/src/ui/resource/wearable-320x320-1btn/layout.qml @@ -0,0 +1,67 @@ +import EmulatorComponent 1.0 + +EmulatorUI { + property string version: "1.0" + + FormList { + Form { + objectName: "portrait" + display: Region { left: 26; top: 60; width: 320; height: 320 } + + mainImage: "default_0.png" + pressedImage: "default_0_p.png" + + KeyList { + Key { objectName: "Power"; keycode: 116 + Region { left: 372; top: 116; width: 12; height: 80 } + tooltip: "Power" + } + } + } + + Form { + objectName: "landscape" + display: Region { left: 60; top: 38; width: 320; height: 320 } + + mainImage: "default_L90.png" + pressedImage: "default_L90_p.png" + + KeyList { + Key { objectName: "Power"; keycode: 116 + Region { left: 116; top: 0; width: 80; height: 12 } + tooltip: "Power" + } + } + } + + Form { + objectName: "reverse portrait" + display: Region { left: 38; top: 60; width: 320; height: 320 } + + mainImage: "default_180.png" + pressedImage: "default_180_p.png" + + KeyList { + Key { objectName: "Power"; keycode: 116 + Region { left: 0; top: 244; width: 12; height: 80 } + tooltip: "Power" + } + } + } + + Form { + objectName: "reverse landscape" + display: Region { left: 60; top: 26; width: 320; height: 320 } + + mainImage: "default_R90.png" + pressedImage: "default_R90_p.png" + + KeyList { + Key { objectName: "Power"; keycode: 116 + Region { left: 244; top: 372; width: 80; height: 12 } + tooltip: "Power" + } + } + } + } +} diff --git a/tizen/src/ui/skinbezelitem.cpp b/tizen/src/ui/skinbezelitem.cpp new file mode 100644 index 0000000000..4d900660fe --- /dev/null +++ b/tizen/src/ui/skinbezelitem.cpp @@ -0,0 +1,54 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include + +#include "skinbezelitem.h" + +SkinBezelItem::SkinBezelItem(QImage bezelImg, QGraphicsItem *parent) : + QGraphicsPixmapItem(QPixmap::fromImage(bezelImg), parent) +{ + keyHandling = false; +} + +void SkinBezelItem::setKeyHandling(bool doing) +{ + keyHandling = doing; +} + +bool SkinBezelItem::isKeyHandling() +{ + return keyHandling; +} + +SkinBezelItem::~SkinBezelItem() +{ + qDebug("destroy bezel item"); +} diff --git a/tizen/src/ui/skinbezelitem.h b/tizen/src/ui/skinbezelitem.h new file mode 100644 index 0000000000..e8754f856f --- /dev/null +++ b/tizen/src/ui/skinbezelitem.h @@ -0,0 +1,50 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef SKINBEZELITEM_H +#define SKINBEZELITEM_H + +#include + +class SkinBezelItem : public QGraphicsPixmapItem +{ +public: + SkinBezelItem(QImage bezelImg, QGraphicsItem *parent = 0); + ~SkinBezelItem(); + + void setKeyHandling(bool doing); + bool isKeyHandling(); + +protected: + +private: + bool keyHandling; +}; + +#endif // SKINBEZELITEM_H diff --git a/tizen/src/ui/skinkeyitem.cpp b/tizen/src/ui/skinkeyitem.cpp new file mode 100644 index 0000000000..a658fdc982 --- /dev/null +++ b/tizen/src/ui/skinkeyitem.cpp @@ -0,0 +1,178 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "skinkeyitem.h" + +SkinKeyItem::SkinKeyItem(QImage pressedImg, HardwareKey *key, SkinBezelItem *parent) : + QGraphicsRectItem(key->region, (QGraphicsItem *)parent) +{ + this->bezelParent = parent; + this->pressedImg = pressedImg; + this->key = key; + isPressed = false; + hoverColor = Qt::white; // TODO: + pen.setColor(Qt::transparent); + + longPressTimer = new QTimer(); + longPressTimer->setInterval(2 * 1000); + longPressTimer->setSingleShot(true); + connect(longPressTimer, SIGNAL(timeout()), this, SLOT(longPressDetected())); + + setToolTip("" + + key->tooltip + ""); + + setAcceptHoverEvents(true); +} + +void SkinKeyItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event) + + isPressed = true; + bezelParent->setKeyHandling(true); + pen.setColor(Qt::transparent); + + update(); + + /* check long press key */ + if (key->keycode == LONGPRESS_KEYCODE) { + longPressTimer->start(); + return; + } + qDebug("key pressed : %s", key->name.toLocal8Bit().data()); + + do_hw_key_event(KEY_PRESSED, key->keycode); +} + +void SkinKeyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event) + int keyCode = 0; + isPressed = false; + bezelParent->setKeyHandling(false); + + update(); + + if (key->keycode == LONGPRESS_KEYCODE) { + if (longPressTimer->remainingTime() <= 0) { + /* long press key */ + if (key->name.compare("KEY_RETURN", Qt::CaseInsensitive) == 0) { + qDebug("key released : KEY_EXIT"); + keyCode = 174; + } else if (key->name.compare("KEY_YELLOW", Qt::CaseInsensitive) == 0) { + qDebug("key released : KEY_MENU"); + keyCode = 125; + } else if (key->name.compare("KEY_CYAN", Qt::CaseInsensitive) == 0) { + qDebug("key released : KEY_INFO"); + keyCode = 188; + } + do_hw_key_event(KEY_RELEASED, keyCode); + return; + } else { + /* short press key */ + longPressTimer->stop(); + if (key->name.compare("KEY_RETURN", Qt::CaseInsensitive) == 0) { + keyCode = 1; + } else if (key->name.compare("KEY_YELLOW", Qt::CaseInsensitive) == 0) { + keyCode = 61; + } else if (key->name.compare("KEY_CYAN", Qt::CaseInsensitive) == 0) { + keyCode = 62; + } + qDebug("key pressed : %s", key->name.toLocal8Bit().data()); + do_hw_key_event(KEY_PRESSED, keyCode); + } + } else { + keyCode = key->keycode; + } + + qDebug("key released : %s", key->name.toLocal8Bit().data()); + do_hw_key_event(KEY_RELEASED, keyCode); +} + +void SkinKeyItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event) + //qDebug("key entered"); + + pen.setColor(hoverColor); + + update(); +} + +void SkinKeyItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event) + //qDebug("key leaved"); + + pen.setColor(Qt::transparent); + + update(); +} + +void SkinKeyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option) + Q_UNUSED(widget) + + if (pen.color() != Qt::transparent) { + painter->setPen(pen); + painter->drawRect(rect()); + } + + if (isPressed == true) { + painter->drawImage(rect().x(), rect().y(), pressedImg); + } +} + +void SkinKeyItem::longPressDetected() +{ + int keyCode = 0; + + qDebug("long press detected"); + if (key->name.compare("KEY_RETURN", Qt::CaseInsensitive) == 0) { + qDebug("key pressed : KEY_EXIT"); + keyCode = 174; + } else if (key->name.compare("KEY_YELLOW", Qt::CaseInsensitive) == 0) { + qDebug("key pressed : KEY_MENU"); + keyCode = 125; + } else if (key->name.compare("KEY_CYAN", Qt::CaseInsensitive) == 0) { + qDebug("key pressed : KEY_INFO"); + keyCode = 188; + } + do_hw_key_event(KEY_PRESSED, keyCode); +} + +SkinKeyItem::~SkinKeyItem() +{ + if (longPressTimer) { + delete longPressTimer; + longPressTimer = NULL; + } + //qDebug("destory key item"); +} diff --git a/tizen/src/ui/skinkeyitem.h b/tizen/src/ui/skinkeyitem.h new file mode 100644 index 0000000000..ce311b9322 --- /dev/null +++ b/tizen/src/ui/skinkeyitem.h @@ -0,0 +1,80 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef SKINKEYITEM_H +#define SKINKEYITEM_H + +#include +#include +#include + +#include "skinbezelitem.h" +#include "hardwarekey.h" + +extern "C" { +#include "skin/maruskin_operation.h" +#include "emul_state.h" +} + +#define LONGPRESS_KEYCODE (-999) + +class SkinKeyItem : public QObject, public QGraphicsRectItem +{ + Q_OBJECT + +public: + SkinKeyItem(QImage pressedImg, HardwareKey *key, SkinBezelItem *parent = 0); + ~SkinKeyItem(); + + HardwareKey *key; + QImage pressedImg; + QTimer *longPressTimer; + +signals: + +public slots: + void longPressDetected(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +private: + SkinBezelItem *bezelParent; + bool isPressed; + QColor hoverColor; + QPen pen; + QBrush brush; +}; + +#endif // SKINKEYITEM_H diff --git a/tizen/src/ui/skinview.cpp b/tizen/src/ui/skinview.cpp new file mode 100644 index 0000000000..c06f7566a1 --- /dev/null +++ b/tizen/src/ui/skinview.cpp @@ -0,0 +1,163 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include + +#include "skinview.h" +#include "mainwindow.h" +#include "skinkeyitem.h" + +SkinView::SkinView(QGraphicsScene *scene, QWidget *parent) : + QGraphicsView(scene, parent) +{ + setStyleSheet("border-style: none"); + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setAlignment(Qt::AlignLeft | Qt::AlignTop); + + grabWinPos = QPoint(-1, -1); + grabPos = QPoint(-1, -1); + + createItems(); + + kbd = new KeyboardHelper(); +} + +void SkinView::createItems() +{ + MainWindow *win = ((MainWindow *)this->parent()); + MainForm *form = win->uiInfo->getMainForm(); + + /* bezel */ + SkinBezelItem *bezelItem = new SkinBezelItem(form->skinImg[MainForm::normal]); + scene()->addItem(bezelItem); + + /* HW keys */ + QList keyList = form->keyList; + + HardwareKey *hwKey = NULL; + for (int i = 0; i < keyList.count(); i++) { + hwKey = keyList.at(i); + if (hwKey != NULL) { + new SkinKeyItem(form->skinImg[MainForm::pressed].copy(hwKey->region), + hwKey, bezelItem); + } + } +} + +void SkinView::rotate() +{ + scene()->clear(); + createItems(); + + adjustSize(); +} + +void SkinView::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event) + + qDebug("resize skin view"); + + MainWindow *win = ((MainWindow *)this->parent()); + + /* geometry */ + const int width = win->uiInfo->getUiSize().width(); + const int height = win->uiInfo->getUiSize().height(); + setGeometry(0, 0, width, height); + + /* scaling */ + const qreal sx = win->getUIState()->getScaleFactor(); + const qreal sy = win->getUIState()->getScaleFactor(); + QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1); + setTransform(transform); + + //QGraphicsView::resizeEvent(event); +} + +void SkinView::mousePressEvent(QMouseEvent *event) +{ + //qDebug("pressed %dx%d", event->x(), event->y()); + + if (event->button() == Qt::LeftButton) { + //qDebug("grab"); + + QWidget *win = ((QWidget *) this->parent()); + grabWinPos = win->pos(); + grabPos = event->globalPos(); + } + + QGraphicsView::mousePressEvent(event); +} + +void SkinView::mouseReleaseEvent(QMouseEvent *event) +{ + //qDebug("released %dx%d", event->x(), event->y()); + + if (event->button() == Qt::LeftButton) { + //qDebug("unloose"); + + grabPos = QPoint(-1, -1); + } + + QGraphicsView::mouseReleaseEvent(event); +} + +void SkinView::mouseMoveEvent(QMouseEvent *event) +{ + QWidget *win = ((QWidget *)this->parent()); + + if (grabPos != QPoint(-1, -1)) { + win->move(grabWinPos + (event->globalPos() - grabPos)); + } + + QGraphicsView::mouseMoveEvent(event); +} + +void SkinView::focusOutEvent(QFocusEvent *event) +{ + qDebug() << "focus out!"; + this->kbd->autoKeyRelease(); +} + +void SkinView::keyPressEvent(QKeyEvent *event) +{ + this->kbd->keyPressed(event); +} + +void SkinView::keyReleaseEvent(QKeyEvent *event) +{ + this->kbd->keyReleased(event); +} + +SkinView::~SkinView() +{ + qDebug("destroy skin view"); +} diff --git a/tizen/src/ui/skinview.h b/tizen/src/ui/skinview.h new file mode 100644 index 0000000000..abbdc42303 --- /dev/null +++ b/tizen/src/ui/skinview.h @@ -0,0 +1,63 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef SKINVIEW_H +#define SKINVIEW_H + +#include + +#include "keyboardhelper.h" + +class SkinView : public QGraphicsView +{ +public: + SkinView(QGraphicsScene *scene, QWidget *parent = 0); + ~SkinView(); + + void rotate(); + +protected: + void resizeEvent(QResizeEvent *event); + + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); + void focusOutEvent(QFocusEvent *event); + + QPoint grabWinPos; + QPoint grabPos; + KeyboardHelper *kbd; + +private: + void createItems(); +}; + +#endif // SKINVIEW_H diff --git a/tizen/src/ui/uiinformation.cpp b/tizen/src/ui/uiinformation.cpp new file mode 100644 index 0000000000..0b7e878eb9 --- /dev/null +++ b/tizen/src/ui/uiinformation.cpp @@ -0,0 +1,168 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "uiinformation.h" + +UIInformation::UIInformation() : + resolution(0, 0), basePort(0) +{ + vmDataPath = "./"; + skinPath = "./"; +} + +MainForm *UIInformation::getMainForm() +{ + int index = uiState.getMainFormIndex(); + + if (index > (mainFormList.count() - 1) || index < 0) { + qWarning("invalid form found"); + + uiState.mainFormAngle = 0; + } + + return mainFormList.at(index); +} + +ControllerForm *UIInformation::getConForm() +{ + int index = uiState.conState.getConFormIndex(); + + if (index > (conFormList.count() - 1) || index < 0) { + qWarning("invalid form found"); + + uiState.conState.conFormIndex = 0; + } + + return conFormList.at(index); +} + +QSize UIInformation::getMainSize() +{ + MainForm *mainForm = getMainForm(); + if (mainForm == NULL) { + qWarning("main form is null"); + return QSize(0, 0); + } + + return mainForm->skinImg[MainForm::normal].size() * uiState.getScaleFactor(); +} + +QSize UIInformation::getConSize() +{ + ControllerForm *conForm = getConForm(); + if (conForm == NULL) { + qWarning("controller form is null"); + return QSize(0, 0); + } + + return conForm->conImg[ControllerForm::normal].size(); +} + +QSize UIInformation::getUiSize() +{ + QSize uiSize = getMainSize(); + + /* docking controller */ + if (uiState.conState.dockingCon != NULL) { + QSize conSize = getConSize(); + uiSize.setWidth(uiSize.width() + conSize.width()); + } + + return uiSize; +} + +QRegion UIInformation::getMainRegion() +{ + MainForm *mainForm = getMainForm(); + if (mainForm == NULL) { + qWarning("main form is null"); + return QRegion(0, 0, 100, 100); + } + + QImage *mainImage = &(mainForm->skinImg[MainForm::normal]); + QImage regionImage = mainImage->scaled( + mainImage->width() * uiState.getScaleFactor(), + mainImage->height() * uiState.getScaleFactor()).createAlphaMask(); + + return QRegion(QBitmap::fromImage(regionImage)); +} + +QRegion UIInformation::getConRegion() +{ + ControllerForm *conForm = getConForm(); + if (conForm == NULL) { + qWarning("controller form is null"); + return QRegion(0, 0, 0, 0); + } + + QImage *conImage = &(conForm->conImg[ControllerForm::normal]); + + return QRegion(QBitmap::fromImage(conImage->createAlphaMask())); +} + +QRegion UIInformation::getUiRegion() +{ + QRegion uiRegion = getMainRegion(); + + /* docking controller */ + DockingController *con = uiState.conState.dockingCon; + if (con != NULL) { + QRegion conRegion = getConRegion(); + + int vShift = 0; + if (getMainSize().height() > getConSize().height()) { + if (con->getDockPos() & Qt::AlignCenter) { + vShift = (getMainSize().height() / 2) + - (getConSize().height() / 2); + } else if (con->getDockPos() & Qt::AlignBottom) { + vShift = getMainSize().height() - getConSize().height(); + } + } + + conRegion.translate(getMainSize().width() + 1, vShift); + uiRegion = uiRegion.united(conRegion); + } + + return uiRegion; +} + +UIInformation::~UIInformation() +{ + qDebug("destroy UI info"); + + for (int i = 0; i < mainFormList.count(); i++) { + delete mainFormList.at(i); + } + mainFormList.clear(); + + for (int i = 0; i < conFormList.count(); i++) { + delete conFormList.at(i); + } + conFormList.clear(); +} diff --git a/tizen/src/ui/uiinformation.h b/tizen/src/ui/uiinformation.h new file mode 100644 index 0000000000..14e7fa3225 --- /dev/null +++ b/tizen/src/ui/uiinformation.h @@ -0,0 +1,68 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef UIINFORMATION_H +#define UIINFORMATION_H + +#include + +#include "mainform.h" +#include "uistate.h" +#include "controllerform.h" + +class UIInformation +{ +public: + UIInformation(); + ~UIInformation(); + + QString vmName; + QSize resolution; + int basePort; + QString vmDataPath; + + QString skinPath; + QString skinName; + QList mainFormList; + QList conFormList; + QColor hoverColor; + + UIState uiState; /* runtime information */ + + MainForm *getMainForm(); /* current */ + ControllerForm *getConForm(); + QSize getMainSize(); + QSize getConSize(); + QSize getUiSize(); /* size included main, docking con */ + QRegion getMainRegion(); + QRegion getConRegion(); + QRegion getUiRegion(); /* size included main, docking con */ +}; + +#endif // UIINFORMATION_H diff --git a/tizen/src/ui/uistate.cpp b/tizen/src/ui/uistate.cpp new file mode 100644 index 0000000000..938d7c8588 --- /dev/null +++ b/tizen/src/ui/uistate.cpp @@ -0,0 +1,93 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "uistate.h" + +UIState::UIState() : + mainFormAngle(0), mainFormScale(100) +{ + onTop = false; + conState.conFormIndex = 0; + conState.dockingCon = NULL; + conState.floatingCon = NULL; + conState.recentlyDockPos = -1; + conState.recentlyFloatPos = QPoint(-1, -1); +} + +int UIState::getMainFormIndex(int angle) +{ + // TODO: map + + int index = 0; + + switch(angle) { + case 90: /* Reverse Landscape */ + index = 3; + break; + case 180: /* Reverse Portrait */ + index = 2; + break; + case 270: /* Landscape */ + index = 1; + break; + case 0: + default: + index = 0; + break; + } + + return index; +} + +int UIState::getMainFormIndex() +{ + return getMainFormIndex(mainFormAngle); +} + +qreal UIState::getScaleFactor(int scale) +{ + return ((qreal)scale) / 100; +} + +qreal UIState::getScaleFactor() +{ + return getScaleFactor(this->mainFormScale); +} + +void UIState::setOnTop(bool on) +{ + qDebug("set on top : %d", on); + + onTop = on; +} + +bool UIState::isOnTop() +{ + return onTop; +} diff --git a/tizen/src/ui/uistate.h b/tizen/src/ui/uistate.h new file mode 100644 index 0000000000..392881bf10 --- /dev/null +++ b/tizen/src/ui/uistate.h @@ -0,0 +1,72 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef UISTATE_H +#define UISTATE_H + +#include "dockingcontroller.h" +#include "floatingcontroller.h" + +class ControllerState +{ +public: + inline int getConFormIndex() { + return conFormIndex; + } + + int conFormIndex; + DockingController *dockingCon; + FloatingController *floatingCon; + int recentlyDockPos; + QPoint recentlyFloatPos; +}; + +class UIState +{ +public: + UIState(); + + int getMainFormIndex(int angle); + int getMainFormIndex(); /* current */ + qreal getScaleFactor(int scale); + qreal getScaleFactor(); /* current */ + + void setOnTop(bool on); + bool isOnTop(); + + int mainFormAngle; + int mainFormScale; /* percentage */ + + ControllerState conState; + +private: + bool onTop; +}; + +#endif // UISTATE_H diff --git a/tizen/src/ui/uiutil.cpp b/tizen/src/ui/uiutil.cpp new file mode 100644 index 0000000000..ab2959a149 --- /dev/null +++ b/tizen/src/ui/uiutil.cpp @@ -0,0 +1,41 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "uiutil.h" + +UIUtil::UIUtil() +{ + /* do nothing */ +} + +QRect UIUtil::getHostScreenBounds() +{ + return QApplication::screens().at( + QApplication::desktop()->primaryScreen())->virtualGeometry(); +} diff --git a/tizen/src/ui/uiutil.h b/tizen/src/ui/uiutil.h new file mode 100644 index 0000000000..b7e20d01c1 --- /dev/null +++ b/tizen/src/ui/uiutil.h @@ -0,0 +1,46 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef UIUTIL_H +#define UIUTIL_H + +#include +#include +#include +#include + +class UIUtil +{ +public: + UIUtil(); + + static QRect getHostScreenBounds(); +}; + +#endif // UIUTIL_H diff --git a/tizen/src/ui/xml/Makefile.objs b/tizen/src/ui/xml/Makefile.objs new file mode 100644 index 0000000000..3b999b8448 --- /dev/null +++ b/tizen/src/ui/xml/Makefile.objs @@ -0,0 +1,26 @@ +obj-$(CONFIG_QT) += emulatoruitype.o moc_emulatoruitype.o +obj-$(CONFIG_QT) += formlisttype.o moc_formlisttype.o +obj-$(CONFIG_QT) += formtype.o moc_formtype.o +obj-$(CONFIG_QT) += hardwarekeytype.o moc_hardwarekeytype.o +obj-$(CONFIG_QT) += regiontype.o moc_regiontype.o +obj-$(CONFIG_QT) += keylisttype.o moc_keylisttype.o + +$(obj)/moc_emulatoruitype.o: $(obj)/moc_emulatoruitype.cpp +$(obj)/moc_emulatoruitype.cpp: $(obj)/emulatoruitype.h + moc $< -o $@ +$(obj)/moc_formlisttype.o: $(obj)/moc_formlisttype.cpp +$(obj)/moc_formlisttype.cpp: $(obj)/formlisttype.h + moc $< -o $@ +$(obj)/moc_formtype.o: $(obj)/moc_formtype.cpp +$(obj)/moc_formtype.cpp: $(obj)/formtype.h + moc $< -o $@ +$(obj)/moc_hardwarekeytype.o: $(obj)/moc_hardwarekeytype.cpp +$(obj)/moc_hardwarekeytype.cpp: $(obj)/hardwarekeytype.h + moc $< -o $@ +$(obj)/moc_regiontype.o: $(obj)/moc_regiontype.cpp +$(obj)/moc_regiontype.cpp: $(obj)/regiontype.h + moc $< -o $@ +$(obj)/moc_keylisttype.o: $(obj)/moc_keylisttype.cpp +$(obj)/moc_keylisttype.cpp: $(obj)/keylisttype.h + moc $< -o $@ + diff --git a/tizen/src/ui/xml/emulatoruitype.cpp b/tizen/src/ui/xml/emulatoruitype.cpp new file mode 100644 index 0000000000..cb81765be8 --- /dev/null +++ b/tizen/src/ui/xml/emulatoruitype.cpp @@ -0,0 +1,46 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "emulatoruitype.h" + +EmulatorUIType::EmulatorUIType(QObject *parent) : + QObject(parent) +{ + /* do nothing */ +} + +FormListType *EmulatorUIType::formListType() +{ + return formList; +} + +void EmulatorUIType::setFormListType(FormListType *formList) +{ + this->formList = formList; +} diff --git a/tizen/src/ui/xml/emulatoruitype.h b/tizen/src/ui/xml/emulatoruitype.h new file mode 100644 index 0000000000..e5e4dd0a62 --- /dev/null +++ b/tizen/src/ui/xml/emulatoruitype.h @@ -0,0 +1,54 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef EMULATORUITYPE_H +#define EMULATORUITYPE_H + +#include + +#include "formlisttype.h" + +class EmulatorUIType : public QObject +{ + Q_OBJECT + Q_PROPERTY(FormListType *formListType READ formListType WRITE setFormListType) + Q_CLASSINFO("DefaultProperty", "formListType") + +public: + explicit EmulatorUIType(QObject *parent = 0); + + FormListType *formListType(); + +private: + void setFormListType(FormListType *formList); + + FormListType *formList; +}; + +#endif // EMULATORUITYPE_H diff --git a/tizen/src/ui/xml/formlisttype.cpp b/tizen/src/ui/xml/formlisttype.cpp new file mode 100644 index 0000000000..f2b7d90259 --- /dev/null +++ b/tizen/src/ui/xml/formlisttype.cpp @@ -0,0 +1,46 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "formlisttype.h" + +FormListType::FormListType(QObject *parent) : + QObject(parent) +{ + /* do nothing */ +} + +QQmlListProperty FormListType::formList() +{ + return QQmlListProperty(this, list); +} + +QList *FormListType::getFormList() +{ + return &list; +} diff --git a/tizen/src/ui/xml/formlisttype.h b/tizen/src/ui/xml/formlisttype.h new file mode 100644 index 0000000000..d94a47ebd9 --- /dev/null +++ b/tizen/src/ui/xml/formlisttype.h @@ -0,0 +1,55 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef FORMLISTTYPE_H +#define FORMLISTTYPE_H + +#include +#include + +#include "formtype.h" + +class FormListType : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty formList READ formList) + Q_CLASSINFO("DefaultProperty", "formList") + +public: + explicit FormListType(QObject *parent = 0); + + QList *getFormList(); + +private: + QQmlListProperty formList(); + + QList list; +}; + +#endif // FORMLISTTYPE_H diff --git a/tizen/src/ui/xml/formtype.cpp b/tizen/src/ui/xml/formtype.cpp new file mode 100644 index 0000000000..0f73981755 --- /dev/null +++ b/tizen/src/ui/xml/formtype.cpp @@ -0,0 +1,85 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "formtype.h" + +FormType::FormType(QObject *parent) : + QObject(parent), keyList(NULL) +{ + /* do nothing */ +} + +RegionType *FormType::displayRegionType() +{ + return displayRegion; +} + +void FormType::setDisplayRegionType(RegionType *displayRegion) +{ + this->displayRegion = displayRegion; +} + +QString FormType::mainImageName() const +{ + return mainImgName; +} + +void FormType::setMainImageName(QString imgFileName) +{ + mainImgName = imgFileName; +} + +QString FormType::pressedImageName() const +{ + return pressedImgName; +} + +void FormType::setPressedImageName(QString imgFileName) +{ + pressedImgName = imgFileName; +} + +KeyListType *FormType::keyListType() +{ + return keyList; +} + +void FormType::setKeyListType(KeyListType *keyList) +{ + this->keyList = keyList; +} + +QRect FormType::getDisplayRegion() +{ + if (displayRegion == NULL) { + return QRect(0, 0, 0, 0); + } + + return displayRegion->region(); +} diff --git a/tizen/src/ui/xml/formtype.h b/tizen/src/ui/xml/formtype.h new file mode 100644 index 0000000000..c9eec66c0e --- /dev/null +++ b/tizen/src/ui/xml/formtype.h @@ -0,0 +1,69 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef FORMTYPE_H +#define FORMTYPE_H + +#include + +#include "keylisttype.h" +#include "regiontype.h" + +class FormType : public QObject +{ + Q_OBJECT + Q_PROPERTY(RegionType *display READ displayRegionType WRITE setDisplayRegionType) + Q_PROPERTY(QString mainImage READ mainImageName WRITE setMainImageName) + Q_PROPERTY(QString pressedImage READ pressedImageName WRITE setPressedImageName) + Q_PROPERTY(KeyListType *keyListType READ keyListType WRITE setKeyListType) + Q_CLASSINFO("DefaultProperty", "keyListType") + +public: + explicit FormType(QObject *parent = 0); + + QString mainImageName() const; + QString pressedImageName() const; + KeyListType *keyListType(); + + QRect getDisplayRegion(); + +private: + RegionType *displayRegionType(); + void setDisplayRegionType(RegionType *displayRegion); + void setMainImageName(QString imgFileName); + void setPressedImageName(QString imgFileName); + void setKeyListType(KeyListType *keyList); + + RegionType *displayRegion; + QString mainImgName; + QString pressedImgName; + KeyListType *keyList; +}; + +#endif // FORMTYPE_H diff --git a/tizen/src/ui/xml/hardwarekeytype.cpp b/tizen/src/ui/xml/hardwarekeytype.cpp new file mode 100644 index 0000000000..4def9c8ebf --- /dev/null +++ b/tizen/src/ui/xml/hardwarekeytype.cpp @@ -0,0 +1,75 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "hardwarekeytype.h" + +HardwareKeyType::HardwareKeyType(QObject *parent) : + QObject(parent) +{ + /* do nothing */ +} + +int HardwareKeyType::keycode() const +{ + return code; +} + +void HardwareKeyType::setKeycode(int keycode) +{ + code = keycode; +} + +QString HardwareKeyType::tooltip() const +{ + return tip; +} + +void HardwareKeyType::setTooltip(const QString &tooltip) +{ + tip = tooltip; +} + +RegionType *HardwareKeyType::keyRegionType() +{ + return keyRegion; +} + +void HardwareKeyType::setKeyRegionType(RegionType *keyRegion) +{ + this->keyRegion = keyRegion; +} + +QRect HardwareKeyType::region() +{ + if (keyRegion == NULL) { + return QRect(0, 0, 0, 0); + } + + return keyRegion->region(); +} diff --git a/tizen/src/ui/xml/hardwarekeytype.h b/tizen/src/ui/xml/hardwarekeytype.h new file mode 100644 index 0000000000..f4ef8da17a --- /dev/null +++ b/tizen/src/ui/xml/hardwarekeytype.h @@ -0,0 +1,64 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef HARDWAREKEYTYPE_H +#define HARDWAREKEYTYPE_H + +#include + +#include "regiontype.h" + +class HardwareKeyType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int keycode READ keycode WRITE setKeycode) + Q_PROPERTY(QString tooltip READ tooltip WRITE setTooltip) + Q_PROPERTY(RegionType *keyRegionType READ keyRegionType WRITE setKeyRegionType) + Q_CLASSINFO("DefaultProperty", "keyRegionType") + +public: + explicit HardwareKeyType(QObject *parent = 0); + + int keycode() const; + QString tooltip() const; + + QRect region(); + +private: + void setKeycode(int keycode); + void setTooltip(const QString &tooltip); + RegionType *keyRegionType(); + void setKeyRegionType(RegionType *regionType); + + int code; + QString tip; + RegionType *keyRegion; +}; + +#endif // HARDWAREKEYTYPE_H diff --git a/tizen/src/ui/xml/keylisttype.cpp b/tizen/src/ui/xml/keylisttype.cpp new file mode 100644 index 0000000000..6280cd1c54 --- /dev/null +++ b/tizen/src/ui/xml/keylisttype.cpp @@ -0,0 +1,47 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "keylisttype.h" + +KeyListType::KeyListType(QObject *parent) : + QObject(parent) +{ + /* do nothing */ +} + +QQmlListProperty KeyListType::keyListType() +{ + return QQmlListProperty(this, list); +} + +QList *KeyListType::getKeyList() +{ + return &list; +} + diff --git a/tizen/src/ui/xml/keylisttype.h b/tizen/src/ui/xml/keylisttype.h new file mode 100644 index 0000000000..5427f50d7e --- /dev/null +++ b/tizen/src/ui/xml/keylisttype.h @@ -0,0 +1,55 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef KEYLISTTYPE_H +#define KEYLISTTYPE_H + +#include +#include + +#include "hardwarekeytype.h" + +class KeyListType : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty keyListType READ keyListType) + Q_CLASSINFO("DefaultProperty", "keyListType") + +public: + explicit KeyListType(QObject *parent = 0); + + QList *getKeyList(); + +private: + QQmlListProperty keyListType(); + + QList list; +}; + +#endif // KEYLISTTYPE_H diff --git a/tizen/src/ui/xml/regiontype.cpp b/tizen/src/ui/xml/regiontype.cpp new file mode 100644 index 0000000000..ac370dc1eb --- /dev/null +++ b/tizen/src/ui/xml/regiontype.cpp @@ -0,0 +1,81 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "regiontype.h" + +RegionType::RegionType(QObject *parent) : + QObject(parent), x(0), y(0), w(0), h(0) +{ + /* do nothing */ +} + +int RegionType::left() +{ + return x; +} + +void RegionType::setLeft(int left) +{ + x = left; +} + +int RegionType::top() +{ + return y; +} + +void RegionType::setTop(int top) +{ + y = top; +} + +int RegionType::width() +{ + return w; +} + +void RegionType::setWidth(int width) +{ + w = width; +} + +int RegionType::height() +{ + return h; +} + +void RegionType::setHeight(int height) +{ + h = height; +} + +QRect RegionType::region() const +{ + return QRect(x, y, w, h); +} diff --git a/tizen/src/ui/xml/regiontype.h b/tizen/src/ui/xml/regiontype.h new file mode 100644 index 0000000000..e0885ab96c --- /dev/null +++ b/tizen/src/ui/xml/regiontype.h @@ -0,0 +1,66 @@ +/* + * Qt UI + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * GiWoong Kim + * Sangho Park + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef REGIONTYPE_H +#define REGIONTYPE_H + +#include +#include + +class RegionType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int left READ left WRITE setLeft) + Q_PROPERTY(int top READ top WRITE setTop) + Q_PROPERTY(int width READ width WRITE setWidth) + Q_PROPERTY(int height READ height WRITE setHeight) + +public: + explicit RegionType(QObject *parent = 0); + + int left(); + int top(); + int width(); + int height(); + + QRect region() const; + +private: + void setLeft(int left); + void setTop(int top); + void setWidth(int width); + void setHeight(int height); + + int x; + int y; + int w; + int h; +}; + +#endif // REGIONTYPE_H diff --git a/tizen/src/util/Makefile.objs b/tizen/src/util/Makefile.objs index e9b3de0548..286a422030 100644 --- a/tizen/src/util/Makefile.objs +++ b/tizen/src/util/Makefile.objs @@ -1,3 +1,11 @@ +ifdef CONFIG_WIN32 +QEMU_CFLAGS += -I$(SRC_PATH)/hw/vigs/vigs_inc +endif + +ifdef CONFIG_DARWIN +QEMU_CFLAGS += -I$(SRC_PATH)/hw/vigs/vigs_inc +endif + # osutil LIBS += $(CURL_LIBS) obj-y += osutil.o diff --git a/tizen/src/util/check_gl_cgl.c b/tizen/src/util/check_gl_cgl.c index 379bab38a9..13c7573d29 100644 --- a/tizen/src/util/check_gl_cgl.c +++ b/tizen/src/util/check_gl_cgl.c @@ -75,7 +75,6 @@ struct gl_context *check_gl_context_create(struct gl_context *share_ctx, kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFANoRecovery, kCGLPFAPBuffer, 0 }; @@ -88,7 +87,6 @@ struct gl_context *check_gl_context_create(struct gl_context *share_ctx, kCGLPFAAlphaSize, 8, kCGLPFADepthSize, 24, kCGLPFAStencilSize, 8, - kCGLPFANoRecovery, kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, 0 }; diff --git a/vl.c b/vl.c index 1844efd1a7..6cfce0716a 100644 --- a/vl.c +++ b/vl.c @@ -2198,13 +2198,26 @@ static DisplayType select_display(const char *p) exit(1); #endif #ifdef CONFIG_MARU -# ifdef CONFIG_SDL } else if (strstart(p, "maru_sdl", &opts)) { +# ifdef CONFIG_SDL display = DT_MARU_SDL; +# else + fprintf(stderr, "maru_sdl support is disabled\n"); + exit(1); # endif -# ifdef CONFIG_USE_SHM } else if (strstart(p, "maru_shm", &opts)) { +# ifdef CONFIG_USE_SHM display = DT_MARU_SHM; +# else + fprintf(stderr, "maru_shm is disabled\n"); + exit(1); +# endif + } else if (strstart(p, "maru_qt", &opts)) { +# ifdef CONFIG_QT + display = DT_MARU_QT; +# else + fprintf(stderr, "maru_qt is disabled\n"); + exit(1); # endif #endif /* CONFIG_MARU */ } else if (strstart(p, "none", &opts)) { @@ -3278,6 +3291,10 @@ int main(int argc, char **argv, char **envp) "'%s' option", slots_str ? "maxmem" : "slots"); exit(EXIT_FAILURE); } + +#ifdef CONFIG_MARU + set_emul_ram_size(optarg); +#endif break; } #ifdef CONFIG_TPM @@ -3471,6 +3488,10 @@ int main(int argc, char **argv, char **envp) qemu_opt_get(opts, "mount_tag")); qemu_opt_set(device, "mount_tag", qemu_opt_get(opts, "mount_tag")); + +#ifdef CONFIG_MARU + set_emul_file_sharing_path(qemu_opt_get(opts, "path")); +#endif break; } case QEMU_OPTION_virtfs_synth: { @@ -3596,6 +3617,9 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_enable_yagl: #if defined(CONFIG_YAGL) enable_yagl = 1; +#ifdef CONFIG_MARU + set_emul_gpu_accel(true); +#endif #else fprintf(stderr, "YaGL openGLES passthrough support is disabled," " ignoring -enable-yagl\n"); @@ -3974,6 +3998,10 @@ int main(int argc, char **argv, char **envp) exit(1); } +#ifdef CONFIG_MARU + maru_display_early_init(display_type); +#endif + current_machine = MACHINE(object_new(object_class_get_name( OBJECT_CLASS(machine_class)))); object_property_add_child(object_get_root(), "machine", @@ -4166,6 +4194,8 @@ int main(int argc, char **argv, char **envp) display_type = DT_MARU_SDL; #elif defined(CONFIG_USE_SHM) display_type = DT_MARU_SHM; +#elif defined(CONFIG_QT) + display_type = DT_MARU_QT; #endif #elif defined(CONFIG_GTK) display_type = DT_GTK; @@ -4520,6 +4550,11 @@ int main(int argc, char **argv, char **envp) start_skin(); break; #endif +#if defined(CONFIG_QT) + case DT_MARU_QT: + maru_display_init(ds, display_type, full_screen); + break; +#endif #endif default: break;