7d973230695fc8b787faac4a7617b3016d214f53
[sdk/emulator/qemu.git] / tizen / src / skin / client / src / org / tizen / emulator / skin / util / SkinUtil.java
1 /**
2  * 
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * GiWoong Kim <giwoong.kim@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  * HyunJun Son
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30 package org.tizen.emulator.skin.util;
31
32 import java.io.File;
33 import java.lang.reflect.Array;
34 import java.lang.reflect.Field;
35 import java.lang.reflect.InvocationTargetException;
36 import java.lang.reflect.Method;
37 import java.util.List;
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40
41 import org.eclipse.swt.graphics.Image;
42 import org.eclipse.swt.graphics.ImageData;
43 import org.eclipse.swt.graphics.Point;
44 import org.eclipse.swt.graphics.Rectangle;
45 import org.eclipse.swt.graphics.Region;
46 import org.eclipse.swt.widgets.MessageBox;
47 import org.eclipse.swt.widgets.Shell;
48 import org.tizen.emulator.skin.comm.ICommunicator.RotationInfo;
49 import org.tizen.emulator.skin.comm.ICommunicator.Scale;
50 import org.tizen.emulator.skin.config.EmulatorConfig;
51 import org.tizen.emulator.skin.config.EmulatorConfig.ArgsConstants;
52 import org.tizen.emulator.skin.config.EmulatorConfig.SkinPropertiesConstants;
53 import org.tizen.emulator.skin.dbi.EventInfoType;
54 import org.tizen.emulator.skin.dbi.KeyMapListType;
55 import org.tizen.emulator.skin.dbi.KeyMapType;
56 import org.tizen.emulator.skin.dbi.RegionType;
57 import org.tizen.emulator.skin.dbi.RotationType;
58 import org.tizen.emulator.skin.image.ImageRegistry;
59 import org.tizen.emulator.skin.image.ImageRegistry.ImageType;
60 import org.tizen.emulator.skin.layout.HWKey;
61 import org.tizen.emulator.skin.log.SkinLogger;
62
63
64 /**
65  * 
66  *
67  */
68 public class SkinUtil {
69
70         public static final String GTK_OS_CLASS = "org.eclipse.swt.internal.gtk.OS";
71         public static final String WIN32_OS_CLASS = "org.eclipse.swt.internal.win32.OS";
72         public static final String COCOA_OS_CLASS = "org.eclipse.swt.internal.cocoa.OS";
73
74         public static final int UNKNOWN_KEYCODE = -1;
75         public static final int SCALE_CONVERTER = 100;
76         public static final String EMULATOR_PREFIX = "emulator";
77
78         private static Logger logger =
79                         SkinLogger.getSkinLogger(SkinUtil.class).getLogger();
80
81         private SkinUtil() {
82                 /* do nothing */
83         }
84
85         public static String getVmName( EmulatorConfig config ) {
86                 
87                 String vmPath = config.getArg( ArgsConstants.VM_PATH );
88
89                 String regex = "";
90                 if ( SwtUtil.isWindowsPlatform() ) {
91                         regex = "\\" + File.separator;
92                 } else {
93                         regex = File.separator;
94                 }
95                 String[] split = StringUtil.nvl( vmPath ).split( regex );
96                 String vmName = split[split.length - 1];
97
98                 return vmName;
99                 
100         }
101         
102         public static String makeEmulatorName( EmulatorConfig config ) {
103
104                 String vmName = getVmName( config );
105
106                 if ( StringUtil.isEmpty( vmName ) ) {
107                         vmName = EMULATOR_PREFIX;
108                 }
109
110                 int portNumber = config.getArgInt( ArgsConstants.NET_BASE_PORT );
111                 return vmName + ":" + portNumber;
112
113         }
114
115         public static String getSdbPath() {
116                 String sdbPath = null;
117
118                 if (SwtUtil.isWindowsPlatform()) {
119                         sdbPath = ".\\..\\..\\ansicon.exe";
120                 } else {
121                         sdbPath = "./../../sdb";
122                 }
123
124                 return sdbPath;
125         }
126
127         public static List<KeyMapType> getHWKeyMapList(short rotationId) {
128                 RotationType rotation = SkinRotation.getRotation(rotationId);
129                 if (rotation == null) {
130                         return null;
131                 }
132
133                 KeyMapListType list = rotation.getKeyMapList();
134                 if (list == null) {
135                         /* try to using a KeyMapList of portrait */
136                         rotation = SkinRotation.getRotation(RotationInfo.PORTRAIT.id());
137                         if (rotation == null) {
138                                 return null;
139                         }
140
141                         list = rotation.getKeyMapList();
142                         if (list == null) {
143                                 return null;
144                         }
145                 }
146
147                 return list.getKeyMap();
148         }
149
150         public static HWKey getHWKey(
151                         int currentX, int currentY, short rotationId, int scale) {
152                 float convertedScale = convertScale(scale);
153
154                 List<KeyMapType> keyMapList = getHWKeyMapList(rotationId);
155                 if (keyMapList == null) {
156                         return null;
157                 }
158
159                 for (KeyMapType keyMap : keyMapList) {
160                         RegionType region = keyMap.getRegion();
161
162                         int scaledX = (int) (region.getLeft() * convertedScale);
163                         int scaledY = (int) (region.getTop() * convertedScale);
164                         int scaledWidth = (int) (region.getWidth() * convertedScale);
165                         int scaledHeight = (int) (region.getHeight() * convertedScale);
166
167                         if (isInGeometry(currentX, currentY, scaledX, scaledY, scaledWidth, scaledHeight)) {
168                                 EventInfoType eventInfo = keyMap.getEventInfo();
169
170                                 HWKey hwKey = new HWKey();
171                                 hwKey.setKeyCode(eventInfo.getKeyCode());
172                                 hwKey.setRegion(new SkinRegion(scaledX, scaledY, scaledWidth, scaledHeight));
173                                 hwKey.setTooltip(keyMap.getTooltip());
174
175                                 return hwKey;
176                         }
177                 }
178
179                 return null;
180         }
181
182         public static boolean isInGeometry( int currentX, int currentY, int targetX, int targetY, int targetWidth,
183                         int targetHeight ) {
184
185                 if ( ( currentX >= targetX ) && ( currentY >= targetY ) ) {
186                         if ( ( currentX <= ( targetX + targetWidth ) ) && ( currentY <= ( targetY + targetHeight ) ) ) {
187                                 return true;
188                         }
189                 }
190
191                 return false;
192
193         }
194
195         public static void trimShell( Shell shell, Image image ) {
196
197                 // trim transparent pixels in image. especially, corner round areas.
198
199                 if ( null == image ) {
200                         return;
201                 }
202
203                 ImageData imageData = image.getImageData();
204
205                 int width = imageData.width;
206                 int height = imageData.height;
207
208                 Region region = new Region();
209                 region.add( new Rectangle( 0, 0, width, height ) );
210
211                 for ( int i = 0; i < width; i++ ) {
212                         for ( int j = 0; j < height; j++ ) {
213                                 int alpha = imageData.getAlpha( i, j );
214                                 if ( 0 == alpha ) {
215                                         region.subtract( i, j, 1, 1 );
216                                 }
217                         }
218                 }
219
220                 shell.setRegion( region );
221
222         }
223
224         public static void trimShell(Shell shell, Image image,
225                         int left, int top, int width, int height) {
226
227                 if (null == image) {
228                         return;
229                 }
230
231                 ImageData imageData = image.getImageData();
232
233                 int right = left + width;
234                 int bottom = top + height;
235
236                 Region region = shell.getRegion();
237                 if (region == null) {
238                         return;
239                 }
240
241                 for (int i = left; i < right; i++) {
242                         for (int j = top; j < bottom; j++) {
243                                 int alpha = imageData.getAlpha(i, j);
244                                 if (0 == alpha) {
245                                         region.subtract(i, j, 1, 1);
246                                 } else {
247                                         region.add(i, j, 1, 1);
248                                 }
249                         }
250                 }
251
252                 shell.setRegion(region);
253         }
254
255         public static int[] convertMouseGeometry( int originalX, int originalY, int lcdWidth, int lcdHeight, int scale,
256                         int angle ) {
257
258                 float convertedScale = convertScale( scale );
259
260                 int x = (int) ( originalX * ( 1 / convertedScale ) );
261                 int y = (int) ( originalY * ( 1 / convertedScale ) );
262
263                 int rotatedX = x;
264                 int rotatedY = y;
265
266                 if ( RotationInfo.LANDSCAPE.angle() == angle ) {
267                         rotatedX = lcdWidth - y;
268                         rotatedY = x;
269                 } else if ( RotationInfo.REVERSE_PORTRAIT.angle() == angle ) {
270                         rotatedX = lcdWidth - x;
271                         rotatedY = lcdHeight - y;
272                 } else if ( RotationInfo.REVERSE_LANDSCAPE.angle() == angle ) {
273                         rotatedX = y;
274                         rotatedY = lcdHeight - x;
275                 }
276
277                 return new int[] { rotatedX, rotatedY };
278
279         }
280
281         public static Image createScaledImage( ImageRegistry imageRegistry, Shell shell, short rotationId, int scale,
282                         ImageType type ) {
283
284                 ImageData originalImageData = imageRegistry.getSkinImageData( rotationId, type );
285
286                 if ( null == originalImageData ) {
287                         return null;
288                 }
289
290                 ImageData imageData = (ImageData) originalImageData.clone();
291
292                 float convertedScale = convertScale( scale );
293
294                 int width = (int) ( originalImageData.width * convertedScale );
295                 int height = (int) ( originalImageData.height * convertedScale );
296                 imageData = imageData.scaledTo( width, height );
297
298                 Image image = new Image( shell.getDisplay(), imageData );
299                 return image;
300
301         }
302
303         public static float convertScale( int scale ) {
304                 return (float) scale / SCALE_CONVERTER;
305         }
306
307         public static int getValidScale( EmulatorConfig config ) {
308
309                 int storedScale = config.getSkinPropertyInt( SkinPropertiesConstants.WINDOW_SCALE,
310                                 EmulatorConfig.DEFAULT_WINDOW_SCALE );
311
312                 if ( !SkinUtil.isValidScale( storedScale ) ) {
313                         return EmulatorConfig.DEFAULT_WINDOW_SCALE;
314                 }else {
315                         return storedScale;
316                 }
317                 
318         }
319
320         public static boolean isValidScale( int scale ) {
321                 if ( Scale.SCALE_100.value() == scale || Scale.SCALE_75.value() == scale
322                 || Scale.SCALE_50.value() == scale || Scale.SCALE_25.value() == scale ) {
323                         return true;
324                 } else {
325                         return false;
326                 }
327         }
328
329         public static <T> int openMessage(Shell shell,
330                         String title, String message, int style, EmulatorConfig config) {
331                 MessageBox messageBox = new MessageBox(shell, style);
332
333                 if (!StringUtil.isEmpty(title)) {
334                         messageBox.setText(title);
335                 } else {
336                         messageBox.setText(makeEmulatorName(config));
337                 }
338
339                 messageBox.setMessage(StringUtil.nvl(message));
340                 return messageBox.open();
341         }
342
343         /* for java reflection */
344         private static Field getOSField(String field) {
345                 String className = "";
346
347                 if (SwtUtil.isLinuxPlatform()) {
348                         className = GTK_OS_CLASS;
349                 } else if (SwtUtil.isWindowsPlatform()) {
350                         className = WIN32_OS_CLASS;
351                 } else if (SwtUtil.isMacPlatform()) {
352                         className = COCOA_OS_CLASS;
353                 }
354
355                 Field f = null;
356                 try {
357                         f = Class.forName(className).getField(field);
358                 } catch (ClassNotFoundException e) {
359                         logger.log(Level.SEVERE, e.getMessage(), e);
360                 } catch (SecurityException e) {
361                         logger.log(Level.SEVERE, e.getMessage(), e);
362                 } catch (NoSuchFieldException e) {
363                         logger.log(Level.SEVERE, e.getMessage(), e);
364                 }
365
366                 return f;
367         }
368
369         private static Method getOSMethod(String method, Class<?>... parameterTypes) {
370                 String className = "";
371
372                 if (SwtUtil.isLinuxPlatform()) {
373                         className = GTK_OS_CLASS;
374                 } else if (SwtUtil.isWindowsPlatform()) {
375                         className = WIN32_OS_CLASS;
376                 } else if (SwtUtil.isMacPlatform()) {
377                         className = COCOA_OS_CLASS;
378                 }
379
380                 Method m = null;
381                 try {
382                         m = Class.forName(className).getMethod(method, parameterTypes);
383                 } catch (ClassNotFoundException e) {
384                         logger.log(Level.SEVERE, e.getMessage(), e);
385                 } catch (SecurityException e) {
386                         logger.log(Level.SEVERE, e.getMessage(), e);
387                 } catch (NoSuchMethodException e) {
388                         logger.log(Level.SEVERE, e.getMessage(), e);
389                 }
390
391                 return m;
392         }
393
394         private static Method getOSMethod(String method) {
395                 return getOSMethod(method, new Class<?>[] {});
396         }
397
398         private static Object invokeOSMethod(Method method, Object... args) {
399                 if (null == method) {
400                         return null;
401                 }
402
403                 try {
404                         return method.invoke(null, args);
405                 } catch (IllegalArgumentException e) {
406                         logger.log(Level.SEVERE, e.getMessage(), e);
407                 } catch (IllegalAccessException e) {
408                         logger.log(Level.SEVERE, e.getMessage(), e);
409                 } catch (InvocationTargetException e) {
410                         logger.log(Level.SEVERE, e.getMessage(), e);
411                 }
412
413                 return null;
414         }
415
416         private static Object invokeOSMethod(Method method) {
417                 return invokeOSMethod(method, new Object[] {});
418         }
419
420         private static boolean setTopMost32(Shell shell, boolean isOnTop) {
421
422                 if (SwtUtil.isLinuxPlatform()) {
423                         /* reference :
424                         http://wmctrl.sourcearchive.com/documentation/1.07/main_8c-source.html */
425
426                         /* if (!OS.GDK_WINDOWING_X11()) {
427                                 logger.warning("There is no x11 system.");
428                                 return;
429                         }
430
431                         int eventData0 = isOnTop ? 1 : 0; // 'add' or 'remove'
432                         int topHandle = 0;
433
434                         Method m = null;
435                         try {
436                                 m = Shell.class.getDeclaredMethod("topHandle", new Class<?>[] {});
437                                 m.setAccessible(true);
438                                 topHandle = (Integer) m.invoke( shell, new Object[] {});
439                         } catch (SecurityException ex) {
440                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
441                         } catch (NoSuchMethodException ex) {
442                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
443                         } catch (IllegalArgumentException ex) {
444                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
445                         } catch (IllegalAccessException ex) {
446                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
447                         } catch (InvocationTargetException ex) {
448                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
449                         }
450
451                         int xWindow = OS.gdk_x11_drawable_get_xid(
452                                         OS.GTK_WIDGET_WINDOW(topHandle));
453                         int xDisplay = OS.GDK_DISPLAY();
454
455                         byte[] messageBuffer = Converter.wcsToMbcs(null, "_NET_WM_STATE", true);
456                         int xMessageAtomType = OS.XInternAtom(xDisplay, messageBuffer, false);
457
458                         messageBuffer = Converter.wcsToMbcs(null, "_NET_WM_STATE_ABOVE", true);
459                         int xMessageAtomAbove = OS.XInternAtom(xDisplay, messageBuffer, false);
460
461                         XClientMessageEvent event = new XClientMessageEvent();
462                         event.type = OS.ClientMessage;
463                         event.window = xWindow;
464                         event.message_type = xMessageAtomType;
465                         event.format = 32;
466                         event.data[0] = eventData0;
467                         event.data[1] = xMessageAtomAbove;
468
469                         int clientEvent = OS.g_malloc(XClientMessageEvent.sizeof);
470                         OS.memmove(clientEvent, event, XClientMessageEvent.sizeof);
471                         int rootWin = OS.XDefaultRootWindow(xDisplay);
472                         // SubstructureRedirectMask : 1L<<20 | SubstructureNotifyMask : 1L<<19
473                         OS.XSendEvent(xDisplay, rootWin, false,
474                                         (int) ( 1L << 20 | 1L << 19 ), clientEvent);
475                         OS.g_free(clientEvent); */
476
477
478                         Boolean gdkWindowingX11 =
479                                         (Boolean) invokeOSMethod(getOSMethod("GDK_WINDOWING_X11"));
480                         if (null == gdkWindowingX11) {
481                                 logger.warning("GDK_WINDOWING_X11 returned null. There is no x11 system.");
482                                 return false;
483                         }
484
485                         int eventData0 = isOnTop ? 1 : 0; /* 'add' or 'remove' */
486                         int topHandle = 0;
487
488                         Method m = null;
489                         try {
490                                 m = Shell.class.getDeclaredMethod("topHandle", new Class<?>[] {});
491
492                                 m.setAccessible(true);
493                                 topHandle = (Integer) m.invoke(shell, new Object[] {});
494                         } catch (SecurityException ex) {
495                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
496                                 return false;
497                         } catch (NoSuchMethodException ex) {
498                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
499                                 return false;
500                         } catch (IllegalArgumentException ex) {
501                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
502                                 return false;
503                         } catch (IllegalAccessException ex) {
504                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
505                                 return false;
506                         } catch (InvocationTargetException ex ) {
507                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
508                                 return false;
509                         }
510
511                         Integer gtkWidgetWindow = (Integer) invokeOSMethod(
512                                         getOSMethod("GTK_WIDGET_WINDOW", int.class), topHandle);
513                         if (null == gtkWidgetWindow) {
514                                 logger.warning("GTK_WIDGET_WINDOW returned null");
515                                 return false;
516                         }
517
518                         Integer xWindow = (Integer) invokeOSMethod(
519                                         getOSMethod("gdk_x11_drawable_get_xid", int.class), gtkWidgetWindow);
520                         if (null == xWindow) {
521                                 logger.warning("gdk_x11_drawable_get_xid returned null");
522                                 return false;
523                         }
524
525                         Integer xDisplay = (Integer) invokeOSMethod(getOSMethod("GDK_DISPLAY"));
526                         if (null == xDisplay) {
527                                 logger.warning("GDK_DISPLAY returned null");
528                                 return false;
529                         }
530
531                         Method xInternAtom = getOSMethod(
532                                         "XInternAtom", int.class, byte[].class, boolean.class);
533
534                         Class<?> converterClass = null;
535                         try {
536                                 converterClass = Class.forName("org.eclipse.swt.internal.Converter");
537                         } catch (ClassNotFoundException ex) {
538                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
539                                 return false;
540                         }
541
542                         Method wcsToMbcs = null;
543                         byte[] messageBufferState = null;
544                         byte[] messageBufferAbove = null;
545
546                         try {
547                                 wcsToMbcs = converterClass.getMethod(
548                                                 "wcsToMbcs", String.class, String.class, boolean.class);
549                         } catch (SecurityException ex) {
550                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
551                                 return false;
552                         } catch (NoSuchMethodException ex) {
553                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
554                                 return false;
555                         }
556
557                         try {
558                                 messageBufferState =
559                                                 (byte[]) wcsToMbcs.invoke(null, null, "_NET_WM_STATE", true);
560                                 messageBufferAbove =
561                                                 (byte[]) wcsToMbcs.invoke(null, null, "_NET_WM_STATE_ABOVE", true);
562                         } catch (IllegalArgumentException ex) {
563                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
564                                 return false;
565                         } catch (IllegalAccessException ex) {
566                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
567                                 return false;
568                         } catch (InvocationTargetException ex) {
569                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
570                                 return false;
571                         }
572
573                         Integer xMessageAtomType =
574                                         (Integer) invokeOSMethod(xInternAtom, xDisplay, messageBufferState, false);
575                         if (null == xMessageAtomType) {
576                                 logger.warning("xMessageAtomType is null");
577                                 return false;
578                         }
579
580                         Integer xMessageAtomAbove =
581                                         (Integer) invokeOSMethod(xInternAtom, xDisplay, messageBufferAbove, false);
582                         if (null == xMessageAtomAbove) {
583                                 logger.warning("xMessageAtomAbove is null");
584                                 return false;
585                         }
586
587                         Class<?> eventClazz = null;
588                         Object event = null;
589                         try {
590                                 eventClazz = Class.forName("org.eclipse.swt.internal.gtk.XClientMessageEvent");
591                                 event = eventClazz.newInstance();
592                         } catch (InstantiationException ex) {
593                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
594                         } catch (IllegalAccessException ex) {
595                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
596                         } catch (ClassNotFoundException ex) {
597                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
598                         }
599
600                         if (null == eventClazz || null == event) {
601                                 return false;
602                         }
603
604                         Integer malloc = null;
605                         try {
606                                 Field type = eventClazz.getField("type");
607
608                                 Field clientMessageField = getOSField("ClientMessage");
609                                 if (null == clientMessageField) {
610                                         logger.warning("clientMessageField is null");
611                                         return false;
612                                 }
613                                 type.set(event, clientMessageField.get(null));
614
615                                 Field window = eventClazz.getField("window");
616                                 window.set(event, xWindow);
617                                 Field messageType = eventClazz.getField("message_type");
618                                 messageType.set(event, xMessageAtomType);
619                                 Field format = eventClazz.getField("format");
620                                 format.set(event, 32);
621
622                                 Object data = Array.newInstance(int.class, 5);
623                                 Array.setInt(data, 0, eventData0);
624                                 Array.setInt(data, 1, xMessageAtomAbove);
625                                 Array.setInt(data, 2, 0);
626                                 Array.setInt(data, 3, 0);
627                                 Array.setInt(data, 4, 0);
628
629                                 Field dataField = eventClazz.getField("data");
630                                 dataField.set(event, data);
631
632                                 Field sizeofField = eventClazz.getField("sizeof");
633                                 Integer sizeof = (Integer) sizeofField.get(null);
634
635                                 Method gMalloc = getOSMethod("g_malloc", int.class);
636                                 malloc = (Integer) invokeOSMethod(gMalloc, sizeof);
637
638                                 Method memmove =
639                                                 getOSMethod("memmove", int.class, eventClazz, int.class);
640                                 invokeOSMethod(memmove, malloc, event, sizeof);
641
642                         } catch (NoSuchFieldException ex) {
643                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
644                                 return false;
645                         } catch (IllegalAccessException ex) {
646                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
647                                 return false;
648                         }
649
650                         Method xDefaultRootWindow =
651                                         getOSMethod("XDefaultRootWindow", int.class);
652                         Integer rootWin =
653                                         (Integer) invokeOSMethod(xDefaultRootWindow, xDisplay);
654
655                         Method xSendEvent = getOSMethod("XSendEvent",
656                                         int.class, int.class, boolean.class, int.class, int.class);
657
658                         /* SubstructureRedirectMask : 1L<<20 | SubstructureNotifyMask : 1L<<19 */
659                         invokeOSMethod(xSendEvent, xDisplay, rootWin,
660                                         false, (int) (1L << 20 | 1L << 19), malloc);
661                         invokeOSMethod(getOSMethod("g_free", int.class), malloc);
662
663                 } else if (SwtUtil.isWindowsPlatform()) {
664                         Point location = shell.getLocation();
665
666                         /* int hWndInsertAfter = 0;
667                         if (isOnTop) {
668                                 hWndInsertAfter = OS.HWND_TOPMOST;
669                         } else {
670                                 hWndInsertAfter = OS.HWND_NOTOPMOST;
671                         }
672                         OS.SetWindowPos(shell.handle,
673                                         hWndInsertAfter, location.x, location.y, 0, 0, OS.SWP_NOSIZE); */
674
675                         int hWndInsertAfter = 0;
676                         int noSize = 0;
677
678                         try {
679                                 if (isOnTop) {
680                                         Field topMost = getOSField("HWND_TOPMOST");
681                                         if (null == topMost) {
682                                                 logger.warning("topMost is null");
683                                                 return false;
684                                         }
685
686                                         hWndInsertAfter = topMost.getInt(null);
687                                 } else {
688                                         Field noTopMost = getOSField("HWND_NOTOPMOST");
689                                         if (null == noTopMost) {
690                                                 logger.warning("HWND_NOTOPMOST is null");
691                                                 return false;
692                                         }
693
694                                         hWndInsertAfter = noTopMost.getInt(null);
695                                 }
696
697                                 Field noSizeField = getOSField("SWP_NOSIZE");
698                                 if (null == noSizeField) {
699                                         logger.warning("SWP_NOSIZE is null");
700                                         return false;
701                                 }
702
703                                 noSize = noSizeField.getInt(null);
704
705                         } catch (IllegalArgumentException ex) {
706                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
707                                 return false;
708                         } catch (IllegalAccessException ex) {
709                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
710                                 return false;
711                         }
712
713                         Method m = getOSMethod("SetWindowPos",
714                                         int.class, int.class, int.class,
715                                         int.class, int.class, int.class, int.class);
716
717                         /* org.eclipse.swt.widgets.Shell */
718                         int shellHandle = 0;
719                         try {
720                                 Field field = shell.getClass().getField("handle");
721                                 shellHandle = field.getInt(shell);
722                                 logger.info("shell.handle:" + shellHandle);
723                         } catch (IllegalArgumentException e) {
724                                 logger.log(Level.SEVERE, e.getMessage(), e);
725                                 return false;
726                         } catch (IllegalAccessException e) {
727                                 logger.log(Level.SEVERE, e.getMessage(), e);
728                                 return false;
729                         } catch (SecurityException e) {
730                                 logger.log(Level.SEVERE, e.getMessage(), e);
731                                 return false;
732                         } catch (NoSuchFieldException e) {
733                                 logger.log(Level.SEVERE, e.getMessage(), e);
734                                 return false;
735                         }
736
737                         invokeOSMethod(m, shellHandle, hWndInsertAfter,
738                                         location.x, location.y, 0, 0, noSize);
739                 } else if (SwtUtil.isMacPlatform()) {
740                         /* do nothing */
741                         logger.warning("not supported yet");
742                         return false;
743                 }
744
745                 return true;
746         }
747
748         private static boolean setTopMost64(Shell shell, boolean isOnTop) {
749
750                 if (SwtUtil.isLinuxPlatform()) {
751                         Boolean gdkWindowingX11 =
752                                         (Boolean) invokeOSMethod(getOSMethod("GDK_WINDOWING_X11"));
753                         if (null == gdkWindowingX11) {
754                                 logger.warning("GDK_WINDOWING_X11 returned null. There is no x11 system.");
755                                 return false;
756                         }
757
758                         int eventData0 = isOnTop ? 1 : 0; /* 'add' or 'remove' */
759                         long topHandle = 0;
760
761                         Method m = null;
762                         try {
763                                 m = Shell.class.getDeclaredMethod("topHandle", new Class<?>[] {});
764
765                                 m.setAccessible(true);
766                                 topHandle = (Long) m.invoke(shell, new Object[] {});
767                         } catch (SecurityException ex) {
768                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
769                                 return false;
770                         } catch (NoSuchMethodException ex) {
771                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
772                                 return false;
773                         } catch (IllegalArgumentException ex) {
774                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
775                                 return false;
776                         } catch (IllegalAccessException ex) {
777                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
778                                 return false;
779                         } catch (InvocationTargetException ex) {
780                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
781                                 return false;
782                         }
783
784                         Long gtkWidgetWindow = (Long) invokeOSMethod(
785                                         getOSMethod("GTK_WIDGET_WINDOW", long.class), topHandle);
786                         if (null == gtkWidgetWindow) {
787                                 logger.warning("GTK_WIDGET_WINDOW returned null");
788                                 return false;
789                         }
790
791                         Long xWindow = (Long) invokeOSMethod(
792                                         getOSMethod("gdk_x11_drawable_get_xid", long.class), gtkWidgetWindow);
793                         if (null == xWindow) {
794                                 logger.warning("gdk_x11_drawable_get_xid returned null");
795                                 return false;
796                         }
797
798                         Long xDisplay = (Long) invokeOSMethod( getOSMethod("GDK_DISPLAY"));
799                         if (null == xDisplay) {
800                                 logger.warning("GDK_DISPLAY returned null");
801                                 return false;
802                         }
803
804                         Method xInternAtom = getOSMethod(
805                                         "XInternAtom", long.class, byte[].class, boolean.class);
806
807                         Class<?> converterClass = null;
808                         try {
809                                 converterClass = Class.forName("org.eclipse.swt.internal.Converter");
810                         } catch (ClassNotFoundException ex) {
811                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
812                                 return false;
813                         }
814
815                         Method wcsToMbcs = null;
816                         byte[] messageBufferState = null;
817                         byte[] messageBufferAbove = null;
818
819                         try {
820                                 wcsToMbcs = converterClass.getMethod(
821                                                 "wcsToMbcs", String.class, String.class, boolean.class);
822                         } catch (SecurityException ex) {
823                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
824                                 return false;
825                         } catch (NoSuchMethodException ex) {
826                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
827                                 return false;
828                         }
829
830                         try {
831                                 messageBufferState =
832                                                 (byte[]) wcsToMbcs.invoke(null, null, "_NET_WM_STATE", true);
833                                 messageBufferAbove =
834                                                 (byte[]) wcsToMbcs.invoke(null, null, "_NET_WM_STATE_ABOVE", true);
835                         } catch (IllegalArgumentException ex) {
836                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
837                                 return false;
838                         } catch (IllegalAccessException ex) {
839                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
840                                 return false;
841                         } catch (InvocationTargetException ex) {
842                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
843                                 return false;
844                         }
845
846                         Long xMessageAtomType =
847                                         (Long) invokeOSMethod(xInternAtom, xDisplay, messageBufferState, false);
848                         if (null == xMessageAtomType) {
849                                 logger.warning("xMessageAtomType is null");
850                                 return false;
851                         }
852
853                         Long xMessageAtomAbove =
854                                         (Long) invokeOSMethod(xInternAtom, xDisplay, messageBufferAbove, false);
855                         if (null == xMessageAtomAbove) {
856                                 logger.warning("xMessageAtomAbove is null");
857                                 return false;
858                         }
859
860                         Class<?> eventClazz = null;
861                         Object event = null;
862                         try {
863                                 eventClazz = Class.forName("org.eclipse.swt.internal.gtk.XClientMessageEvent");
864                                 event = eventClazz.newInstance();
865                         } catch (InstantiationException ex) {
866                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
867                         } catch (IllegalAccessException ex) {
868                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
869                         } catch (ClassNotFoundException ex) {
870                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
871                         }
872
873                         if (null == eventClazz || null == event) {
874                                 return false;
875                         }
876
877                         Long malloc = null;
878                         try {
879                                 Field type = eventClazz.getField("type");
880
881                                 Field clientMessageField = getOSField("ClientMessage");
882                                 if (null == clientMessageField) {
883                                         logger.warning("clientMessageField is null");
884                                         return false;
885                                 }
886                                 type.set(event, clientMessageField.get(null));
887
888                                 Field window = eventClazz.getField("window");
889                                 window.set(event, xWindow);
890                                 Field messageType = eventClazz.getField("message_type");
891                                 messageType.set(event, xMessageAtomType);
892                                 Field format = eventClazz.getField("format");
893                                 format.set(event, 32);
894
895                                 Object data = Array.newInstance(long.class, 5);
896                                 Array.setLong(data, 0, eventData0);
897                                 Array.setLong(data, 1, xMessageAtomAbove);
898                                 Array.setLong(data, 2, 0);
899                                 Array.setLong(data, 3, 0);
900                                 Array.setLong(data, 4, 0);
901
902                                 Field dataField = eventClazz.getField("data");
903                                 dataField.set(event, data);
904
905                                 Field sizeofField = eventClazz.getField("sizeof");
906                                 Integer sizeof = (Integer) sizeofField.get(null);
907
908                                 Method gMalloc = getOSMethod("g_malloc", long.class);
909                                 malloc = (Long) invokeOSMethod(gMalloc, sizeof.longValue());
910
911                                 Method memmove =
912                                                 getOSMethod("memmove", long.class, eventClazz, long.class);
913                                 invokeOSMethod(memmove, malloc, event, sizeof.longValue());
914
915                         } catch (NoSuchFieldException ex) {
916                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
917                                 return false;
918                         } catch (IllegalAccessException ex) {
919                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
920                                 return false;
921                         }
922
923                         Method xDefaultRootWindow =
924                                         getOSMethod("XDefaultRootWindow", long.class);
925                         Long rootWin =
926                                         (Long) invokeOSMethod(xDefaultRootWindow, xDisplay);
927
928                         Method xSendEvent = getOSMethod("XSendEvent", long.class, long.class, boolean.class,
929                                         long.class, long.class);
930
931                         /*  ubstructureRedirectMask : 1L<<20 | SubstructureNotifyMask : 1L<<19 */
932                         invokeOSMethod(xSendEvent, xDisplay, rootWin,
933                                         false, (long) (1L << 20 | 1L << 19), malloc);
934                         invokeOSMethod(getOSMethod("g_free", long.class), malloc);
935                 } else if (SwtUtil.isWindowsPlatform()) {
936                         Point location = shell.getLocation();
937
938                         long hWndInsertAfter = 0;
939                         int noSize = 0;
940
941                         try {
942                                 if (isOnTop) {
943                                         Field topMost = getOSField("HWND_TOPMOST");
944                                         if (null == topMost) {
945                                                 logger.warning("topMost is null");
946                                                 return false;
947                                         }
948
949                                         hWndInsertAfter = topMost.getLong(null);
950                                 } else {
951                                         Field noTopMost = getOSField("HWND_NOTOPMOST");
952                                         if (null == noTopMost) {
953                                                 logger.warning("noTopMost is null");
954                                                 return false;
955                                         }
956
957                                         hWndInsertAfter = noTopMost.getLong(null);
958                                 }
959
960                                 Field noSizeField = getOSField("SWP_NOSIZE");
961                                 if (null == noSizeField) {
962                                         logger.warning("SWP_NOSIZE is null");
963                                         return false;
964                                 }
965
966                                 noSize = noSizeField.getInt(null);
967
968                         } catch (IllegalArgumentException ex) {
969                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
970                                 return false;
971                         } catch (IllegalAccessException ex) {
972                                 logger.log(Level.SEVERE, ex.getMessage(), ex);
973                                 return false;
974                         }
975
976                         Method m = getOSMethod("SetWindowPos",
977                                         long.class, long.class, int.class,
978                                         int.class, int.class, int.class, int.class);
979
980                         /* org.eclipse.swt.widgets.Shell */
981                         long shellHandle = 0;
982                         try {
983                                 Field field = shell.getClass().getField("handle");
984                                 shellHandle = field.getLong(shell);
985                                 logger.info("shell.handle:" + shellHandle);
986                         } catch (IllegalArgumentException e) {
987                                 logger.log(Level.SEVERE, e.getMessage(), e);
988                                 return false;
989                         } catch (IllegalAccessException e) {
990                                 logger.log(Level.SEVERE, e.getMessage(), e);
991                                 return false;
992                         } catch (SecurityException e) {
993                                 logger.log(Level.SEVERE, e.getMessage(), e);
994                                 return false;
995                         } catch (NoSuchFieldException e) {
996                                 logger.log(Level.SEVERE, e.getMessage(), e);
997                                 return false;
998                         }
999
1000                         invokeOSMethod(m, shellHandle, hWndInsertAfter,
1001                                         location.x, location.y, 0, 0, noSize);
1002                 } else if (SwtUtil.isMacPlatform()) {
1003                         /* do nothing */
1004                         logger.warning("not supported yet");
1005                         return false;
1006                 }
1007
1008                 return true;
1009         }
1010
1011         public static boolean setTopMost(Shell shell, boolean isOnTop) {
1012                 if (shell == null) {
1013                         return false;
1014                 }
1015
1016                 /* internal/Library.java::arch() */
1017                 String osArch = System.getProperty("os.arch"); /* $NON-NLS-1$ */
1018
1019                 if (osArch.equals("amd64") || osArch.equals("x86_64") ||
1020                                 osArch.equals("IA64W") || osArch.equals("ia64")) {
1021                         /* $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ */
1022                         logger.info("64bit architecture : " + osArch);
1023
1024                         return setTopMost64(shell, isOnTop); /* 64bit */
1025                 }
1026
1027                 logger.info("32bit architecture : " + osArch);
1028                 return setTopMost32(shell, isOnTop); /* 32bit */
1029         }
1030 }