libpng="no"
dxva2="no"
vaapi="no"
+qt="no"
+qtabi="5.0"
#
glusterfs=""
glusterfs_discard="no"
;;
--enable-vaapi) vaapi="yes"
;;
+ --disable-qt) qt="no"
+ ;;
+ --enable-qt) qt="yes"
+ ;;
#
--disable-glusterfs) glusterfs="no"
;;
--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
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
# Look for sdl configuration program (pkg-config or sdl-config). Try
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"
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
# 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
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
# 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
#include "display.h"
+#include "vigs_qt5.h"
#include "qom/object_interfaces.h"
#if defined(CONFIG_LINUX)
#include <X11/Xlib.h>
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");
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;
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*/);
};
*/
#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"
}
}
+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;
}
}
+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 =
.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);
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;
{
VIGSState *s = DO_UPCAST(VIGSState, dev, dev);
- vigs_server_destroy(s->server);
+ s->server->destroy(s->server);
qemu_bh_delete(s->fence_ack_bh);
#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 <math.h>
-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
{
" 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"
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)
{
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])
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":
NULL);
ws_sfc->backend->BindTexture(GL_TEXTURE_2D, cur_tex);
+ ws_sfc->tex = tmp_tex;
+
return true;
}
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;
+}
+
/*
* @}
*/
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);
}
/*
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;
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;
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) ???");
}
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;
}
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);
}
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,
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) {
/*
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)
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)) {
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;
}
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;
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);
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);
}
#include <GL/glext.h>
#include "winsys_gl.h"
-struct work_queue;
struct vigs_gl_pool;
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);
*/
/*
- * Other.
+ * Rendering thread related.
+ * @{
*/
GLuint vao;
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);
#include "vigs_gl_backend.h"
#include "vigs_log.h"
+#include "vigs_qt5.h"
#include <OpenGL/OpenGL.h>
#include <dlfcn.h>
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFANoRecovery,
kCGLPFAPBuffer,
0
};
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFANoRecovery,
kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core,
0
};
CGLError error;
CGLPixelFormatObj pixel_format;
int n;
+ CGLContextObj qt5_ctx = NULL;
gl_backend_cgl = g_malloc0(sizeof(*gl_backend_cgl));
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);
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;
}
#include "vigs_gl_backend.h"
#include "vigs_log.h"
+#include "vigs_qt5.h"
#include <GL/glx.h>
#include <dlfcn.h>
PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
PFNGLXGETCURRENTCONTEXTPROC glXGetCurrentContext;
PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
+ PFNGLXQUERYCONTEXTPROC glXQueryContext;
/* GLX_ARB_create_context */
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
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)
{
int n = 0;
GLXFBConfig *configs = NULL;
GLXContext ctx = NULL;
+ unsigned int i;
tmp = getenv("GL_VERSION");
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);
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;
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);
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);
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);
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;
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);
#include "vigs_gl_backend.h"
#include "vigs_log.h"
+#include "vigs_qt5.h"
#include <windows.h>
#include <wingdi.h>
#include <GL/gl.h>
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)
{
UINT n = 0;
PIXELFORMATDESCRIPTOR pix_fmt;
HGLRC ctx;
+ unsigned int i;
tmp = getenv("GL_VERSION");
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:
};
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;
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);
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);
}
if (!vigs_gl_backend_wgl_create_context(gl_backend_wgl,
- NULL,
+ qt5_ctx,
&gl_backend_wgl->ctx)) {
goto fail;
}
#endif /* GL_GLEXT_LEGACY */
-
+#ifdef GL_ARB_shader_objects
#if GL_ARB_shader_objects
#ifndef GL_MESA_shader_debug
#endif /* GL_MESA_shader_debug */
#endif /* GL_ARB_shader_objects */
-
+#endif
/*
* ???. GL_MESA_packed_depth_stencil
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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;
+}
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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;
+}
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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 <QGuiApplication>
+#include <QOpenGLContext>
+#include <qpa/qplatformnativeinterface.h>
+#include <stdio.h>
+
+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);
+}
--- /dev/null
+/*
+ * vigs
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *
+ * 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
--- /dev/null
+/*
+ * vigs stub
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Kitae Kim <kt920.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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;
+}
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 =
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;
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);
}
.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;
server->comm = vigs_comm_create(ram_ptr);
if (!server->comm) {
- goto fail;
+ return false;
}
server->surfaces = g_hash_table_new_full(g_direct_hash,
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)
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);
+ }
}
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;
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;
/*
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);
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
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;
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;
-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
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
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFANoRecovery,
kCGLPFAPBuffer,
0
};
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFANoRecovery,
kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core,
0
};
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)
{
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);
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");
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)
{
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);
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");
#ifdef CONFIG_MARU
DT_MARU_SDL,
DT_MARU_SHM,
+ DT_MARU_QT,
#endif
DT_NONE,
} DisplayType;
#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"
/* gtk.c */
void early_gtk_display_init(void);
void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover);
-
#endif
echo "##### QEMU configure append:" $CONFIGURE_APPEND
exec ./configure \
--enable-werror \
+ --extra-ldflags=-Wl,--export-dynamic \
--audio-drv-list=alsa \
--disable-vnc \
--disable-pie \
--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 \
$CONFIGURE_APPEND \
;;
Darwin*)
+# FIXME: "-export_dynamic" causes error on old version clang
cd ..
echo ""
echo "##### QEMU configuring for emulator"
--disable-cocoa \
--disable-sdl \
$CONFIGURE_APPEND \
+
+# --extra-ldflags="-Xlinker -export_dynamic" \
;;
esac
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) \
;; \
# utils
obj-y += util/
+# ui
+obj-y += ui/
+
# maru display
obj-y += display/
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)
MULTI_DEBUG_CHANNEL(tizen, display);
-MaruScreenShot* screenshot = NULL;
+MaruScreenShot *screenshot;
static MaruDisplayChangeListener *mdcl;
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
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;
}
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);
}
}
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);
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__ */
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();
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);
INFO("Memory attached at 0x%X\n", (int)shared_memory);
}
-
void maru_shm_pre_init(MaruDisplayChangeListener *mdcl)
{
dcl = g_malloc0(sizeof(DisplayChangeListener));
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 */
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QApplication>
+#include <QQmlComponent>
+#include <QQmlEngine>
+#include <QQmlProperty>
+
+#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<RegionType>("EmulatorComponent", 1, 0, "Region");
+ qmlRegisterType<HardwareKeyType>("EmulatorComponent", 1, 0, "Key");
+ qmlRegisterType<KeyListType>("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<ConFile *> 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<EmulatorUIType>("EmulatorComponent", 1, 0, "EmulatorUI");
+ qmlRegisterType<FormListType>("EmulatorComponent", 1, 0, "FormList");
+ qmlRegisterType<FormType>("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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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__
#if defined(CONFIG_LINUX)
#include <X11/XKBlib.h>
-#elif defined (CONFIG_WIN32)
+extern bool kvm_allowed;
+#elif defined(CONFIG_WIN32)
#include <windows.h>
+extern bool hax_allowed;
+#elif defined(CONFIG_DARWIN)
+extern bool hax_allowed;
#endif
DECLARE_DEBUG_CHANNEL(emul_state);
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)
{
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;
+}
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 {
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);
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);
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__ */
}
#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);
return 0;
}
-#ifdef CONFIG_DARWIN
+#if defined(CONFIG_DARWIN) && !defined(CONFIG_QT)
int g_argc;
static void* main_thread(void* args)
#else // WIN32
int main(int argc, char *argv[])
{
+#ifndef CONFIG_DARWIN
maru_register_exception_handler();
+#endif
return emulator_main(argc, argv, NULL);
}
#endif
#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
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);
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;
}
}
}
void ns_event_loop(int* keepRunning);
+void ns_run_in_event_loop(void (*func)());
+
+void set_application_icon(char *path);
+
#endif /* _NS_EVENT_H_ */
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];
+}
JAVA_KEY_DELETE = 127
};
-
#define KEY_MAX 0777
#define KEY_F0 0410
#define KEY_BTAB 0541
-
#define SHIFT 0
+
+/* for Java skin*/
static const int vkkey2scancode[KEY_MAX] = {
[0 ... (KEY_MAX - 1)] = -1,
}
}
+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)
{
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);
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;
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;
#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);
--- /dev/null
+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 $@
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QWidget>
+
+#include "hardwarekey.h"
+
+class ControllerForm
+{
+ Q_ENUMS(ConImgType)
+
+public:
+ ControllerForm(QString name);
+ ~ControllerForm();
+
+ QString name;
+ QImage conImg[2];
+ QList<HardwareKey *> keyList;
+
+ enum ConImgType {
+ normal = 0,
+ pressed = 1
+ };
+};
+
+#endif // CONTROLLERFORM_H
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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);
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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 <QWidget>
+
+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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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 <QtWidgets>
+
+#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()
+{
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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 <QGLWidget>
+
+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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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 <QtWidgets>
+
+#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()
+{
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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 <QLabel>
+
+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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QDialog>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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<HardwareKey *> 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;
+ }
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QRubberBand>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QDialog>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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<HardwareKey *> 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;
+ }
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QRubberBand>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QWidget>
+
+class HardwareKey
+{
+public:
+ HardwareKey(QString name, int keycode, QRect region, QString tooltip);
+ ~HardwareKey();
+
+ QString name;
+ int keycode;
+ QRect region;
+ QString tooltip;
+};
+
+#endif // HARDWAREKEY_H
--- /dev/null
+/*
+ * Qt keyboard helper
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Sungmin Ha <sungmin82.ha@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <Qt>
+#include <QtWidgets>
+
+#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<int, int>::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<int, int>::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");
+}
--- /dev/null
+/*
+ * Qt keyboard helper
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Sungmin Ha <sungmin82.ha@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QMap>
+
+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<int> keyCodeList;
+ QMap<int, int> keyMap;
+ QMap<int, int> keypadMap;
+ bool numLockState;
+ bool capsLockState;
+
+private:
+ void createKeyMap();
+ void createKeypadMap();
+};
+
+#endif // KEYBOARDHELPER_H
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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();
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+#include "hardwarekey.h"
+
+class MainForm
+{
+ Q_ENUMS(SkinImgType)
+
+public:
+ MainForm();
+ ~MainForm();
+
+ QImage skinImg[2];
+ QRect displayRegion;
+ QList<HardwareKey *> keyList;
+
+ enum SkinImgType {
+ normal = 0,
+ pressed = 1
+ };
+};
+
+#endif // MAINFORM_H
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Hyunjin Lee <hyunjin816.lee@samsung.com>
+ * SungMin Ha <sungmin82.ha@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Hyunjin Lee <hyunjin816.lee@samsung.com>
+ * SungMin Ha <sungmin82.ha@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ * 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 <QWidget>
+#include <QGLContext>
+
+#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
--- /dev/null
+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 $@
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 "<a href=\"https://developer.tizen.org\">https://developer.tizen.org</a>";
+
+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) + "<p>"
+ + "Version : " + version + "<br>"
+ + "Snapshot : " + SnapshotName + "<br>"
+ + "Build Date : " + QString(build_date) + "<p><br>"
+ + "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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+class AboutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit AboutDialog(QWidget *parent = 0);
+ ~AboutDialog();
+
+protected:
+ void showEvent(QShowEvent *event);
+};
+
+#endif // ABOUTDIALOG_H
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * SungMin Ha <sungmin82.ha@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+#include "contextmenu.h"
+#include "mainwindow.h"
+
+#ifdef CONFIG_WIN32
+#include <windows.h>
+#elif defined (CONFIG_LINUX)
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#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<ContextMenu *>(obj);
+
+ if (menu != NULL &&
+ (event->type() == QEvent::MouseButtonPress ||
+ event->type() == QEvent::MouseButtonRelease)) {
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(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();
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * SungMin Ha <sungmin82.ha@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+#include <QDialog>
+
+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
--- /dev/null
+/*
+ * Qt Screenshot
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Munkyu Im <munkyu.im@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+#include <qtoolbutton.h>
+#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;
+}
--- /dev/null
+/*
+ * Qt Screenshot
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Munkyu Im <munkyu.im@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+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
--- /dev/null
+/*
+ * Qt Screenshot
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Munkyu Im <munkyu.im@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtCore/qmath.h>
+
+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() {
+}
--- /dev/null
+/*
+ * Qt Screenshot
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Munkyu Im <munkyu.im@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+class ScreenshotView: public QGraphicsView {
+
+public:
+ ScreenshotView(QGraphicsScene *scene, QWidget *parent);
+ ~ScreenshotView();
+
+protected:
+ void mouseMoveEvent(QMouseEvent *event);
+
+};
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<EmulatorUI xmlns="http://www.tizen.org/emulator/skin/dbi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <dbi_version>2.2</dbi_version>
+ <rotations>
+ <rotation name="Portrait">
+ <display id="0">
+ <region left="67" top="116" width="720" height="1280"/>
+ </display>
+ <imageList>
+ <mainImage>default_0.png</mainImage>
+ <keyPressedImage>default_0_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="210" top="1401" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>169</keyCode>
+ <keyName>Menu</keyName>
+ </eventInfo>
+ <tooltip>Menu</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="390" top="1401" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>139</keyCode>
+ <keyName>Home</keyName>
+ </eventInfo>
+ <tooltip>Home</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="570" top="1401" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>158</keyCode>
+ <keyName>Back</keyName>
+ </eventInfo>
+ <tooltip>Back</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="841" top="1309" width="24" height="96" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="841" top="108" width="24" height="96" update="true"/>
+ <eventInfo>
+ <keyCode>115</keyCode>
+ <keyName>Volume +</keyName>
+ </eventInfo>
+ <tooltip>Volume +</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="841" top="219" width="24" height="96" update="true"/>
+ <eventInfo>
+ <keyCode>114</keyCode>
+ <keyName>Volume -</keyName>
+ </eventInfo>
+ <tooltip>Volume -</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ <rotation name="Landscape">
+ <display id="0">
+ <region left="116" top="78" width="1280" height="720"/>
+ </display>
+ <imageList>
+ <mainImage>default_L90.png</mainImage>
+ <keyPressedImage>default_L90_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="1400" top="570" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>169</keyCode>
+ <keyName>Menu</keyName>
+ </eventInfo>
+ <tooltip>Menu</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="1400" top="392" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>139</keyCode>
+ <keyName>Home</keyName>
+ </eventInfo>
+ <tooltip>Home</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="1400" top="210" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>158</keyCode>
+ <keyName>Back</keyName>
+ </eventInfo>
+ <tooltip>Back</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="1308" top="2" width="96" height="24" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="108" top="2" width="96" height="24" update="true"/>
+ <eventInfo>
+ <keyCode>115</keyCode>
+ <keyName>Volume +</keyName>
+ </eventInfo>
+ <tooltip>Volume +</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="217" top="2" width="96" height="24" update="true"/>
+ <eventInfo>
+ <keyCode>114</keyCode>
+ <keyName>Volume -</keyName>
+ </eventInfo>
+ <tooltip>Volume -</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ <rotation name="Reverse Portrait">
+ <display id="0">
+ <region left="78" top="117" width="720" height="1280"/>
+ </display>
+ <imageList>
+ <mainImage>default_180.png</mainImage>
+ <keyPressedImage>default_180_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="570" top="30" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>169</keyCode>
+ <keyName>Menu</keyName>
+ </eventInfo>
+ <tooltip>Menu</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="390" top="30" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>139</keyCode>
+ <keyName>Home</keyName>
+ </eventInfo>
+ <tooltip>Home</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="210" top="30" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>158</keyCode>
+ <keyName>Back</keyName>
+ </eventInfo>
+ <tooltip>Back</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="2" top="110" width="24" height="96" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="2" top="1310" width="24" height="96" update="true"/>
+ <eventInfo>
+ <keyCode>115</keyCode>
+ <keyName>Volume +</keyName>
+ </eventInfo>
+ <tooltip>Volume +</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="2" top="1200" width="24" height="96" update="true"/>
+ <eventInfo>
+ <keyCode>114</keyCode>
+ <keyName>Volume -</keyName>
+ </eventInfo>
+ <tooltip>Volume -</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ <rotation name="Reverse Landscape">
+ <display id="0">
+ <region left="117" top="67" width="1280" height="720"/>
+ </display>
+ <imageList>
+ <mainImage>default_R90.png</mainImage>
+ <keyPressedImage>default_R90_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="28" top="209" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>169</keyCode>
+ <keyName>Menu</keyName>
+ </eventInfo>
+ <tooltip>Menu</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="28" top="391" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>139</keyCode>
+ <keyName>Home</keyName>
+ </eventInfo>
+ <tooltip>Home</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="28" top="568" width="84" height="84"/>
+ <eventInfo>
+ <keyCode>158</keyCode>
+ <keyName>Back</keyName>
+ </eventInfo>
+ <tooltip>Back</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="109" top="841" width="96" height="24" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="1309" top="841" width="96" height="24" update="true"/>
+ <eventInfo>
+ <keyCode>115</keyCode>
+ <keyName>Volume +</keyName>
+ </eventInfo>
+ <tooltip>Volume +</tooltip>
+ </keyMap>
+ <keyMap>
+ <region left="1199" top="841" width="96" height="24" update="true"/>
+ <eventInfo>
+ <keyCode>114</keyCode>
+ <keyName>Volume -</keyName>
+ </eventInfo>
+ <tooltip>Volume -</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ </rotations>
+ <hover>
+ <color B="255" G="255" R="255" />
+ </hover>
+ <popupMenu>
+ <keywindowItem visible="false" />
+ <hostKeyboardItem visible="false" />
+ <ramdumpItem visible="false" />
+ </popupMenu>
+</EmulatorUI>
--- /dev/null
+skin.name=Phone 720x1280
+resolution.width=720
+resolution.height=1280
+manager.priority=3
--- /dev/null
+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 -"
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<RCC>
+ <qresource prefix="/">
+ <file>about.png</file>
+ <file>icons/emulator_icon.ico</file>
+ <file>icons/shell.png</file>
+ <file>icons/about.png</file>
+ <file>icons/advanced.png</file>
+ <file>icons/close.png</file>
+ <file>icons/force_close.png</file>
+ <file>icons/rotate.png</file>
+ <file>icons/scale.png</file>
+ <file>icons/control_panel.png</file>
+ <file>icons/detailed_info.png</file>
+ <file>icons/screen_shot.png</file>
+ <file>icons/host_keyboard.png</file>
+ <file>icons/save_screenshot_dialog.png</file>
+ <file>icons/copy_screenshot_dialog.png</file>
+ <file>icons/refresh_screenshot_dialog.png</file>
+ </qresource>
+</RCC>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<EmulatorUI xmlns="http://www.tizen.org/emulator/skin/dbi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <dbi_version>2.2</dbi_version>
+ <rotations>
+ <rotation name="Portrait">
+ <display id="0">
+ <region left="26" top="60" width="320" height="320"/>
+ </display>
+ <imageList>
+ <mainImage>default_0.png</mainImage>
+ <keyPressedImage>default_0_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="372" top="116" width="12" height="80" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ <rotation name="Landscape">
+ <display id="0">
+ <region left="60" top="38" width="320" height="320"/>
+ </display>
+ <imageList>
+ <mainImage>default_L90.png</mainImage>
+ <keyPressedImage>default_L90_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="116" top="0" width="80" height="12" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ <rotation name="Reverse Portrait">
+ <display id="0">
+ <region left="38" top="60" width="320" height="320"/>
+ </display>
+ <imageList>
+ <mainImage>default_180.png</mainImage>
+ <keyPressedImage>default_180_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="0" top="244" width="12" height="80" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ <rotation name="Reverse Landscape">
+ <display id="0">
+ <region left="60" top="26" width="320" height="320"/>
+ </display>
+ <imageList>
+ <mainImage>default_R90.png</mainImage>
+ <keyPressedImage>default_R90_p.png</keyPressedImage>
+ </imageList>
+ <keyMapList>
+ <keyMap>
+ <region left="244" top="372" width="80" height="12" update="true"/>
+ <eventInfo>
+ <keyCode>116</keyCode>
+ <keyName>Power</keyName>
+ </eventInfo>
+ <tooltip>Power</tooltip>
+ </keyMap>
+ </keyMapList>
+ </rotation>
+ </rotations>
+ <hover>
+ <color B="255" G="255" R="255" />
+ </hover>
+ <popupMenu>
+ <scaleItem visible="false" />
+ <keywindowItem visible="false" />
+ <hostKeyboardItem visible="false" />
+ <ramdumpItem visible="false" />
+ </popupMenu>
+</EmulatorUI>
--- /dev/null
+skin.name=Wearable 320x320
+resolution.width=320
+resolution.height=320
+manager.priority=1
--- /dev/null
+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"
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+#include <QGraphicsSceneMouseEvent>
+
+#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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QGraphicsPixmapItem>
+
+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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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("<span style=background-color:white><font color=black>"
+ + key->tooltip + "</font></span>");
+
+ 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QGraphicsRectItem>
+#include <QPainter>
+#include <QTimer>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+#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<HardwareKey *> 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");
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QGraphicsView>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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();
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QtWidgets>
+
+#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<MainForm *> mainFormList;
+ QList<ControllerForm *> 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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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;
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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();
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QApplication>
+#include <QDesktopWidget>
+#include <QScreen>
+#include <QRect>
+
+class UIUtil
+{
+public:
+ UIUtil();
+
+ static QRect getHostScreenBounds();
+};
+
+#endif // UIUTIL_H
--- /dev/null
+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 $@
+
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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;
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QObject>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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<FormType> FormListType::formList()
+{
+ return QQmlListProperty<FormType>(this, list);
+}
+
+QList<FormType *> *FormListType::getFormList()
+{
+ return &list;
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QObject>
+#include <QQmlListProperty>
+
+#include "formtype.h"
+
+class FormListType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<FormType> formList READ formList)
+ Q_CLASSINFO("DefaultProperty", "formList")
+
+public:
+ explicit FormListType(QObject *parent = 0);
+
+ QList<FormType *> *getFormList();
+
+private:
+ QQmlListProperty<FormType> formList();
+
+ QList<FormType *> list;
+};
+
+#endif // FORMLISTTYPE_H
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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();
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QObject>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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();
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QObject>
+
+#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
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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<HardwareKeyType> KeyListType::keyListType()
+{
+ return QQmlListProperty<HardwareKeyType>(this, list);
+}
+
+QList<HardwareKeyType *> *KeyListType::getKeyList()
+{
+ return &list;
+}
+
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QObject>
+#include <QQmlListProperty>
+
+#include "hardwarekeytype.h"
+
+class KeyListType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<HardwareKeyType> keyListType READ keyListType)
+ Q_CLASSINFO("DefaultProperty", "keyListType")
+
+public:
+ explicit KeyListType(QObject *parent = 0);
+
+ QList<HardwareKeyType *> *getKeyList();
+
+private:
+ QQmlListProperty<HardwareKeyType> keyListType();
+
+ QList<HardwareKeyType *> list;
+};
+
+#endif // KEYLISTTYPE_H
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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);
+}
--- /dev/null
+/*
+ * Qt UI
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * GiWoong Kim <giwoong.kim@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * 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 <QObject>
+#include <QRect>
+
+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
+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
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFANoRecovery,
kCGLPFAPBuffer,
0
};
kCGLPFAAlphaSize, 8,
kCGLPFADepthSize, 24,
kCGLPFAStencilSize, 8,
- kCGLPFANoRecovery,
kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core,
0
};
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)) {
"'%s' option", slots_str ? "maxmem" : "slots");
exit(EXIT_FAILURE);
}
+
+#ifdef CONFIG_MARU
+ set_emul_ram_size(optarg);
+#endif
break;
}
#ifdef CONFIG_TPM
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: {
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");
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",
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;
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;