304 if (env->ExceptionCheck()) return JNI_ERR; 305 306 clazz = env->FindClass("com/sun/glass/ui/gtk/GtkApplication"); 307 if (env->ExceptionCheck()) return JNI_ERR; 308 jApplicationCls = (jclass) env->NewGlobalRef(clazz); 309 jApplicationDisplay = env->GetStaticFieldID(jApplicationCls, "display", "J"); 310 if (env->ExceptionCheck()) return JNI_ERR; 311 jApplicationScreen = env->GetStaticFieldID(jApplicationCls, "screen", "I"); 312 if (env->ExceptionCheck()) return JNI_ERR; 313 jApplicationVisualID = env->GetStaticFieldID(jApplicationCls, "visualID", "J"); 314 if (env->ExceptionCheck()) return JNI_ERR; 315 jApplicationReportException = env->GetStaticMethodID( 316 jApplicationCls, "reportException", "(Ljava/lang/Throwable;)V"); 317 if (env->ExceptionCheck()) return JNI_ERR; 318 jApplicationGetApplication = env->GetStaticMethodID( 319 jApplicationCls, "GetApplication", "()Lcom/sun/glass/ui/Application;"); 320 if (env->ExceptionCheck()) return JNI_ERR; 321 jApplicationGetName = env->GetMethodID(jApplicationCls, "getName", "()Ljava/lang/String;"); 322 if (env->ExceptionCheck()) return JNI_ERR; 323 324 // Before doing anything with GTK we validate that the DISPLAY can be opened 325 display = XOpenDisplay(NULL); 326 if (display != NULL) { 327 XCloseDisplay(display); 328 displayValid = JNI_TRUE; 329 } else { 330 // Invalid DISPLAY, skip initialization 331 return JNI_VERSION_1_6; 332 } 333 334 return JNI_VERSION_1_6; 335 } 336 337 void 338 glass_throw_exception(JNIEnv * env, 339 const char * exceptionClass, 340 const char * exceptionMessage) { 341 jclass throwableClass = env->FindClass(exceptionClass); 342 if (check_and_clear_exception(env)) return; 343 env->ThrowNew(throwableClass, exceptionMessage); 344 check_and_clear_exception(env); 345 } 346 347 int 348 glass_throw_oom(JNIEnv * env, const char * message) { 349 glass_throw_exception(env, "java/lang/OutOfMemoryError", message); 350 // must return a non-zero value, see HANDLE_MEM_ALLOC_ERROR 351 return 1; 352 } 353 483 484 for (guint i = 0; i < size; ++i) { 485 if (!g_str_has_prefix(uris[i], FILE_PREFIX) 486 && !g_str_has_prefix(uris[i], URI_LIST_COMMENT_PREFIX)) { 487 g_string_append(str, uris[i]); 488 g_string_append(str, URI_LIST_LINE_BREAK); 489 } 490 } 491 492 if (str->len > 2) { 493 g_string_erase(str, str->len - 2, 2); 494 } 495 496 result = env->NewStringUTF(str->str); 497 check_and_clear_exception(env); 498 499 g_string_free(str, TRUE); 500 } 501 g_strfreev(uris); 502 return result; 503 } | 304 if (env->ExceptionCheck()) return JNI_ERR; 305 306 clazz = env->FindClass("com/sun/glass/ui/gtk/GtkApplication"); 307 if (env->ExceptionCheck()) return JNI_ERR; 308 jApplicationCls = (jclass) env->NewGlobalRef(clazz); 309 jApplicationDisplay = env->GetStaticFieldID(jApplicationCls, "display", "J"); 310 if (env->ExceptionCheck()) return JNI_ERR; 311 jApplicationScreen = env->GetStaticFieldID(jApplicationCls, "screen", "I"); 312 if (env->ExceptionCheck()) return JNI_ERR; 313 jApplicationVisualID = env->GetStaticFieldID(jApplicationCls, "visualID", "J"); 314 if (env->ExceptionCheck()) return JNI_ERR; 315 jApplicationReportException = env->GetStaticMethodID( 316 jApplicationCls, "reportException", "(Ljava/lang/Throwable;)V"); 317 if (env->ExceptionCheck()) return JNI_ERR; 318 jApplicationGetApplication = env->GetStaticMethodID( 319 jApplicationCls, "GetApplication", "()Lcom/sun/glass/ui/Application;"); 320 if (env->ExceptionCheck()) return JNI_ERR; 321 jApplicationGetName = env->GetMethodID(jApplicationCls, "getName", "()Ljava/lang/String;"); 322 if (env->ExceptionCheck()) return JNI_ERR; 323 324 return JNI_VERSION_1_6; 325 } 326 327 void 328 glass_throw_exception(JNIEnv * env, 329 const char * exceptionClass, 330 const char * exceptionMessage) { 331 jclass throwableClass = env->FindClass(exceptionClass); 332 if (check_and_clear_exception(env)) return; 333 env->ThrowNew(throwableClass, exceptionMessage); 334 check_and_clear_exception(env); 335 } 336 337 int 338 glass_throw_oom(JNIEnv * env, const char * message) { 339 glass_throw_exception(env, "java/lang/OutOfMemoryError", message); 340 // must return a non-zero value, see HANDLE_MEM_ALLOC_ERROR 341 return 1; 342 } 343 473 474 for (guint i = 0; i < size; ++i) { 475 if (!g_str_has_prefix(uris[i], FILE_PREFIX) 476 && !g_str_has_prefix(uris[i], URI_LIST_COMMENT_PREFIX)) { 477 g_string_append(str, uris[i]); 478 g_string_append(str, URI_LIST_LINE_BREAK); 479 } 480 } 481 482 if (str->len > 2) { 483 g_string_erase(str, str->len - 2, 2); 484 } 485 486 result = env->NewStringUTF(str->str); 487 check_and_clear_exception(env); 488 489 g_string_free(str, TRUE); 490 } 491 g_strfreev(uris); 492 return result; 493 } 494 495 //*************************************************************************** 496 497 typedef struct _DeviceGrabContext { 498 GdkWindow * window; 499 gboolean grabbed; 500 } DeviceGrabContext; 501 502 gboolean disableGrab = FALSE; 503 static gboolean configure_transparent_window(GtkWidget *window); 504 static void configure_opaque_window(GtkWidget *window); 505 506 static void grab_mouse_device(GdkDevice *device, DeviceGrabContext *context); 507 static void ungrab_mouse_device(GdkDevice *device); 508 509 gint glass_gdk_visual_get_depth (GdkVisual * visual) 510 { 511 // gdk_visual_get_depth is GTK 2.2 + 512 return gdk_visual_get_depth(visual); 513 } 514 515 GdkScreen * glass_gdk_window_get_screen(GdkWindow * gdkWindow) 516 { 517 #ifdef GLASS_GTK3 518 GdkVisual * gdkVisual = gdk_window_get_visual(gdkWindow); 519 return gdk_visual_get_screen(gdkVisual); 520 #else 521 return gdk_window_get_screen(gdkWindow); 522 #endif 523 } 524 525 gboolean 526 glass_gdk_mouse_devices_grab(GdkWindow *gdkWindow) { 527 #ifdef GLASS_GTK3 528 if (disableGrab) { 529 return TRUE; 530 } 531 DeviceGrabContext context; 532 GList *devices = gdk_device_manager_list_devices ( 533 gdk_display_get_device_manager( 534 gdk_display_get_default()), 535 GDK_DEVICE_TYPE_MASTER); 536 537 context.window = gdkWindow; 538 context.grabbed = FALSE; 539 g_list_foreach(devices, (GFunc) grab_mouse_device, &context); 540 541 return context.grabbed; 542 #else 543 return glass_gdk_mouse_devices_grab_with_cursor(gdkWindow, NULL, TRUE); 544 #endif 545 } 546 547 gboolean 548 glass_gdk_mouse_devices_grab_with_cursor(GdkWindow *gdkWindow, GdkCursor *cursor, gboolean owner_events) { 549 if (disableGrab) { 550 return TRUE; 551 } 552 GdkGrabStatus status = gdk_pointer_grab(gdkWindow, owner_events, (GdkEventMask) 553 (GDK_POINTER_MOTION_MASK 554 | GDK_POINTER_MOTION_HINT_MASK 555 | GDK_BUTTON_MOTION_MASK 556 | GDK_BUTTON1_MOTION_MASK 557 | GDK_BUTTON2_MOTION_MASK 558 | GDK_BUTTON3_MOTION_MASK 559 | GDK_BUTTON_PRESS_MASK 560 | GDK_BUTTON_RELEASE_MASK), 561 NULL, cursor, GDK_CURRENT_TIME); 562 563 return (status == GDK_GRAB_SUCCESS) ? TRUE : FALSE; 564 } 565 566 void 567 glass_gdk_mouse_devices_ungrab() { 568 #ifdef GLASS_GTK3 569 GList *devices = gdk_device_manager_list_devices( 570 gdk_display_get_device_manager( 571 gdk_display_get_default()), 572 GDK_DEVICE_TYPE_MASTER); 573 g_list_foreach(devices, (GFunc) ungrab_mouse_device, NULL); 574 #else 575 gdk_pointer_ungrab(GDK_CURRENT_TIME); 576 #endif 577 } 578 579 void 580 glass_gdk_master_pointer_grab(GdkWindow *window, GdkCursor *cursor) { 581 if (disableGrab) { 582 gdk_window_set_cursor(window, cursor); 583 return; 584 } 585 #ifdef GLASS_GTK3 586 gdk_device_grab(gdk_device_manager_get_client_pointer( 587 gdk_display_get_device_manager( 588 gdk_display_get_default())), 589 window, GDK_OWNERSHIP_NONE, FALSE, GDK_ALL_EVENTS_MASK, 590 cursor, GDK_CURRENT_TIME); 591 #else 592 gdk_pointer_grab(window, FALSE, (GdkEventMask) 593 (GDK_POINTER_MOTION_MASK 594 | GDK_BUTTON_MOTION_MASK 595 | GDK_BUTTON1_MOTION_MASK 596 | GDK_BUTTON2_MOTION_MASK 597 | GDK_BUTTON3_MOTION_MASK 598 | GDK_BUTTON_RELEASE_MASK), 599 NULL, cursor, GDK_CURRENT_TIME); 600 #endif 601 } 602 603 void 604 glass_gdk_master_pointer_ungrab() { 605 #ifdef GLASS_GTK3 606 gdk_device_ungrab(gdk_device_manager_get_client_pointer( 607 gdk_display_get_device_manager( 608 gdk_display_get_default())), 609 GDK_CURRENT_TIME); 610 #else 611 gdk_pointer_ungrab(GDK_CURRENT_TIME); 612 #endif 613 } 614 615 void 616 glass_gdk_master_pointer_get_position(gint *x, gint *y) { 617 #ifdef GLASS_GTK3 618 gdk_device_get_position(gdk_device_manager_get_client_pointer( 619 gdk_display_get_device_manager( 620 gdk_display_get_default())), 621 NULL, x, y); 622 #else 623 gdk_display_get_pointer(gdk_display_get_default(), NULL, x, y, NULL); 624 #endif 625 } 626 627 gboolean 628 glass_gdk_device_is_grabbed(GdkDevice *device) { 629 #ifdef GLASS_GTK3 630 return gdk_display_device_is_grabbed(gdk_display_get_default(), device); 631 #else 632 (void) device; 633 return gdk_display_pointer_is_grabbed(gdk_display_get_default()); 634 #endif 635 } 636 637 void 638 glass_gdk_device_ungrab(GdkDevice *device) { 639 #ifdef GLASS_GTK3 640 gdk_device_ungrab(device, GDK_CURRENT_TIME); 641 #else 642 (void) device; 643 gdk_pointer_ungrab(GDK_CURRENT_TIME); 644 #endif 645 } 646 647 GdkWindow * 648 glass_gdk_device_get_window_at_position(GdkDevice *device, gint *x, gint *y) { 649 #ifdef GLASS_GTK3 650 return gdk_device_get_window_at_position(device, x, y); 651 #else 652 (void) device; 653 return gdk_display_get_window_at_pointer(gdk_display_get_default(), x, y); 654 #endif 655 } 656 657 void 658 glass_gtk_configure_transparency_and_realize(GtkWidget *window, 659 gboolean transparent) { 660 #ifdef GLASS_GTK3 661 gboolean isTransparent = glass_configure_window_transparency(window, transparent); 662 gtk_widget_realize(window); 663 if (isTransparent) { 664 GdkRGBA rgba = { 1.0, 1.0, 1.0, 0.0 }; 665 gdk_window_set_background_rgba(gtk_widget_get_window(window), &rgba); 666 } 667 #else 668 glass_configure_window_transparency(window, transparent); 669 gtk_widget_realize(window); 670 #endif 671 } 672 673 void 674 glass_gtk_window_configure_from_visual(GtkWidget *widget, GdkVisual *visual) { 675 glass_widget_set_visual(widget, visual); 676 } 677 678 static gboolean 679 configure_transparent_window(GtkWidget *window) { 680 GdkScreen *default_screen = gdk_screen_get_default(); 681 GdkDisplay *default_display = gdk_display_get_default(); 682 683 #ifdef GLASS_GTK3 684 GdkVisual *visual = gdk_screen_get_rgba_visual(default_screen); 685 if (visual 686 && gdk_display_supports_composite(default_display) 687 && gdk_screen_is_composited(default_screen)) { 688 glass_widget_set_visual(window, visual); 689 return TRUE; 690 } 691 #else 692 GdkColormap *colormap = gdk_screen_get_rgba_colormap(default_screen); 693 if (colormap 694 && gdk_display_supports_composite(default_display) 695 && gdk_screen_is_composited(default_screen)) { 696 gtk_widget_set_colormap(window, colormap); 697 return TRUE; 698 } 699 #endif 700 701 return FALSE; 702 } 703 704 void 705 glass_gdk_window_get_size(GdkWindow *window, gint *w, gint *h) { 706 *w = gdk_window_get_width(window); 707 *h = gdk_window_get_height(window); 708 } 709 710 void 711 glass_gdk_display_get_pointer(GdkDisplay* display, gint* x, gint *y) { 712 #ifdef GLASS_GTK3 713 gdk_device_get_position( 714 gdk_device_manager_get_client_pointer( 715 gdk_display_get_device_manager(display)), NULL , x, y); 716 #else 717 gdk_display_get_pointer(display, NULL, x, y, NULL); 718 #endif 719 } 720 721 722 const guchar* 723 glass_gtk_selection_data_get_data_with_length( 724 GtkSelectionData * selectionData, 725 gint * length) { 726 if (selectionData == NULL) { 727 return NULL; 728 } 729 730 *length = gtk_selection_data_get_length(selectionData); 731 return gtk_selection_data_get_data(selectionData); 732 } 733 734 static void 735 configure_opaque_window(GtkWidget *window) { 736 (void) window; 737 /* We need to pick a visual that really is glx compatible 738 * instead of using the default visual 739 * 740 CHECK_LOAD_SYMBOL_GDK (gdk_screen_get_system_visual); 741 CHECK_LOAD_SYMBOL_GDK (gdk_screen_get_default); 742 glass_widget_set_visual(window, 743 gdk_screen_get_system_visual( 744 gdk_screen_get_default())); 745 */ 746 } 747 748 gboolean 749 glass_configure_window_transparency(GtkWidget *window, gboolean transparent) { 750 if (transparent) { 751 if (configure_transparent_window(window)) { 752 return TRUE; 753 } 754 755 fprintf(stderr,"Can't create transparent stage, because your screen doesn't" 756 " support alpha channel." 757 " You need to enable XComposite extension.\n"); 758 fflush(stderr); 759 } 760 761 configure_opaque_window(window); 762 return FALSE; 763 } 764 765 static void 766 grab_mouse_device(GdkDevice *device, DeviceGrabContext *context) { 767 GdkInputSource source = gdk_device_get_source(device); 768 if (source == GDK_SOURCE_MOUSE) { 769 #ifdef GLASS_GTK3 770 GdkGrabStatus status = gdk_device_grab(device, 771 context->window, 772 GDK_OWNERSHIP_NONE, 773 TRUE, 774 GDK_ALL_EVENTS_MASK, 775 NULL, 776 GDK_CURRENT_TIME); 777 #else 778 GdkGrabStatus status = GDK_GRAB_SUCCESS; 779 /* FIXME reachable by 2? 780 GdkGrabStatus status = gdk_device_grab(device, 781 context->window, 782 GDK_OWNERSHIP_NONE, 783 TRUE, 784 GDK_ALL_EVENTS_MASK, 785 NULL, 786 GDK_CURRENT_TIME); 787 */ 788 #endif 789 if (status == GDK_GRAB_SUCCESS) { 790 context->grabbed = TRUE; 791 } 792 } 793 } 794 795 static void 796 ungrab_mouse_device(GdkDevice *device) { 797 #ifdef GLASS_GTK3 798 GdkInputSource source = gdk_device_get_source(device); 799 if (source == GDK_SOURCE_MOUSE) { 800 gdk_device_ungrab(device, GDK_CURRENT_TIME); 801 } 802 #else 803 // not used on the GTK2 path 804 #endif 805 } 806 807 GdkPixbuf * 808 glass_pixbuf_from_window(GdkWindow *window, 809 gint srcx, gint srcy, 810 gint width, gint height) 811 { 812 GdkPixbuf * ret = NULL; 813 814 #ifdef GLASS_GTK3 815 ret = gdk_pixbuf_get_from_window (window, srcx, srcy, width, height); 816 #else 817 ret = gdk_pixbuf_get_from_drawable (NULL, 818 window, 819 NULL, 820 srcx, srcy, 821 0, 0, 822 width, height); 823 #endif 824 return ret; 825 } 826 827 void 828 glass_window_apply_shape_mask(GdkWindow *window, 829 void* data, uint width, uint height) 830 { 831 #ifdef GLASS_GTK3 832 cairo_surface_t * shape = cairo_image_surface_create_for_data( 833 (unsigned char *)data, 834 CAIRO_FORMAT_ARGB32, 835 width, height, 836 width * 4 837 ); 838 cairo_region_t *region = gdk_cairo_region_create_from_surface (shape); 839 840 gdk_window_shape_combine_region (window, region, 0, 0); 841 842 gdk_window_input_shape_combine_region (window, region, 0, 0); 843 844 cairo_region_destroy(region); 845 cairo_surface_finish (shape); 846 #else 847 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data((guchar *) data, 848 GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, NULL, NULL); 849 850 if (GDK_IS_PIXBUF(pixbuf)) { 851 GdkBitmap* mask = NULL; 852 gdk_pixbuf_render_pixmap_and_mask(pixbuf, NULL, &mask, 128); 853 854 gdk_window_input_shape_combine_mask(window, mask, 0, 0); 855 856 g_object_unref(pixbuf); 857 if (mask) { 858 g_object_unref(mask); 859 } 860 } 861 #endif 862 } 863 864 void 865 glass_window_reset_input_shape_mask(GdkWindow *window) 866 { 867 #ifdef GLASS_GTK3 868 gdk_window_input_shape_combine_region(window, NULL, 0, 0); 869 #else 870 gdk_window_input_shape_combine_mask(window, NULL, 0, 0); 871 #endif 872 } 873 874 GdkWindow * 875 glass_gdk_drag_context_get_dest_window (GdkDragContext * context) 876 { 877 return ((context != NULL) ? gdk_drag_context_get_dest_window(context) : NULL); 878 } 879 880 881 void glass_gdk_x11_display_set_window_scale (GdkDisplay *display, 882 gint scale) 883 { 884 #ifdef GLASS_GTK3 885 // Optional call, if it does not exist then GTK3 is not yet 886 // doing automatic scaling of coordinates so we do not need 887 // to override it. CHECK_LOAD_SYMBOL_GDK_OPT will simply 888 // return if the symbol was not found. 889 gdk_x11_display_set_window_scale(display, scale); // since 3.10 890 #else 891 (void) display; 892 (void) scale; 893 #endif 894 } 895 896 //-------- Glass utility ---------------------------------------- 897 898 void 899 glass_widget_set_visual(GtkWidget *widget, GdkVisual *visual) 900 { 901 #ifdef GLASS_GTK3 902 gtk_widget_set_visual (widget, visual); 903 #else 904 GdkColormap *colormap = gdk_colormap_new(visual, TRUE); 905 gtk_widget_set_colormap (widget, colormap); 906 #endif 907 } 908 909 guint glass_settings_get_guint_opt (const gchar *schema_name, 910 const gchar *key_name, 911 int defval) 912 { 913 GSettingsSchemaSource *default_schema_source = 914 g_settings_schema_source_get_default(); 915 if (default_schema_source == NULL) { 916 if (gtk_verbose) { 917 fprintf(stderr, "No schema source dir found!\n"); 918 } 919 return defval; 920 } 921 GSettingsSchema *the_schema = 922 g_settings_schema_source_lookup(default_schema_source, schema_name, TRUE); 923 if (the_schema == NULL) { 924 if (gtk_verbose) { 925 fprintf(stderr, "schema '%s' not found!\n", schema_name); 926 } 927 return defval; 928 } 929 if (!g_settings_schema_has_key(the_schema, key_name)) { 930 if (gtk_verbose) { 931 fprintf(stderr, "key '%s' not found in schema '%s'!\n", key_name, schema_name); 932 } 933 return defval; 934 } 935 if (gtk_verbose) { 936 fprintf(stderr, "found schema '%s' and key '%s'\n", schema_name, key_name); 937 } 938 GSettings *gset = g_settings_new(schema_name); 939 return g_settings_get_uint(gset, key_name); 940 } |