screenshot: modified CopyToClipboard on Ubuntu 64bit 50/18850/1
authorGiWoong Kim <giwoong.kim@samsung.com>
Thu, 20 Mar 2014 06:39:07 +0000 (15:39 +0900)
committerGiWoong Kim <giwoong.kim@samsung.com>
Wed, 2 Apr 2014 05:46:43 +0000 (14:46 +0900)
On Ubuntu 12.04 64bit, SWT setContents function doesn't work
with image. Therefore, I replaced to GTK function using JNI.

Change-Id: Icf0b367d24654d4b704d84581bccf01723cb8518
Signed-off-by: GiWoong Kim <giwoong.kim@samsung.com>
tizen/src/Makefile
tizen/src/skin/client/build.xml
tizen/src/skin/client/native_src/check-gtk.sh [new file with mode: 0755]
tizen/src/skin/client/native_src/clipboard.c [new file with mode: 0644]
tizen/src/skin/client/src/org/tizen/emulator/skin/screenshot/ScreenShotDialog.java
tizen/src/skin/client/src/org/tizen/emulator/skin/util/SwtUtil.java

index 3124133..ee402e2 100644 (file)
@@ -123,7 +123,7 @@ ifdef CONFIG_DARWIN
        cp -pP sdbscript $(EMUL_DIR)/bin
 endif
 
-# use shared memory to display LCD
+# use shared memory for display framebuffer
 ifdef CONFIG_USE_SHM
 ifdef CONFIG_LINUX
        cp -pP skin/client/native_src/libshared.so $(EMUL_DIR)/bin
@@ -133,6 +133,11 @@ ifdef CONFIG_DARWIN
 endif
 endif
 
+# use GTK for CopyToClipboard on Ubuntu 12.04 64bit
+ifdef CONFIG_LINUX
+       cp -pP skin/client/native_src/libclipboard.so $(EMUL_DIR)/bin
+endif
+
 # change loading path of dynamic shared libraries on MAC OS X
 ifdef CONFIG_DARWIN
        install_name_tool -change /opt/local/lib/libgthread-2.0.*.dylib @loader_path/libgthread-2.0.0.dylib $(EMUL_DIR)/bin/qemu-img
@@ -227,7 +232,7 @@ ifdef CONFIG_DARWIN
        cp -pP sdbscript $(DIBS_COMMON_DIR)/bin
 endif
 
-# use shared memory to display LCD
+# use shared memory for display framebuffer
 ifdef CONFIG_USE_SHM
 ifdef CONFIG_LINUX
        cp -pP skin/client/native_src/libshared.so $(DIBS_COMMON_DIR)/bin
@@ -237,6 +242,11 @@ ifdef CONFIG_DARWIN
 endif
 endif
 
+# use GTK for CopyToClipboard on Ubuntu 12.04 64bit
+ifdef CONFIG_LINUX
+       cp -pP skin/client/native_src/libclipboard.so $(EMUL_DIR)/bin
+endif
+
 # change loading path of dynamic shared libraries on MAC OS X
 ifdef CONFIG_DARWIN
        install_name_tool -change /opt/local/lib/libgthread-2.0.*.dylib @loader_path/libgthread-2.0.0.dylib $(DIBS_COMMON_DIR)/bin/qemu-img
index 0880e75..b21c6ac 100644 (file)
@@ -1,6 +1,5 @@
 <?xml version="1.0" standalone="yes"?>
 <project name="emulator-skin" basedir="." default="make-jar">
-
        <condition property="isWindows">
                <os family="windows" />
        </condition>
                        <arg line="-o" />
                        <arg line="libshared.so" />
                </exec>
+
+               <exec dir="native_src" executable="./check-gtk.sh" outputproperty="gtkabi" failifexecutionfails="false" />
+               <echo message="gtkversion : ${gtkabi}" />
+
+               <javah classpath="build;lib/swt.jar" destdir="native_src">
+                       <class name="org.tizen.emulator.skin.screenshot.ScreenShotDialog" />
+               </javah>
+               <exec executable="pkg-config" outputproperty="gtk" failifexecutionfails="false">
+                       <arg line="--cflags" />
+                       <arg line="--libs" />
+                       <arg line="${gtkabi}" />
+               </exec>
+               <exec dir="native_src" executable="gcc" failifexecutionfails="false">
+                       <arg line="-c" />
+                       <arg line="-fPIC" />
+                       <arg line="clipboard.c" />
+                       <arg line="-o" />
+                       <arg line="clipboard.o" />
+                       <arg line="-I${env.JAVA_JNI_H_INCLUDE_PATH}" />
+                       <arg line="-I${env.JAVA_JNI_H_INCLUDE_PATH}/linux" />
+                       <arg line="${gtk}" />
+               </exec>
+               <exec dir="native_src" executable="gcc" failifexecutionfails="false">
+                       <arg line="clipboard.o" />
+                       <arg line="-shared" />
+                       <arg line="-o" />
+                       <arg line="libclipboard.so" />
+               </exec>
+
                <delete>
                        <fileset dir="native_src" includes="**/*.h" />
                </delete>
diff --git a/tizen/src/skin/client/native_src/check-gtk.sh b/tizen/src/skin/client/native_src/check-gtk.sh
new file mode 100755 (executable)
index 0000000..28f7d7a
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+GTK3="gtk+-3.0"
+GTK2="gtk+-2.0"
+
+pkg-config --exists $GTK3
+if [ "$?" = "0" ]
+then
+    echo $GTK3
+else
+    echo $GTK2
+fi
diff --git a/tizen/src/skin/client/native_src/clipboard.c b/tizen/src/skin/client/native_src/clipboard.c
new file mode 100644 (file)
index 0000000..8df8df3
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * Copy framebuffer to clipboard by JNI
+ *
+ * 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 <jni.h>
+#include <stdio.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include "org_tizen_emulator_skin_screenshot_ScreenShotDialog.h"
+
+JNIEXPORT jint JNICALL Java_org_tizen_emulator_skin_screenshot_ScreenShotDialog_copyToClipboard
+    (JNIEnv *env, jobject obj, jint width, jint height, jbyteArray pixels)
+{
+    int len = (*env)->GetArrayLength(env, pixels);
+    if (len <= 0) {
+        fprintf(stderr, "clipboard.c: failed to get length\n");
+        fflush(stderr);
+        return -1;
+    }
+
+    fprintf(stdout, "clipboard.c: copy to clipboard (%dx%d:%d)\n", width, height, len);
+    fflush(stdout);
+
+    GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
+    if (clipboard == NULL) {
+        fprintf(stderr, "clipboard.c: failed to get clipboard\n");
+        fflush(stderr);
+        return -1;
+    }
+
+    char *data = (char *)g_malloc(len);
+    if (data == NULL) {
+        fprintf(stderr, "clipboard.c: failed to g_malloc\n");
+        fflush(stderr);
+        return -1;
+    }
+    (*env)->GetByteArrayRegion(env, pixels, 0, len, data);
+
+    GdkPixbuf *image = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8,
+        width, height, width * 3, NULL, NULL);
+    if (image == NULL) {
+        fprintf(stderr, "clipboard.c: failed to get pixbuf\n");
+        fflush(stderr);
+
+        g_free(data);
+        return -1;
+    }
+
+    gtk_clipboard_set_image(clipboard, image);
+
+    g_object_unref(image);
+
+    return 0;
+}
+
index dcccacb..103a39c 100644 (file)
@@ -43,6 +43,7 @@ import java.util.logging.Logger;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.ScrolledComposite;
 import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.DND;
 import org.eclipse.swt.dnd.ImageTransfer;
 import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.events.MouseEvent;
@@ -68,6 +69,7 @@ import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
@@ -84,6 +86,7 @@ import org.tizen.emulator.skin.util.StringUtil;
 import org.tizen.emulator.skin.util.SwtUtil;
 
 public class ScreenShotDialog {
+       public static final String JNI_LIBRARY_FILE = "clipboard";
        private final static String DETAIL_SCREENSHOT_WINDOW_TITLE = "Screen Shot";
 
        private final static String DEFAULT_FILE_EXTENSION = "png";
@@ -95,6 +98,30 @@ public class ScreenShotDialog {
        private static Logger logger =
                        SkinLogger.getSkinLogger(ScreenShotDialog.class).getLogger();
 
+       static {
+               /* load JNI library file */
+               try {
+                       if (SwtUtil.isLinuxPlatform() == true &&
+                                       SwtUtil.is64bitPlatform() == true) {
+                               System.loadLibrary(JNI_LIBRARY_FILE);
+                       }
+               } catch (UnsatisfiedLinkError e) {
+                       logger.severe("Failed to load a " + JNI_LIBRARY_FILE + " file.\n" + e);
+
+                       Shell temp = new Shell(Display.getDefault());
+                       MessageBox messageBox = new MessageBox(temp, SWT.ICON_ERROR);
+                       messageBox.setText("Emulator");
+                       messageBox.setMessage(
+                                       "Failed to load a JNI library file from "
+                                       + System.getProperty("java.library.path") + ".\n\n" + e);
+                       messageBox.open();
+                       temp.dispose();
+               }
+       }
+
+       /* define JNI function */
+       public native int copyToClipboard(int width, int height, byte buf[]);
+
        protected EmulatorSkin skin;
        protected EmulatorConfig config;
        private Shell shell;
@@ -429,6 +456,8 @@ public class ScreenShotDialog {
                saveItem.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent e) {
+                               logger.info("Save menu is selected");
+
                                FileDialog fileDialog = new FileDialog(parent, SWT.SAVE);
                                fileDialog.setText("Save Image");
 
@@ -466,6 +495,8 @@ public class ScreenShotDialog {
                copyItem.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent e) {
+                               logger.info("CopyToClipboard menu is selected");
+
                                if (null == imageShot || imageShot.isDisposed()) {
                                        SkinUtil.openMessage(parent, null,
                                                        "Fail to copy to clipboard.", SWT.ICON_ERROR, config);
@@ -501,11 +532,24 @@ public class ScreenShotDialog {
 
                                ImageData pngData = new ImageData(
                                                new ByteArrayInputStream(bao.toByteArray()));
-                               Object[] imageObject = new Object[] { pngData };
 
-                               Transfer[] transfer = new Transfer[] { ImageTransfer.getInstance() };
-                               Clipboard clipboard = new Clipboard(parent.getDisplay());
-                               clipboard.setContents(imageObject, transfer);
+                               if (SwtUtil.isLinuxPlatform() == true &&
+                                               SwtUtil.is64bitPlatform() == true) {
+                                       /* use JNI for Ubuntu 12.04 64bit */
+                                       int result = copyToClipboard(
+                                                       pngData.width, pngData.height, pngData.data);
+                                       if (result < 0) {
+                                               DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+                                       }
+                               } else {
+                                       Object[] imageObject = new Object[] { pngData };
+
+                                       Transfer[] transfer = new Transfer[] { ImageTransfer.getInstance() };
+                                       Clipboard clipboard = new Clipboard(parent.getDisplay());
+                                       clipboard.setContents(imageObject, transfer);
+
+                                       clipboard.dispose();
+                               }
                        }
                });
 
@@ -519,6 +563,8 @@ public class ScreenShotDialog {
                refreshItem.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent e) {
+                               logger.info("Refresh menu is selected");
+
                                refreshItem.setEnabled(false);
 
                                parent.getDisplay().asyncExec(new Runnable() {
index 2b3e9aa..01bed42 100644 (file)
@@ -51,4 +51,17 @@ public class SwtUtil {
        public static boolean isMacPlatform() {
                return "cocoa".equalsIgnoreCase(SWT.getPlatform());
        }
+
+       public static boolean is64bitPlatform() {
+               /* internal/Library.java::arch() */
+               String osArch = System.getProperty("os.arch"); /* $NON-NLS-1$ */
+
+               if (osArch.equals("amd64") || osArch.equals("x86_64") ||
+                               osArch.equals("IA64W") || osArch.equals("ia64")) {
+                       /* $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ */
+                       return true;
+               }
+
+               return false;
+       }
 }