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