< prev index next >

modules/graphics/src/main/native-glass/gtk/glass_window.cpp

Print this page




   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 #include "glass_window.h"
  26 #include "glass_general.h"
  27 #include "glass_gtkcompat.h"
  28 #include "glass_key.h"
  29 #include "glass_screen.h"
  30 #include "glass_dnd.h"
  31 
  32 #include <com_sun_glass_events_WindowEvent.h>
  33 #include <com_sun_glass_events_ViewEvent.h>
  34 #include <com_sun_glass_events_MouseEvent.h>
  35 #include <com_sun_glass_events_KeyEvent.h>
  36 
  37 #include <com_sun_glass_ui_Window_Level.h>
  38 
  39 #include <X11/extensions/shape.h>
  40 #include <cairo.h>
  41 #include <cairo-xlib.h>
  42 #include <gdk/gdkx.h>
  43 #include <gdk/gdk.h>
  44 




  45 #include <string.h>
  46 
  47 #include <algorithm>
  48 
  49 WindowContext * WindowContextBase::sm_grab_window = NULL;
  50 WindowContext * WindowContextBase::sm_mouse_drag_window = NULL;
  51 
  52 GdkAtom atom_net_wm_state = gdk_atom_intern_static_string("_NET_WM_STATE");
  53 
  54 GdkWindow* WindowContextBase::get_gdk_window(){
  55     return gdk_window;
  56 }
  57 
  58 jobject WindowContextBase::get_jview() {
  59     return jview;
  60 }
  61 
  62 jobject WindowContextBase::get_jwindow() {
  63     return jwindow;
  64 }
  65 
  66 bool WindowContextBase::isEnabled() {
  67     if (jwindow) {
  68         bool result = (JNI_TRUE == mainEnv->CallBooleanMethod(jwindow, jWindowIsEnabled));
  69         LOG_EXCEPTION(mainEnv)
  70         return result;
  71     } else {
  72         return false;
  73     }


 336 
 337     if (jview) {
 338         mainEnv->CallVoidMethod(jview, jViewNotifyMouse,
 339                 isDrag ? com_sun_glass_events_MouseEvent_DRAG : com_sun_glass_events_MouseEvent_MOVE,
 340                 button,
 341                 (jint) event->x, (jint) event->y,
 342                 (jint) event->x_root, (jint) event->y_root,
 343                 glass_modifier,
 344                 JNI_FALSE,
 345                 JNI_FALSE);
 346         CHECK_JNI_EXCEPTION(mainEnv)
 347     }
 348 }
 349 
 350 void WindowContextBase::process_mouse_scroll(GdkEventScroll* event) {
 351     jdouble dx = 0;
 352     jdouble dy = 0;
 353 
 354     // converting direction to change in pixels
 355     switch (event->direction) {





 356         case GDK_SCROLL_UP:
 357             dy = 1;
 358             break;
 359         case GDK_SCROLL_DOWN:
 360             dy = -1;
 361             break;
 362         case GDK_SCROLL_LEFT:
 363             dx = 1;
 364             break;
 365         case GDK_SCROLL_RIGHT:
 366             dx = -1;
 367             break;
 368     }
 369 
 370     if (jview) {
 371         mainEnv->CallVoidMethod(jview, jViewNotifyScroll,
 372                 (jint) event->x, (jint) event->y,
 373                 (jint) event->x_root, (jint) event->y_root,
 374                 dx, dy,
 375                 gdk_modifier_mask_to_glass(event->state),


 401                     JNI_FALSE);
 402             CHECK_JNI_EXCEPTION(mainEnv)
 403         }
 404     }
 405 }
 406 
 407 void WindowContextBase::process_key(GdkEventKey* event) {
 408     bool press = event->type == GDK_KEY_PRESS;
 409     jint glassKey = get_glass_key(event);
 410     jint glassModifier = gdk_modifier_mask_to_glass(event->state);
 411     if (press) {
 412         glassModifier |= glass_key_to_modifier(glassKey);
 413     } else {
 414         glassModifier &= ~glass_key_to_modifier(glassKey);
 415     }
 416     jcharArray jChars = NULL;
 417     jchar key = gdk_keyval_to_unicode(event->keyval);
 418     if (key >= 'a' && key <= 'z' && (event->state & GDK_CONTROL_MASK)) {
 419         key = key - 'a' + 1; // map 'a' to ctrl-a, and so on.
 420     } else {
 421         key = glass_gtk_fixup_typed_key(key, event->keyval);














 422     }
 423 
 424     if (key > 0) {
 425         jChars = mainEnv->NewCharArray(1);
 426         if (jChars) {
 427             mainEnv->SetCharArrayRegion(jChars, 0, 1, &key);
 428             CHECK_JNI_EXCEPTION(mainEnv)
 429         }
 430     } else {
 431         jChars = mainEnv->NewCharArray(0);
 432     }
 433     if (jview) {
 434         if (press) {
 435             mainEnv->CallVoidMethod(jview, jViewNotifyKey,
 436                     com_sun_glass_events_KeyEvent_PRESS,
 437                     glassKey,
 438                     jChars,
 439                     glassModifier);
 440             CHECK_JNI_EXCEPTION(mainEnv)
 441 


 447                         glassModifier);
 448                 CHECK_JNI_EXCEPTION(mainEnv)
 449             }
 450         } else {
 451             mainEnv->CallVoidMethod(jview, jViewNotifyKey,
 452                     com_sun_glass_events_KeyEvent_RELEASE,
 453                     glassKey,
 454                     jChars,
 455                     glassModifier);
 456             CHECK_JNI_EXCEPTION(mainEnv)
 457         }
 458     }
 459 }
 460 
 461 void WindowContextBase::paint(void* data, jint width, jint height)
 462 {
 463     if (!is_visible()) {
 464         return;
 465     }
 466 





 467     cairo_t* context;
 468     context = gdk_cairo_create(GDK_DRAWABLE(gdk_window));
 469 
 470     cairo_surface_t* cairo_surface;
 471     cairo_surface = cairo_image_surface_create_for_data(
 472             (unsigned char*)data,
 473             CAIRO_FORMAT_ARGB32,
 474             width, height, width * 4);
 475 
 476     applyShapeMask(data, width, height);
 477 
 478     cairo_set_source_surface(context, cairo_surface, 0, 0);

 479     cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
 480     cairo_paint(context);




 481 
 482     cairo_destroy(context);
 483     cairo_surface_destroy(cairo_surface);
 484 }
 485 
 486 void WindowContextBase::add_child(WindowContextTop* child) {
 487     children.insert(child);
 488     gtk_window_set_transient_for(child->get_gtk_window(), this->get_gtk_window());
 489 }
 490 
 491 void WindowContextBase::remove_child(WindowContextTop* child) {
 492     children.erase(child);
 493     gtk_window_set_transient_for(child->get_gtk_window(), NULL);
 494 }
 495 
 496 void WindowContextBase::show_or_hide_children(bool show) {
 497     std::set<WindowContextTop*>::iterator it;
 498     for (it = children.begin(); it != children.end(); ++it) {
 499         (*it)->set_visible(show);
 500         (*it)->show_or_hide_children(show);
 501     }
 502 }
 503 
 504 void WindowContextBase::reparent_children(WindowContext* parent) {
 505     std::set<WindowContextTop*>::iterator it;
 506     for (it = children.begin(); it != children.end(); ++it) {
 507         (*it)->set_owner(parent);
 508         parent->add_child(*it);
 509     }
 510     children.clear();
 511 }
 512 
 513 void WindowContextBase::set_visible(bool visible) {
 514     if (visible) {
 515         gtk_widget_show_all(gtk_widget);
 516     } else {
 517         gtk_widget_hide(gtk_widget);
 518         if (jview && is_mouse_entered) {
 519             is_mouse_entered = false;


 582 
 583 void WindowContextBase::ungrab_focus() {
 584     if (!WindowContextBase::sm_mouse_drag_window) {
 585         glass_gdk_mouse_devices_ungrab();
 586     }
 587     WindowContextBase::sm_grab_window = NULL;
 588 
 589     if (jwindow) {
 590         mainEnv->CallVoidMethod(jwindow, jWindowNotifyFocusUngrab);
 591         CHECK_JNI_EXCEPTION(mainEnv)
 592     }
 593 }
 594 
 595 void WindowContextBase::set_cursor(GdkCursor* cursor) {
 596     if (!is_in_drag()) {
 597         if (WindowContextBase::sm_mouse_drag_window) {
 598             glass_gdk_mouse_devices_grab_with_cursor(
 599                     WindowContextBase::sm_mouse_drag_window->get_gdk_window(), cursor, FALSE);
 600         } else if (WindowContextBase::sm_grab_window) {
 601             glass_gdk_mouse_devices_grab_with_cursor(
 602                     WindowContextBase::sm_grab_window->get_gdk_window(), cursor);
 603         }
 604     }
 605     gdk_window_set_cursor(gdk_window, cursor);
 606 }
 607 
 608 void WindowContextBase::set_background(float r, float g, float b) {







 609     GdkColor color;
 610     color.red   = (guint16) (r * 65535);
 611     color.green = (guint16) (g * 65535);
 612     color.blue  = (guint16) (b * 65535);
 613     gtk_widget_modify_bg(gtk_widget, GTK_STATE_NORMAL, &color);

 614 }
 615 
 616 WindowContextBase::~WindowContextBase() {
 617     if (xim.ic) {
 618         XDestroyIC(xim.ic);
 619         xim.ic = NULL;
 620     }
 621     if (xim.im) {
 622         XCloseIM(xim.im);
 623         xim.im = NULL;
 624     }
 625 
 626     gtk_widget_destroy(gtk_widget);
 627 }
 628 
 629 ////////////////////////////// WindowContextTop /////////////////////////////////
 630 
 631 
 632 WindowContextTop::WindowContextTop(jobject _jwindow, WindowContext* _owner, long _screen,
 633         WindowFrameType _frame_type, WindowType type, GdkWMFunction wmf) :
 634             WindowContextBase(),
 635             screen(_screen),
 636             frame_type(_frame_type),
 637             owner(_owner),
 638             geometry(),
 639             stale_config_notifications(),
 640             resizable(),
 641             frame_extents_initialized(),
 642             map_received(false),
 643             location_assigned(false),
 644             size_assigned(false),
 645             on_top(false)
 646 {
 647     jwindow = mainEnv->NewGlobalRef(_jwindow);
 648 
 649     gtk_widget =  gtk_window_new(type == POPUP ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
 650 
 651     if (gchar* app_name = get_application_name()) {
 652         gtk_window_set_wmclass(GTK_WINDOW(gtk_widget), app_name, app_name);
 653         g_free(app_name);
 654     }
 655 
 656     if (owner) {
 657         owner->add_child(this);
 658         if (on_top_inherited()) {
 659             gtk_window_set_keep_above(GTK_WINDOW(gtk_widget), TRUE);


 702 // Applied to a temporary full screen window to prevent sending events to Java
 703 void WindowContextTop::detach_from_java() {
 704     if (jview) {
 705         mainEnv->DeleteGlobalRef(jview);
 706         jview = NULL;
 707     }
 708     if (jwindow) {
 709         mainEnv->DeleteGlobalRef(jwindow);
 710         jwindow = NULL;
 711     }
 712 }
 713 
 714 static GdkAtom
 715 get_net_frame_extents_atom() {
 716     static const char * extents_str = "_NET_FRAME_EXTENTS";
 717     return gdk_atom_intern(extents_str, TRUE);
 718 }
 719 
 720 void
 721 WindowContextTop::request_frame_extents() {
 722     Display *display = GDK_WINDOW_XDISPLAY(gdk_window);
 723     Atom rfeAtom = XInternAtom(display, "_NET_REQUEST_FRAME_EXTENTS", True);
 724     if (rfeAtom != None) {
 725         XClientMessageEvent clientMessage;
 726         memset(&clientMessage, 0, sizeof(clientMessage));
 727 
 728         clientMessage.type = ClientMessage;
 729         clientMessage.window = GDK_WINDOW_XID(gdk_window);
 730         clientMessage.message_type = rfeAtom;
 731         clientMessage.format = 32;
 732 
 733         XSendEvent(display, XDefaultRootWindow(display), False,
 734                    SubstructureRedirectMask | SubstructureNotifyMask,
 735                    (XEvent *) &clientMessage);
 736         XFlush(display);
 737     }
 738 }
 739 
 740 void WindowContextTop::activate_window() {
 741     Display *display = GDK_WINDOW_XDISPLAY(gdk_window);
 742     Atom navAtom = XInternAtom(display, "_NET_ACTIVE_WINDOW", True);
 743     if (navAtom != None) {
 744         XClientMessageEvent clientMessage;
 745         memset(&clientMessage, 0, sizeof(clientMessage));
 746 
 747         clientMessage.type = ClientMessage;
 748         clientMessage.window = GDK_WINDOW_XID(gdk_window);
 749         clientMessage.message_type = navAtom;
 750         clientMessage.format = 32;
 751         clientMessage.data.l[0] = 1;
 752         clientMessage.data.l[1] = gdk_x11_get_server_time(gdk_window);
 753         clientMessage.data.l[2] = 0;
 754 
 755         XSendEvent(display, XDefaultRootWindow(display), False,
 756                    SubstructureRedirectMask | SubstructureNotifyMask,
 757                    (XEvent *) &clientMessage);
 758         XFlush(display);
 759     }
 760 }
 761 


 780             gdk_atom_intern("CARDINAL", FALSE),
 781             0,
 782             sizeof (unsigned long) * 4,
 783             FALSE,
 784             NULL,
 785             NULL,
 786             NULL,
 787             (guchar**) & extents)) {
 788         *left = extents [0];
 789         *right = extents [1];
 790         *top = extents [2];
 791         *bottom = extents [3];
 792 
 793         g_free(extents);
 794         return true;
 795     }
 796 
 797     return false;
 798 }
 799 
 800 
 801 static int geometry_get_window_width(const WindowGeometry *windowGeometry) {
 802      return (windowGeometry->final_width.type != BOUNDSTYPE_WINDOW)
 803                    ? windowGeometry->final_width.value
 804                          + windowGeometry->extents.left
 805                          + windowGeometry->extents.right
 806                    : windowGeometry->final_width.value;
 807 }
 808 
 809 static int geometry_get_window_height(const WindowGeometry *windowGeometry) {
 810     return (windowGeometry->final_height.type != BOUNDSTYPE_WINDOW)
 811                    ? windowGeometry->final_height.value
 812                          + windowGeometry->extents.top
 813                          + windowGeometry->extents.bottom
 814                    : windowGeometry->final_height.value;
 815 }
 816 
 817 static int geometry_get_content_width(WindowGeometry *windowGeometry) {
 818     return (windowGeometry->final_width.type != BOUNDSTYPE_CONTENT)
 819                    ? windowGeometry->final_width.value
 820                          - windowGeometry->extents.left


 852     if (windowGeometry->gravity_x != 0) {
 853         newValue += geometry_get_window_width(windowGeometry)
 854                 * windowGeometry->gravity_x;
 855     }
 856     windowGeometry->refx = newValue;
 857 }
 858 
 859 static void geometry_set_window_y(WindowGeometry *windowGeometry, int value) {
 860     float newValue = value;
 861     if (windowGeometry->gravity_y != 0) {
 862         newValue += geometry_get_window_height(windowGeometry)
 863                 * windowGeometry->gravity_y;
 864     }
 865     windowGeometry->refy = newValue;
 866 }
 867 
 868 void WindowContextTop::process_net_wm_property() {
 869     // Workaround for https://bugs.launchpad.net/unity/+bug/998073
 870 
 871     static GdkAtom atom_atom = gdk_atom_intern_static_string("ATOM");

 872     static GdkAtom atom_net_wm_state_hidden = gdk_atom_intern_static_string("_NET_WM_STATE_HIDDEN");
 873     static GdkAtom atom_net_wm_state_above = gdk_atom_intern_static_string("_NET_WM_STATE_ABOVE");
 874 
 875     gint length;
 876 
 877     glong* atoms = NULL;
 878 
 879     if (gdk_property_get(gdk_window, atom_net_wm_state, atom_atom,
 880             0, G_MAXLONG, FALSE, NULL, NULL, &length, (guchar**) &atoms)) {
 881 
 882         bool is_hidden = false;
 883         bool is_above = false;
 884         for (gint i = 0; i < (gint)(length / sizeof(glong)); i++) {
 885             if (atom_net_wm_state_hidden == (GdkAtom)atoms[i]) {
 886                 is_hidden = true;
 887             } else if (atom_net_wm_state_above == (GdkAtom)atoms[i]) {
 888                 is_above = true;
 889             }
 890         }
 891 
 892         g_free(atoms);
 893 
 894         if (is_iconified != is_hidden) {
 895             is_iconified = is_hidden;
 896 
 897             notify_state((is_hidden)
 898                     ? com_sun_glass_events_WindowEvent_MINIMIZE
 899                     : com_sun_glass_events_WindowEvent_RESTORE);
 900         }
 901 
 902         notify_on_top(is_above);
 903     }
 904 }
 905 
 906 void WindowContextTop::process_property_notify(GdkEventProperty* event) {


 907     if (event->atom == atom_net_wm_state && event->window == gdk_window) {
 908         process_net_wm_property();
 909     } else if (event->atom == get_net_frame_extents_atom() &&
 910             event->window == gdk_window) {
 911         int top, left, bottom, right;
 912         if (get_frame_extents_property(&top, &left, &bottom, &right)) {
 913             int oldX = geometry_get_window_x(&geometry);
 914             int oldY = geometry_get_window_y(&geometry);
 915             int oldWidth = geometry_get_content_width(&geometry);
 916             int oldHeight = geometry_get_content_height(&geometry);
 917 
 918             bool updateWindowConstraints = geometry.extents.top != top
























 919                     || geometry.extents.left != left
 920                     || geometry.extents.bottom != bottom
 921                     || geometry.extents.right != right;
 922 
 923             geometry.extents.top = top;
 924             geometry.extents.left = left;
 925             geometry.extents.bottom = bottom;
 926             geometry.extents.right = right;
 927 
 928             if (updateWindowConstraints) {
 929                 update_window_constraints();
 930             }
 931 
 932             XWindowChanges windowChanges;
 933             unsigned int windowChangesMask = 0;
 934 
 935             int newX = geometry_get_window_x(&geometry);
 936             int newY = geometry_get_window_y(&geometry);
 937             int newWidth = geometry_get_content_width(&geometry);
 938             int newHeight = geometry_get_content_height(&geometry);
 939 
 940             if (oldX != newX) {
 941                 windowChanges.x = newX;
 942                 windowChangesMask |= CWX;
 943             }
 944 
 945             if (oldY != newY) {
 946                 windowChanges.y = newY;
 947                 windowChangesMask |= CWY;
 948             }
 949 
 950             if (oldWidth != newWidth) {
 951                 windowChanges.width = newWidth;
 952                 windowChangesMask |= CWWidth;
 953             }
 954 
 955             if (oldHeight != newHeight) {
 956                 windowChanges.height = newHeight;
 957                 windowChangesMask |= CWHeight;
 958             }
 959 
 960             window_configure(&windowChanges, windowChangesMask);
 961 
 962             if (jview) {
 963                 mainEnv->CallVoidMethod(jview, jViewNotifyView, com_sun_glass_events_ViewEvent_MOVE);
 964                 CHECK_JNI_EXCEPTION(mainEnv)
 965             }
 966         }
 967     }
 968 }
 969 
 970 void WindowContextTop::process_configure(GdkEventConfigure* event) {
 971 
 972     geometry.current_width = event->width + geometry.extents.left
 973                                            + geometry.extents.right;
 974     geometry.current_height = event->height + geometry.extents.top
 975                                              + geometry.extents.bottom;
 976     gint x, y;
 977     if (gtk_window_get_decorated(GTK_WINDOW(gtk_widget))) {
 978         gtk_window_get_position(GTK_WINDOW(gtk_widget), &x, &y);
 979     } else {
 980         x = event->x;
 981         y = event->y;


 982     }
 983 
 984     if (stale_config_notifications == 0) {
 985         if ((geometry_get_content_width(&geometry) != event->width)
 986                 || (geometry_get_content_height(&geometry) != event->height)) {
 987             geometry.final_width.value = event->width;



 988             geometry.final_width.type = BOUNDSTYPE_CONTENT;
 989             geometry.final_height.value = event->height;
 990             geometry.final_height.type = BOUNDSTYPE_CONTENT;
 991         }
 992         geometry_set_window_x(&geometry, x);
 993         geometry_set_window_y(&geometry, y);
 994     } else {
 995         --stale_config_notifications;
 996     }
 997     if (jview) {
 998         mainEnv->CallVoidMethod(jview, jViewNotifyResize,
 999                 event->width,
1000                 event->height);
1001         CHECK_JNI_EXCEPTION(mainEnv)



1002     }

1003     if (jwindow) {
1004         mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize,
1005                 (is_maximized)
1006                     ? com_sun_glass_events_WindowEvent_MAXIMIZE
1007                     : com_sun_glass_events_WindowEvent_RESIZE,
1008                 geometry.current_width,
1009                 geometry.current_height);
1010         CHECK_JNI_EXCEPTION(mainEnv)
1011 
1012         mainEnv->CallVoidMethod(jwindow, jWindowNotifyMove, x, y);
1013         CHECK_JNI_EXCEPTION(mainEnv)
1014     }
1015 
1016     glong to_screen = getScreenPtrForLocation(x, y);
1017     if (to_screen != -1) {
1018         if (to_screen != screen) {
1019             if (jwindow) {
1020                 //notify screen changed
1021                 jobject jScreen = createJavaScreen(mainEnv, to_screen);
1022                 mainEnv->CallVoidMethod(jwindow, jWindowNotifyMoveToAnotherScreen, jScreen);
1023                 CHECK_JNI_EXCEPTION(mainEnv)
1024             }
1025             screen = to_screen;
1026         }
1027     }
1028 
1029     if (resizable.request != REQUEST_NONE) {
1030         set_window_resizable(resizable.request == REQUEST_RESIZABLE, true);
1031         resizable.request = REQUEST_NONE;




1032     }
1033 }
1034 
1035 void WindowContextTop::update_window_constraints() {
1036     if (resizable.value) {
1037         GdkGeometry geom = {
1038             (resizable.minw == -1) ? 1
1039                     : resizable.minw - geometry.extents.left - geometry.extents.right,
1040             (resizable.minh == -1) ? 1
1041                     : resizable.minh - geometry.extents.top - geometry.extents.bottom,
1042             (resizable.maxw == -1) ? 100000
1043                     : resizable.maxw - geometry.extents.left - geometry.extents.right,
1044             (resizable.maxh == -1) ? 100000
1045                     : resizable.maxh - geometry.extents.top - geometry.extents.bottom,
1046             0, 0, 0, 0, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
1047         };
1048         gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom,
1049                 static_cast<GdkWindowHints> (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE));
1050     }
1051 }
1052 
1053 void WindowContextTop::set_window_resizable(bool res, bool grip) {
1054     if(!res) {
1055         int w = geometry_get_content_width(&geometry);
1056         int h = geometry_get_content_height(&geometry);
1057         if (w == -1 && h == -1) {
1058             gtk_window_get_size(GTK_WINDOW(gtk_widget), &w, &h);
1059         }
1060         GdkGeometry geom = {w, h, w, h, 0, 0, 0, 0, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST};
1061         gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom,
1062                 static_cast<GdkWindowHints>(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE));
1063         GLASS_GTK_WINDOW_SET_HAS_RESIZE_GRIP(gdk_window, FALSE);
1064         resizable.prev = resizable.value;
1065         resizable.value = false;
1066     } else {
1067         resizable.prev = resizable.value;
1068         resizable.value = true;
1069         update_window_constraints();
1070         if (grip) {
1071             GLASS_GTK_WINDOW_SET_HAS_RESIZE_GRIP(gdk_window, TRUE);
1072         }
1073     }
1074 }
1075 
1076 void WindowContextTop::set_resizable(bool res) {

1077     gint w, h;
1078     gtk_window_get_size(GTK_WINDOW(gtk_widget), &w, &h);
1079     if (map_received || w > 1 || h > 1) {
1080         set_window_resizable(res, true);
1081     } else {
1082         //Since window is not ready yet set only request for change of resizable.
1083         resizable.request  = res ? REQUEST_RESIZABLE : REQUEST_NOT_RESIZABLE;
1084     }
1085 }
1086 
1087 void WindowContextTop::set_visible(bool visible)
1088 {
1089     if (visible) {
1090         if (!size_assigned) {
1091             set_bounds(0, 0, false, false, 320, 200, -1, -1);
1092         }
1093         if (!location_assigned) {
1094             set_bounds(0, 0, true, true, -1, -1, -1, -1);
1095         }
1096     }
1097     WindowContextBase::set_visible(visible);
1098 }
1099 
1100 void WindowContextTop::set_bounds(int x, int y, bool xSet, bool ySet, int w, int h, int cw, int ch) {


1153         windowChangesMask |= CWY;
1154     }
1155 
1156     if (xSet || ySet) location_assigned = true;
1157     if (w > 0 || h > 0 || cw > 0 || ch > 0) size_assigned = true;
1158 
1159     window_configure(&windowChanges, windowChangesMask);
1160 
1161 }
1162 
1163 void WindowContextTop::process_map() {
1164     map_received = true;
1165 }
1166 
1167 void WindowContextTop::window_configure(XWindowChanges *windowChanges,
1168         unsigned int windowChangesMask) {
1169     if (windowChangesMask == 0) {
1170         return;
1171     }
1172 
1173     if (!gtk_widget_get_visible(gtk_widget)) {
1174         // not visible yet, synchronize with gtk only
1175         if (windowChangesMask & (CWX | CWY)) {
1176             gint newX, newY;
1177             gtk_window_get_position(GTK_WINDOW(gtk_widget), &newX, &newY);
1178 
1179             if (windowChangesMask & CWX) {
1180                 newX = windowChanges->x;
1181             }
1182             if (windowChangesMask & CWY) {
1183                 newY = windowChanges->y;
1184             }
1185 
1186             gtk_window_move(GTK_WINDOW(gtk_widget), newX, newY);
1187         }
1188 
1189         if (windowChangesMask & (CWWidth | CWHeight)) {
1190             gint newWidth, newHeight;
1191             gtk_window_get_size(GTK_WINDOW(gtk_widget),
1192                     &newWidth, &newHeight);
1193 
1194             if (windowChangesMask & CWWidth) {
1195                 newWidth = windowChanges->width;
1196             }
1197             if (windowChangesMask & CWHeight) {
1198                 newHeight = windowChanges->height;
1199             }
1200 
1201             gtk_window_resize(GTK_WINDOW(gtk_widget), newWidth, newHeight);
1202         }
1203         stale_config_notifications = 1;
1204         return;
1205     }
1206 
1207     ++stale_config_notifications;
1208 
1209     if (!resizable.value && (windowChangesMask & (CWWidth | CWHeight))) {
1210         XSizeHints *sizeHints = XAllocSizeHints();
1211         if (sizeHints != NULL) {
1212             int fixedWidth = (windowChangesMask & CWWidth)
1213                     ? windowChanges->width
1214                     : geometry_get_content_width(&geometry);
1215             int fixedHeight = (windowChangesMask & CWHeight)
1216                     ? windowChanges->height
1217                     : geometry_get_content_height(&geometry);
1218 
1219             sizeHints->flags = PMinSize | PMaxSize;
1220 
1221             sizeHints->min_width = 1;
1222             sizeHints->min_height = 1;
1223             sizeHints->max_width = INT_MAX;
1224             sizeHints->max_height = INT_MAX;
1225             XSetWMNormalHints(GDK_WINDOW_XDISPLAY(gdk_window),
1226                     GDK_WINDOW_XID(gdk_window),
1227                     sizeHints);
1228 
1229             XConfigureWindow(GDK_WINDOW_XDISPLAY(gdk_window),
1230                     GDK_WINDOW_XID(gdk_window),
1231                     windowChangesMask,
1232                     windowChanges);
1233 
1234             sizeHints->min_width = fixedWidth;
1235             sizeHints->min_height = fixedHeight;
1236             sizeHints->max_width = fixedWidth;
1237             sizeHints->max_height = fixedHeight;
1238             XSetWMNormalHints(GDK_WINDOW_XDISPLAY(gdk_window),
1239                     GDK_WINDOW_XID(gdk_window),
1240                     sizeHints);
1241 
1242             XFree(sizeHints);
1243             return;
1244         }

1245     }
1246 
1247     XConfigureWindow(GDK_WINDOW_XDISPLAY(gdk_window),
1248             GDK_WINDOW_XID(gdk_window),
1249             windowChangesMask,
1250             windowChanges);
1251 }
1252 
1253 void WindowContextTop::applyShapeMask(void* data, uint width, uint height)
1254 {
1255     if (frame_type != TRANSPARENT) {
1256         return;
1257     }
1258 
1259     GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data((guchar *) data,
1260             GDK_COLORSPACE_RGB, TRUE, 8, width, height, width * 4, NULL, NULL);
1261 
1262     if (GDK_IS_PIXBUF(pixbuf)) {
1263         GdkBitmap* mask = NULL;
1264         gdk_pixbuf_render_pixmap_and_mask(pixbuf, NULL, &mask, 128);
1265 
1266         gdk_window_input_shape_combine_mask(gdk_window, mask, 0, 0);
1267 
1268         g_object_unref(pixbuf);
1269         if (mask) {
1270             g_object_unref(mask);
1271         }


1272     }
1273 }
1274 
1275 void WindowContextTop::set_minimized(bool minimize) {
1276     is_iconified = minimize;
1277     if (minimize) {
1278         if (frame_type == TRANSPARENT) {
1279             // https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1245571
1280             gdk_window_input_shape_combine_mask(gdk_window, NULL, 0, 0);
1281         }
1282 
1283         if ((gdk_windowManagerFunctions & GDK_FUNC_MINIMIZE) == 0) {
1284             // in this case - the window manager will not support the programatic
1285             // request to iconify - so we need to disable this until we are restored.
1286             GdkWMFunction wmf = (GdkWMFunction)(gdk_windowManagerFunctions | GDK_FUNC_MINIMIZE);
1287             gdk_window_set_functions(gdk_window, wmf);
1288         }
1289         gtk_window_iconify(GTK_WINDOW(gtk_widget));
1290     } else {
1291         gtk_window_deiconify(GTK_WINDOW(gtk_widget));
1292         activate_window();
1293     }
1294 }
1295 void WindowContextTop::set_maximized(bool maximize) {
1296     is_maximized = maximize;
1297     if (maximize) {

1298         gtk_window_maximize(GTK_WINDOW(gtk_widget));
1299     } else {
1300         gtk_window_unmaximize(GTK_WINDOW(gtk_widget));
1301     }
1302 }
1303 
1304 void WindowContextTop::enter_fullscreen() {

1305     gtk_window_fullscreen(GTK_WINDOW(gtk_widget));
1306 }
1307 
1308 void WindowContextTop::exit_fullscreen() {
1309     gtk_window_unfullscreen(GTK_WINDOW(gtk_widget));
1310 }
1311 
1312 void WindowContextTop::request_focus() {
1313     gtk_window_present(GTK_WINDOW(gtk_widget));
1314 }
1315 
1316 void WindowContextTop::set_focusable(bool focusable) {
1317     gtk_window_set_accept_focus(GTK_WINDOW(gtk_widget), focusable ? TRUE : FALSE);
1318 }
1319 
1320 void WindowContextTop::set_title(const char* title) {
1321     gtk_window_set_title(GTK_WINDOW(gtk_widget),title);
1322 }
1323 
1324 void WindowContextTop::set_alpha(double alpha) {
1325     gtk_window_set_opacity(GTK_WINDOW(gtk_widget), (gdouble)alpha);
1326 }
1327 
1328 void WindowContextTop::set_enabled(bool enabled) {
1329     if (enabled) {
1330         //set back proper resizable value.
1331         set_window_resizable(resizable.prev, true);

1332     } else {
1333         //disabled window can't be resizable.
1334         set_window_resizable(false, false);





1335     }
1336 }
1337 
1338 void WindowContextTop::set_minimum_size(int w, int h) {
1339     resizable.minw = w;
1340     resizable.minh = h;
1341     update_window_constraints();
1342 }
1343 
1344 void WindowContextTop::set_maximum_size(int w, int h) {
1345     resizable.maxw = w;
1346     resizable.maxh = h;
1347     update_window_constraints();
1348 }
1349 
1350 void WindowContextTop::set_icon(GdkPixbuf* pixbuf) {
1351     gtk_window_set_icon(GTK_WINDOW(gtk_widget), pixbuf);
1352 }
1353 
1354 void WindowContextTop::restack(bool restack) {


1454     WindowContextBase::process_destroy();
1455 }
1456 
1457 ////////////////////////////// WindowContextPlug ////////////////////////////////
1458 
1459 static gboolean plug_configure(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
1460     (void)widget;
1461 
1462     if (event->type == GDK_CONFIGURE) {
1463         ((WindowContextPlug*)user_data)->process_gtk_configure(&event->configure);
1464     }
1465     return FALSE;
1466 }
1467 
1468 WindowContextPlug::WindowContextPlug(jobject _jwindow, void* _owner) :
1469         WindowContextBase(),
1470         parent()
1471 {
1472     jwindow = mainEnv->NewGlobalRef(_jwindow);
1473 
1474     gtk_widget = gtk_plug_new((GdkNativeWindow)PTR_TO_JLONG(_owner));


1475 
1476     g_signal_connect(G_OBJECT(gtk_widget), "configure-event", G_CALLBACK(plug_configure), this);
1477 
1478     gtk_widget_set_size_request(gtk_widget, 0, 0);
1479     gtk_widget_set_events(gtk_widget, GDK_ALL_EVENTS_MASK);
1480     gtk_widget_set_can_focus(GTK_WIDGET(gtk_widget), TRUE);
1481     gtk_widget_set_app_paintable(gtk_widget, TRUE);
1482 
1483     gtk_widget_realize(gtk_widget);
1484     gdk_window = gtk_widget_get_window(gtk_widget);
1485 
1486     g_object_set_data_full(G_OBJECT(gdk_window), GDK_WINDOW_DATA_CONTEXT, this, NULL);
1487     gdk_window_register_dnd(gdk_window);
1488 
1489     gtk_container = gtk_fixed_new();
1490     gtk_container_add (GTK_CONTAINER(gtk_widget), gtk_container);
1491     gtk_widget_realize(gtk_container);
1492 }
1493 
1494 GtkWindow *WindowContextPlug::get_gtk_window() {


1687 
1688     gtk_widget_set_size_request(gtk_widget, event->width, event->height);
1689 
1690     if (jwindow) {
1691         mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize,
1692                 com_sun_glass_events_WindowEvent_RESIZE,
1693                 event->width,
1694                 event->height);
1695         CHECK_JNI_EXCEPTION(mainEnv)
1696     }
1697 }
1698 
1699 bool WindowContextChild::set_view(jobject view) {
1700     if (jview) {
1701         mainEnv->DeleteGlobalRef(jview);
1702     }
1703 
1704     if (view) {
1705         gint width, height;
1706         jview = mainEnv->NewGlobalRef(view);
1707         width = gtk_widget->allocation.width;
1708         height = gtk_widget->allocation.height;


1709         mainEnv->CallVoidMethod(view, jViewNotifyResize, width, height);
1710         CHECK_JNI_EXCEPTION_RET(mainEnv, FALSE)
1711     } else {
1712         jview = NULL;
1713     }
1714     return TRUE;
1715 }
1716 
1717 void WindowContextChild::set_bounds(int x, int y, bool xSet, bool ySet, int w, int h, int cw, int ch) {
1718 
1719     if (x > 0 || y > 0 || xSet || ySet) {
1720         gint newX, newY;
1721         gdk_window_get_origin(gdk_window, &newX, &newY);
1722         if (jwindow) {
1723             mainEnv->CallVoidMethod(jwindow,
1724                     jWindowNotifyMove,
1725                     newX, newY);
1726             CHECK_JNI_EXCEPTION(mainEnv)
1727         }
1728     }
1729 
1730     // As we have no frames, there's no difference between the calls
1731     if ((cw | ch) > 0) {
1732         w = cw; h = ch;
1733     }
1734 
1735     if (w > 0 || h > 0) {
1736         gint newWidth, newHeight;
1737         newWidth = gtk_widget->allocation.width;
1738         newHeight = gtk_widget->allocation.height;


1739 
1740         if (w > 0) {
1741             newWidth = w;
1742         }
1743         if (h > 0) {
1744             newHeight = h;
1745         }
1746         gtk_widget_set_size_request(gtk_widget, newWidth, newHeight);
1747         // FIXME: hack to set correct size to view
1748         if (jview) {
1749             mainEnv->CallVoidMethod(jview,
1750                     jViewNotifyResize,
1751                     newWidth, newHeight);
1752             CHECK_JNI_EXCEPTION(mainEnv)
1753         }
1754     }
1755 }
1756 
1757 int WindowContextChild::getEmbeddedX() {
1758     int x;


1776 
1777     embedded_children.erase(pos);
1778     if (toFront) {
1779         embedded_children.push_back(this);
1780     } else {
1781         embedded_children.insert(embedded_children.begin(), this);
1782     }
1783 
1784     gdk_window_restack(gdk_window, NULL, toFront ? TRUE : FALSE);
1785 }
1786 
1787 void WindowContextChild::enter_fullscreen() {
1788     if (full_screen_window) {
1789         return;
1790     }
1791 
1792     full_screen_window = new WindowContextTop(jwindow, NULL, 0L, UNTITLED,
1793                                                 NORMAL, (GdkWMFunction) 0);
1794     int x, y, w, h;
1795     gdk_window_get_origin(gdk_window, &x, &y);



1796     gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL);

1797     full_screen_window->set_bounds(x, y, true, true, w, h, -1, -1);
1798 
1799     if (WindowContextBase::sm_grab_window == this) {
1800         ungrab_focus();
1801     }
1802 
1803     reparent_children(full_screen_window);
1804 
1805     full_screen_window->set_visible(true);
1806     full_screen_window->enter_fullscreen();
1807 
1808     if (jwindow) {
1809         mainEnv->CallVoidMethod(jwindow, jWindowNotifyDelegatePtr, (jlong)full_screen_window);
1810         CHECK_JNI_EXCEPTION(mainEnv)
1811     }
1812 
1813     if (jview) {
1814         this->view = (GlassView*)mainEnv->GetLongField(jview, jViewPtr);
1815 
1816         this->view->current_window = full_screen_window;




   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 #include "glass_window.h"
  26 #include "glass_general.h"

  27 #include "glass_key.h"
  28 #include "glass_screen.h"
  29 #include "glass_dnd.h"
  30 
  31 #include <com_sun_glass_events_WindowEvent.h>
  32 #include <com_sun_glass_events_ViewEvent.h>
  33 #include <com_sun_glass_events_MouseEvent.h>
  34 #include <com_sun_glass_events_KeyEvent.h>
  35 
  36 #include <com_sun_glass_ui_Window_Level.h>
  37 
  38 #include <X11/extensions/shape.h>
  39 #include <cairo.h>
  40 #include <cairo-xlib.h>
  41 #include <gdk/gdkx.h>
  42 #include <gdk/gdk.h>
  43 
  44 #ifdef GLASS_GTK3
  45 #include <gtk/gtkx.h>
  46 #endif
  47 
  48 #include <string.h>
  49 
  50 #include <algorithm>
  51 
  52 WindowContext * WindowContextBase::sm_grab_window = NULL;
  53 WindowContext * WindowContextBase::sm_mouse_drag_window = NULL;
  54 


  55 GdkWindow* WindowContextBase::get_gdk_window(){
  56     return gdk_window;
  57 }
  58 
  59 jobject WindowContextBase::get_jview() {
  60     return jview;
  61 }
  62 
  63 jobject WindowContextBase::get_jwindow() {
  64     return jwindow;
  65 }
  66 
  67 bool WindowContextBase::isEnabled() {
  68     if (jwindow) {
  69         bool result = (JNI_TRUE == mainEnv->CallBooleanMethod(jwindow, jWindowIsEnabled));
  70         LOG_EXCEPTION(mainEnv)
  71         return result;
  72     } else {
  73         return false;
  74     }


 337 
 338     if (jview) {
 339         mainEnv->CallVoidMethod(jview, jViewNotifyMouse,
 340                 isDrag ? com_sun_glass_events_MouseEvent_DRAG : com_sun_glass_events_MouseEvent_MOVE,
 341                 button,
 342                 (jint) event->x, (jint) event->y,
 343                 (jint) event->x_root, (jint) event->y_root,
 344                 glass_modifier,
 345                 JNI_FALSE,
 346                 JNI_FALSE);
 347         CHECK_JNI_EXCEPTION(mainEnv)
 348     }
 349 }
 350 
 351 void WindowContextBase::process_mouse_scroll(GdkEventScroll* event) {
 352     jdouble dx = 0;
 353     jdouble dy = 0;
 354 
 355     // converting direction to change in pixels
 356     switch (event->direction) {
 357 #if GTK_CHECK_VERSION(3, 4, 0)
 358         case GDK_SCROLL_SMOOTH:
 359             //FIXME 3.4 ???
 360             break;
 361 #endif
 362         case GDK_SCROLL_UP:
 363             dy = 1;
 364             break;
 365         case GDK_SCROLL_DOWN:
 366             dy = -1;
 367             break;
 368         case GDK_SCROLL_LEFT:
 369             dx = 1;
 370             break;
 371         case GDK_SCROLL_RIGHT:
 372             dx = -1;
 373             break;
 374     }
 375 
 376     if (jview) {
 377         mainEnv->CallVoidMethod(jview, jViewNotifyScroll,
 378                 (jint) event->x, (jint) event->y,
 379                 (jint) event->x_root, (jint) event->y_root,
 380                 dx, dy,
 381                 gdk_modifier_mask_to_glass(event->state),


 407                     JNI_FALSE);
 408             CHECK_JNI_EXCEPTION(mainEnv)
 409         }
 410     }
 411 }
 412 
 413 void WindowContextBase::process_key(GdkEventKey* event) {
 414     bool press = event->type == GDK_KEY_PRESS;
 415     jint glassKey = get_glass_key(event);
 416     jint glassModifier = gdk_modifier_mask_to_glass(event->state);
 417     if (press) {
 418         glassModifier |= glass_key_to_modifier(glassKey);
 419     } else {
 420         glassModifier &= ~glass_key_to_modifier(glassKey);
 421     }
 422     jcharArray jChars = NULL;
 423     jchar key = gdk_keyval_to_unicode(event->keyval);
 424     if (key >= 'a' && key <= 'z' && (event->state & GDK_CONTROL_MASK)) {
 425         key = key - 'a' + 1; // map 'a' to ctrl-a, and so on.
 426     } else {
 427 #ifdef GLASS_GTK2
 428         if (key == 0) {
 429             // Work around "bug" fixed in gtk-3.0:
 430             // http://mail.gnome.org/archives/commits-list/2011-March/msg06832.html
 431             switch (event->keyval) {
 432             case 0xFF08 /* Backspace */: key =  '\b';
 433             case 0xFF09 /* Tab       */: key =  '\t';
 434             case 0xFF0A /* Linefeed  */: key =  '\n';
 435             case 0xFF0B /* Vert. Tab */: key =  '\v';
 436             case 0xFF0D /* Return    */: key =  '\r';
 437             case 0xFF1B /* Escape    */: key =  '\033';
 438             case 0xFFFF /* Delete    */: key =  '\177';
 439             }
 440         }
 441 #endif
 442     }
 443 
 444     if (key > 0) {
 445         jChars = mainEnv->NewCharArray(1);
 446         if (jChars) {
 447             mainEnv->SetCharArrayRegion(jChars, 0, 1, &key);
 448             CHECK_JNI_EXCEPTION(mainEnv)
 449         }
 450     } else {
 451         jChars = mainEnv->NewCharArray(0);
 452     }
 453     if (jview) {
 454         if (press) {
 455             mainEnv->CallVoidMethod(jview, jViewNotifyKey,
 456                     com_sun_glass_events_KeyEvent_PRESS,
 457                     glassKey,
 458                     jChars,
 459                     glassModifier);
 460             CHECK_JNI_EXCEPTION(mainEnv)
 461 


 467                         glassModifier);
 468                 CHECK_JNI_EXCEPTION(mainEnv)
 469             }
 470         } else {
 471             mainEnv->CallVoidMethod(jview, jViewNotifyKey,
 472                     com_sun_glass_events_KeyEvent_RELEASE,
 473                     glassKey,
 474                     jChars,
 475                     glassModifier);
 476             CHECK_JNI_EXCEPTION(mainEnv)
 477         }
 478     }
 479 }
 480 
 481 void WindowContextBase::paint(void* data, jint width, jint height)
 482 {
 483     if (!is_visible()) {
 484         return;
 485     }
 486 
 487 #ifdef GLASS_GTK3
 488     cairo_region_t *region = gdk_window_get_clip_region(gdk_window);
 489     gdk_window_begin_paint_region(gdk_window, region);
 490 #endif
 491 
 492     cairo_t* context;
 493     context = gdk_cairo_create(gdk_window);
 494 
 495     cairo_surface_t* cairo_surface;
 496     cairo_surface = cairo_image_surface_create_for_data(
 497             (unsigned char*)data,
 498             CAIRO_FORMAT_ARGB32,
 499             width, height, width * 4);
 500 
 501     applyShapeMask(data, width, height);
 502 
 503     cairo_set_source_surface(context, cairo_surface, 0, 0);
 504 
 505     cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
 506     cairo_paint(context);
 507 #ifdef GLASS_GTK3
 508     gdk_window_end_paint(gdk_window);
 509     cairo_region_destroy(region);
 510 #endif
 511 
 512     cairo_destroy(context);
 513     cairo_surface_destroy(cairo_surface);
 514 }
 515 
 516 void WindowContextBase::add_child(WindowContextTop* child) {
 517     children.insert(child);
 518     gtk_window_set_transient_for(child->get_gtk_window(), this->get_gtk_window());
 519 }
 520 
 521 void WindowContextBase::remove_child(WindowContextTop* child) {
 522     children.erase(child);
 523     gtk_window_set_transient_for(child->get_gtk_window(), NULL);
 524 }
 525 
 526 void WindowContextBase::show_or_hide_children(bool show) {
 527     std::set<WindowContextTop*>::iterator it;
 528     for (it = children.begin(); it != children.end(); ++it) {
 529         (*it)->set_minimized(!show);
 530         (*it)->show_or_hide_children(show);
 531     }
 532 }
 533 
 534 void WindowContextBase::reparent_children(WindowContext* parent) {
 535     std::set<WindowContextTop*>::iterator it;
 536     for (it = children.begin(); it != children.end(); ++it) {
 537         (*it)->set_owner(parent);
 538         parent->add_child(*it);
 539     }
 540     children.clear();
 541 }
 542 
 543 void WindowContextBase::set_visible(bool visible) {
 544     if (visible) {
 545         gtk_widget_show_all(gtk_widget);
 546     } else {
 547         gtk_widget_hide(gtk_widget);
 548         if (jview && is_mouse_entered) {
 549             is_mouse_entered = false;


 612 
 613 void WindowContextBase::ungrab_focus() {
 614     if (!WindowContextBase::sm_mouse_drag_window) {
 615         glass_gdk_mouse_devices_ungrab();
 616     }
 617     WindowContextBase::sm_grab_window = NULL;
 618 
 619     if (jwindow) {
 620         mainEnv->CallVoidMethod(jwindow, jWindowNotifyFocusUngrab);
 621         CHECK_JNI_EXCEPTION(mainEnv)
 622     }
 623 }
 624 
 625 void WindowContextBase::set_cursor(GdkCursor* cursor) {
 626     if (!is_in_drag()) {
 627         if (WindowContextBase::sm_mouse_drag_window) {
 628             glass_gdk_mouse_devices_grab_with_cursor(
 629                     WindowContextBase::sm_mouse_drag_window->get_gdk_window(), cursor, FALSE);
 630         } else if (WindowContextBase::sm_grab_window) {
 631             glass_gdk_mouse_devices_grab_with_cursor(
 632                     WindowContextBase::sm_grab_window->get_gdk_window(), cursor, TRUE);
 633         }
 634     }
 635     gdk_window_set_cursor(gdk_window, cursor);
 636 }
 637 
 638 void WindowContextBase::set_background(float r, float g, float b) {
 639 #ifdef GLASS_GTK3
 640     GdkRGBA rgba = {0, 0, 0, 1.};
 641     rgba.red = r;
 642     rgba.green = g;
 643     rgba.blue = b;
 644     gdk_window_set_background_rgba(gdk_window, &rgba);
 645 #else
 646     GdkColor color;
 647     color.red   = (guint16) (r * 65535);
 648     color.green = (guint16) (g * 65535);
 649     color.blue  = (guint16) (b * 65535);
 650     gtk_widget_modify_bg(gtk_widget, GTK_STATE_NORMAL, &color);
 651 #endif
 652 }
 653 
 654 WindowContextBase::~WindowContextBase() {
 655     if (xim.ic) {
 656         XDestroyIC(xim.ic);
 657         xim.ic = NULL;
 658     }
 659     if (xim.im) {
 660         XCloseIM(xim.im);
 661         xim.im = NULL;
 662     }
 663 
 664     gtk_widget_destroy(gtk_widget);
 665 }
 666 
 667 ////////////////////////////// WindowContextTop /////////////////////////////////
 668 
 669 
 670 WindowContextTop::WindowContextTop(jobject _jwindow, WindowContext* _owner, long _screen,
 671         WindowFrameType _frame_type, WindowType type, GdkWMFunction wmf) :
 672             WindowContextBase(),
 673             screen(_screen),
 674             frame_type(_frame_type),
 675             owner(_owner),
 676             geometry(),

 677             resizable(),
 678             frame_extents_initialized(),
 679             map_received(false),
 680             location_assigned(false),
 681             size_assigned(false),
 682             on_top(false)
 683 {
 684     jwindow = mainEnv->NewGlobalRef(_jwindow);
 685 
 686     gtk_widget =  gtk_window_new(type == POPUP ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
 687 
 688     if (gchar* app_name = get_application_name()) {
 689         gtk_window_set_wmclass(GTK_WINDOW(gtk_widget), app_name, app_name);
 690         g_free(app_name);
 691     }
 692 
 693     if (owner) {
 694         owner->add_child(this);
 695         if (on_top_inherited()) {
 696             gtk_window_set_keep_above(GTK_WINDOW(gtk_widget), TRUE);


 739 // Applied to a temporary full screen window to prevent sending events to Java
 740 void WindowContextTop::detach_from_java() {
 741     if (jview) {
 742         mainEnv->DeleteGlobalRef(jview);
 743         jview = NULL;
 744     }
 745     if (jwindow) {
 746         mainEnv->DeleteGlobalRef(jwindow);
 747         jwindow = NULL;
 748     }
 749 }
 750 
 751 static GdkAtom
 752 get_net_frame_extents_atom() {
 753     static const char * extents_str = "_NET_FRAME_EXTENTS";
 754     return gdk_atom_intern(extents_str, TRUE);
 755 }
 756 
 757 void
 758 WindowContextTop::request_frame_extents() {
 759     Display *display = GDK_DISPLAY_XDISPLAY(gdk_window_get_display(gdk_window));
 760     Atom rfeAtom = XInternAtom(display, "_NET_REQUEST_FRAME_EXTENTS", True);
 761     if (rfeAtom != None) {
 762         XClientMessageEvent clientMessage;
 763         memset(&clientMessage, 0, sizeof(clientMessage));
 764 
 765         clientMessage.type = ClientMessage;
 766         clientMessage.window = GDK_WINDOW_XID(gdk_window);
 767         clientMessage.message_type = rfeAtom;
 768         clientMessage.format = 32;
 769 
 770         XSendEvent(display, XDefaultRootWindow(display), False,
 771                    SubstructureRedirectMask | SubstructureNotifyMask,
 772                    (XEvent *) &clientMessage);
 773         XFlush(display);
 774     }
 775 }
 776 
 777 void WindowContextTop::activate_window() {
 778     Display *display = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdk_window));
 779     Atom navAtom = XInternAtom(display, "_NET_ACTIVE_WINDOW", True);
 780     if (navAtom != None) {
 781         XClientMessageEvent clientMessage;
 782         memset(&clientMessage, 0, sizeof(clientMessage));
 783 
 784         clientMessage.type = ClientMessage;
 785         clientMessage.window = GDK_WINDOW_XID(gdk_window);
 786         clientMessage.message_type = navAtom;
 787         clientMessage.format = 32;
 788         clientMessage.data.l[0] = 1;
 789         clientMessage.data.l[1] = gdk_x11_get_server_time(gdk_window);
 790         clientMessage.data.l[2] = 0;
 791 
 792         XSendEvent(display, XDefaultRootWindow(display), False,
 793                    SubstructureRedirectMask | SubstructureNotifyMask,
 794                    (XEvent *) &clientMessage);
 795         XFlush(display);
 796     }
 797 }
 798 


 817             gdk_atom_intern("CARDINAL", FALSE),
 818             0,
 819             sizeof (unsigned long) * 4,
 820             FALSE,
 821             NULL,
 822             NULL,
 823             NULL,
 824             (guchar**) & extents)) {
 825         *left = extents [0];
 826         *right = extents [1];
 827         *top = extents [2];
 828         *bottom = extents [3];
 829 
 830         g_free(extents);
 831         return true;
 832     }
 833 
 834     return false;
 835 }
 836 

 837 static int geometry_get_window_width(const WindowGeometry *windowGeometry) {
 838      return (windowGeometry->final_width.type != BOUNDSTYPE_WINDOW)
 839                    ? windowGeometry->final_width.value
 840                          + windowGeometry->extents.left
 841                          + windowGeometry->extents.right
 842                    : windowGeometry->final_width.value;
 843 }
 844 
 845 static int geometry_get_window_height(const WindowGeometry *windowGeometry) {
 846     return (windowGeometry->final_height.type != BOUNDSTYPE_WINDOW)
 847                    ? windowGeometry->final_height.value
 848                          + windowGeometry->extents.top
 849                          + windowGeometry->extents.bottom
 850                    : windowGeometry->final_height.value;
 851 }
 852 
 853 static int geometry_get_content_width(WindowGeometry *windowGeometry) {
 854     return (windowGeometry->final_width.type != BOUNDSTYPE_CONTENT)
 855                    ? windowGeometry->final_width.value
 856                          - windowGeometry->extents.left


 888     if (windowGeometry->gravity_x != 0) {
 889         newValue += geometry_get_window_width(windowGeometry)
 890                 * windowGeometry->gravity_x;
 891     }
 892     windowGeometry->refx = newValue;
 893 }
 894 
 895 static void geometry_set_window_y(WindowGeometry *windowGeometry, int value) {
 896     float newValue = value;
 897     if (windowGeometry->gravity_y != 0) {
 898         newValue += geometry_get_window_height(windowGeometry)
 899                 * windowGeometry->gravity_y;
 900     }
 901     windowGeometry->refy = newValue;
 902 }
 903 
 904 void WindowContextTop::process_net_wm_property() {
 905     // Workaround for https://bugs.launchpad.net/unity/+bug/998073
 906 
 907     static GdkAtom atom_atom = gdk_atom_intern_static_string("ATOM");
 908     static GdkAtom atom_net_wm_state = gdk_atom_intern_static_string("_NET_WM_STATE");
 909     static GdkAtom atom_net_wm_state_hidden = gdk_atom_intern_static_string("_NET_WM_STATE_HIDDEN");
 910     static GdkAtom atom_net_wm_state_above = gdk_atom_intern_static_string("_NET_WM_STATE_ABOVE");
 911 
 912     gint length;
 913 
 914     glong* atoms = NULL;
 915 
 916     if (gdk_property_get(gdk_window, atom_net_wm_state, atom_atom,
 917             0, G_MAXLONG, FALSE, NULL, NULL, &length, (guchar**) &atoms)) {
 918 
 919         bool is_hidden = false;
 920         bool is_above = false;
 921         for (gint i = 0; i < (gint)(length / sizeof(glong)); i++) {
 922             if (atom_net_wm_state_hidden == (GdkAtom)atoms[i]) {
 923                 is_hidden = true;
 924             } else if (atom_net_wm_state_above == (GdkAtom)atoms[i]) {
 925                 is_above = true;
 926             }
 927         }
 928 
 929         g_free(atoms);
 930 
 931         if (is_iconified != is_hidden) {
 932             is_iconified = is_hidden;
 933 
 934             notify_state((is_hidden)
 935                     ? com_sun_glass_events_WindowEvent_MINIMIZE
 936                     : com_sun_glass_events_WindowEvent_RESTORE);
 937         }
 938 
 939         notify_on_top(is_above);
 940     }
 941 }
 942 
 943 void WindowContextTop::process_property_notify(GdkEventProperty* event) {
 944     static GdkAtom atom_net_wm_state = gdk_atom_intern_static_string("_NET_WM_STATE");
 945 
 946     if (event->atom == atom_net_wm_state && event->window == gdk_window) {
 947         process_net_wm_property();
 948     }
 949 }






 950 
 951 void WindowContextTop::process_configure(GdkEventConfigure* event) {
 952     gint x, y, w, h;
 953     bool updateWindowConstraints = false;
 954     if (gtk_window_get_decorated(GTK_WINDOW(gtk_widget))) {
 955         GdkRectangle frame;
 956         gint top, left, bottom, right;
 957 
 958         gdk_window_get_frame_extents(gdk_window, &frame);
 959         gint contentX, contentY;
 960         gdk_window_get_origin(gdk_window, &contentX, &contentY);
 961 #ifdef GLASS_GTK3
 962         gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h);
 963 #else
 964         gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL);
 965 #endif
 966         x = frame.x;
 967         y = frame.y;
 968         geometry.current_width = frame.width;
 969         geometry.current_height = frame.height;
 970 
 971         top = contentY - frame.y;
 972         left = contentX - frame.x;
 973         bottom = frame.y + frame.height - (contentY + h);
 974         right = frame.x + frame.width - (contentX + w);
 975         if (geometry.extents.top != top
 976                 || geometry.extents.left != left
 977                 || geometry.extents.bottom != bottom
 978                 || geometry.extents.right != right) {
 979             updateWindowConstraints = true;
 980             geometry.extents.top = top;
 981             geometry.extents.left = left;
 982             geometry.extents.bottom = bottom;
 983             geometry.extents.right = right;






































 984         }













 985     } else {
 986         x = event->x;
 987         y = event->y;
 988         w = event->width;
 989         h = event->height;
 990     }
 991 
 992     if (size_assigned && w <= 1 && h <= 1 && (geometry.final_width.value > 1 ||
 993                                              geometry.final_height.value > 1)) {
 994         // skip artifact
 995         return;
 996     }
 997 
 998     geometry.final_width.value = w;
 999     geometry.final_width.type = BOUNDSTYPE_CONTENT;
1000     geometry.final_height.value = h;
1001     geometry.final_height.type = BOUNDSTYPE_CONTENT;

1002     geometry_set_window_x(&geometry, x);
1003     geometry_set_window_y(&geometry, y);
1004 


1005     if (jview) {
1006         mainEnv->CallVoidMethod(jview, jViewNotifyResize,
1007                 event->width,
1008                 event->height);
1009         CHECK_JNI_EXCEPTION(mainEnv)
1010         mainEnv->CallVoidMethod(jview, jViewNotifyView,
1011                 com_sun_glass_events_ViewEvent_MOVE);
1012         CHECK_JNI_EXCEPTION(mainEnv)
1013     }
1014 
1015     if (jwindow) {
1016         mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize,
1017                 (is_maximized)
1018                     ? com_sun_glass_events_WindowEvent_MAXIMIZE
1019                     : com_sun_glass_events_WindowEvent_RESIZE,
1020                 geometry.current_width,
1021                 geometry.current_height);
1022         CHECK_JNI_EXCEPTION(mainEnv)
1023 
1024         mainEnv->CallVoidMethod(jwindow, jWindowNotifyMove, x, y);
1025         CHECK_JNI_EXCEPTION(mainEnv)
1026     }
1027 
1028     glong to_screen = getScreenPtrForLocation(x, y);
1029     if (to_screen != -1) {
1030         if (to_screen != screen) {
1031             if (jwindow) {
1032                 //notify screen changed
1033                 jobject jScreen = createJavaScreen(mainEnv, to_screen);
1034                 mainEnv->CallVoidMethod(jwindow, jWindowNotifyMoveToAnotherScreen, jScreen);
1035                 CHECK_JNI_EXCEPTION(mainEnv)
1036             }
1037             screen = to_screen;
1038         }
1039     }
1040 
1041     if (resizable.request != REQUEST_NONE) {
1042         set_window_resizable(resizable.request == REQUEST_RESIZABLE);
1043         resizable.request = REQUEST_NONE;
1044     } else if (!resizable.value) {
1045         set_window_resizable(false);
1046     } else if (updateWindowConstraints) {
1047         update_window_constraints();
1048     }
1049 }
1050 
1051 void WindowContextTop::update_window_constraints() {
1052     if (resizable.value) {
1053         GdkGeometry geom = {
1054             (resizable.minw == -1) ? 1
1055                     : resizable.minw - geometry.extents.left - geometry.extents.right,
1056             (resizable.minh == -1) ? 1
1057                     : resizable.minh - geometry.extents.top - geometry.extents.bottom,
1058             (resizable.maxw == -1) ? 100000
1059                     : resizable.maxw - geometry.extents.left - geometry.extents.right,
1060             (resizable.maxh == -1) ? 100000
1061                     : resizable.maxh - geometry.extents.top - geometry.extents.bottom,
1062             0, 0, 0, 0, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST
1063         };
1064         gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom,
1065                 static_cast<GdkWindowHints> (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE));
1066     }
1067 }
1068 
1069 void WindowContextTop::set_window_resizable(bool res) {
1070     if(!res) {
1071         int w = geometry_get_content_width(&geometry);
1072         int h = geometry_get_content_height(&geometry);
1073         if (w == -1 && h == -1) {
1074             gtk_window_get_size(GTK_WINDOW(gtk_widget), &w, &h);
1075         }
1076         GdkGeometry geom = {w, h, w, h, 0, 0, 0, 0, 0.0, 0.0, GDK_GRAVITY_NORTH_WEST};
1077         gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom,
1078                 static_cast<GdkWindowHints>(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE));


1079         resizable.value = false;
1080     } else {

1081         resizable.value = true;
1082         update_window_constraints();



1083     }
1084 }
1085 
1086 void WindowContextTop::set_resizable(bool res) {
1087     resizable.prev = false;
1088     gint w, h;
1089     gtk_window_get_size(GTK_WINDOW(gtk_widget), &w, &h);
1090     if (map_received || w > 1 || h > 1) {
1091         set_window_resizable(res);
1092     } else {
1093         //Since window is not ready yet set only request for change of resizable.
1094         resizable.request  = res ? REQUEST_RESIZABLE : REQUEST_NOT_RESIZABLE;
1095     }
1096 }
1097 
1098 void WindowContextTop::set_visible(bool visible)
1099 {
1100     if (visible) {
1101         if (!size_assigned) {
1102             set_bounds(0, 0, false, false, 320, 200, -1, -1);
1103         }
1104         if (!location_assigned) {
1105             set_bounds(0, 0, true, true, -1, -1, -1, -1);
1106         }
1107     }
1108     WindowContextBase::set_visible(visible);
1109 }
1110 
1111 void WindowContextTop::set_bounds(int x, int y, bool xSet, bool ySet, int w, int h, int cw, int ch) {


1164         windowChangesMask |= CWY;
1165     }
1166 
1167     if (xSet || ySet) location_assigned = true;
1168     if (w > 0 || h > 0 || cw > 0 || ch > 0) size_assigned = true;
1169 
1170     window_configure(&windowChanges, windowChangesMask);
1171 
1172 }
1173 
1174 void WindowContextTop::process_map() {
1175     map_received = true;
1176 }
1177 
1178 void WindowContextTop::window_configure(XWindowChanges *windowChanges,
1179         unsigned int windowChangesMask) {
1180     if (windowChangesMask == 0) {
1181         return;
1182     }
1183 


1184     if (windowChangesMask & (CWX | CWY)) {
1185         gint newX, newY;
1186         gtk_window_get_position(GTK_WINDOW(gtk_widget), &newX, &newY);

1187         if (windowChangesMask & CWX) {
1188             newX = windowChanges->x;
1189         }
1190         if (windowChangesMask & CWY) {
1191             newY = windowChanges->y;
1192         }

1193         gtk_window_move(GTK_WINDOW(gtk_widget), newX, newY);
1194     }
1195 
1196     if (windowChangesMask & (CWWidth | CWHeight)) {
1197         gint newWidth, newHeight;
1198         gtk_window_get_size(GTK_WINDOW(gtk_widget), &newWidth, &newHeight);

1199 
1200         if (windowChangesMask & CWWidth) {
1201             newWidth = windowChanges->width;
1202         }
1203         if (windowChangesMask & CWHeight) {
1204             newHeight = windowChanges->height;
1205         }
1206         if (!resizable.value) {
1207             GdkGeometry geom;
1208             GdkWindowHints hints = (GdkWindowHints)(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
1209             geom.min_width = geom.max_width = newWidth;
1210             geom.min_height = geom.max_height = newHeight;
1211             gtk_window_set_geometry_hints(GTK_WINDOW(gtk_widget), NULL, &geom, hints);






































1212         }
1213         gtk_window_resize(GTK_WINDOW(gtk_widget), newWidth, newHeight);
1214     }





1215 }
1216 
1217 void WindowContextTop::applyShapeMask(void* data, uint width, uint height)
1218 {
1219     if (frame_type != TRANSPARENT) {
1220         return;
1221     }
1222 
1223     glass_window_apply_shape_mask(gtk_widget_get_window(gtk_widget), data, width, height);
1224 }
1225 
1226 void WindowContextTop::ensure_window_size() {
1227     gint w, h;
1228 #ifdef GLASS_GTK3
1229     gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h);
1230 #else
1231     gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL);
1232 #endif
1233     if (size_assigned && (geometry.final_width.value != w
1234                        || geometry.final_height.value != h)) {
1235 
1236         gdk_window_resize(gdk_window, geometry.final_width.value,
1237                                       geometry.final_height.value);
1238     }
1239 }
1240 
1241 void WindowContextTop::set_minimized(bool minimize) {
1242     is_iconified = minimize;
1243     if (minimize) {
1244         if (frame_type == TRANSPARENT) {
1245             // https://bugs.launchpad.net/ubuntu/+source/unity/+bug/1245571
1246             glass_window_reset_input_shape_mask(gtk_widget_get_window(gtk_widget));
1247         }
1248 
1249         if ((gdk_windowManagerFunctions & GDK_FUNC_MINIMIZE) == 0) {
1250             // in this case - the window manager will not support the programatic
1251             // request to iconify - so we need to disable this until we are restored.
1252             GdkWMFunction wmf = (GdkWMFunction)(gdk_windowManagerFunctions | GDK_FUNC_MINIMIZE);
1253             gdk_window_set_functions(gdk_window, wmf);
1254         }
1255         gtk_window_iconify(GTK_WINDOW(gtk_widget));
1256     } else {
1257         gtk_window_deiconify(GTK_WINDOW(gtk_widget));
1258         activate_window();
1259     }
1260 }
1261 void WindowContextTop::set_maximized(bool maximize) {
1262     is_maximized = maximize;
1263     if (maximize) {
1264         ensure_window_size();
1265         gtk_window_maximize(GTK_WINDOW(gtk_widget));
1266     } else {
1267         gtk_window_unmaximize(GTK_WINDOW(gtk_widget));
1268     }
1269 }
1270 
1271 void WindowContextTop::enter_fullscreen() {
1272     ensure_window_size();
1273     gtk_window_fullscreen(GTK_WINDOW(gtk_widget));
1274 }
1275 
1276 void WindowContextTop::exit_fullscreen() {
1277     gtk_window_unfullscreen(GTK_WINDOW(gtk_widget));
1278 }
1279 
1280 void WindowContextTop::request_focus() {
1281     gtk_window_present(GTK_WINDOW(gtk_widget));
1282 }
1283 
1284 void WindowContextTop::set_focusable(bool focusable) {
1285     gtk_window_set_accept_focus(GTK_WINDOW(gtk_widget), focusable ? TRUE : FALSE);
1286 }
1287 
1288 void WindowContextTop::set_title(const char* title) {
1289     gtk_window_set_title(GTK_WINDOW(gtk_widget),title);
1290 }
1291 
1292 void WindowContextTop::set_alpha(double alpha) {
1293     gtk_window_set_opacity(GTK_WINDOW(gtk_widget), (gdouble)alpha);
1294 }
1295 
1296 void WindowContextTop::set_enabled(bool enabled) {
1297     if (enabled) {
1298         if (resizable.prev) {
1299             set_window_resizable(true);
1300         }
1301     } else {
1302         if (resizable.value) {
1303             set_window_resizable(false);
1304             resizable.prev = true;
1305         } else if (resizable.request == REQUEST_RESIZABLE) {
1306             resizable.request = REQUEST_NOT_RESIZABLE;
1307             resizable.prev = true;
1308         }
1309     }
1310 }
1311 
1312 void WindowContextTop::set_minimum_size(int w, int h) {
1313     resizable.minw = w;
1314     resizable.minh = h;
1315     update_window_constraints();
1316 }
1317 
1318 void WindowContextTop::set_maximum_size(int w, int h) {
1319     resizable.maxw = w;
1320     resizable.maxh = h;
1321     update_window_constraints();
1322 }
1323 
1324 void WindowContextTop::set_icon(GdkPixbuf* pixbuf) {
1325     gtk_window_set_icon(GTK_WINDOW(gtk_widget), pixbuf);
1326 }
1327 
1328 void WindowContextTop::restack(bool restack) {


1428     WindowContextBase::process_destroy();
1429 }
1430 
1431 ////////////////////////////// WindowContextPlug ////////////////////////////////
1432 
1433 static gboolean plug_configure(GtkWidget *widget, GdkEvent *event, gpointer user_data) {
1434     (void)widget;
1435 
1436     if (event->type == GDK_CONFIGURE) {
1437         ((WindowContextPlug*)user_data)->process_gtk_configure(&event->configure);
1438     }
1439     return FALSE;
1440 }
1441 
1442 WindowContextPlug::WindowContextPlug(jobject _jwindow, void* _owner) :
1443         WindowContextBase(),
1444         parent()
1445 {
1446     jwindow = mainEnv->NewGlobalRef(_jwindow);
1447 
1448     WindowContext* parent = ((WindowContext*)JLONG_TO_PTR(_owner));
1449     Window win = GDK_WINDOW_XID(parent->get_gdk_window());
1450     gtk_widget = gtk_plug_new(win);
1451 
1452     g_signal_connect(G_OBJECT(gtk_widget), "configure-event", G_CALLBACK(plug_configure), this);
1453 
1454     gtk_widget_set_size_request(gtk_widget, 0, 0);
1455     gtk_widget_set_events(gtk_widget, GDK_ALL_EVENTS_MASK);
1456     gtk_widget_set_can_focus(GTK_WIDGET(gtk_widget), TRUE);
1457     gtk_widget_set_app_paintable(gtk_widget, TRUE);
1458 
1459     gtk_widget_realize(gtk_widget);
1460     gdk_window = gtk_widget_get_window(gtk_widget);
1461 
1462     g_object_set_data_full(G_OBJECT(gdk_window), GDK_WINDOW_DATA_CONTEXT, this, NULL);
1463     gdk_window_register_dnd(gdk_window);
1464 
1465     gtk_container = gtk_fixed_new();
1466     gtk_container_add (GTK_CONTAINER(gtk_widget), gtk_container);
1467     gtk_widget_realize(gtk_container);
1468 }
1469 
1470 GtkWindow *WindowContextPlug::get_gtk_window() {


1663 
1664     gtk_widget_set_size_request(gtk_widget, event->width, event->height);
1665 
1666     if (jwindow) {
1667         mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize,
1668                 com_sun_glass_events_WindowEvent_RESIZE,
1669                 event->width,
1670                 event->height);
1671         CHECK_JNI_EXCEPTION(mainEnv)
1672     }
1673 }
1674 
1675 bool WindowContextChild::set_view(jobject view) {
1676     if (jview) {
1677         mainEnv->DeleteGlobalRef(jview);
1678     }
1679 
1680     if (view) {
1681         gint width, height;
1682         jview = mainEnv->NewGlobalRef(view);
1683         GtkAllocation ws;
1684         gtk_widget_get_allocation(gtk_widget, &ws);
1685         width = ws.width;
1686         height = ws.height;
1687         mainEnv->CallVoidMethod(view, jViewNotifyResize, width, height);
1688         CHECK_JNI_EXCEPTION_RET(mainEnv, FALSE)
1689     } else {
1690         jview = NULL;
1691     }
1692     return TRUE;
1693 }
1694 
1695 void WindowContextChild::set_bounds(int x, int y, bool xSet, bool ySet, int w, int h, int cw, int ch) {
1696 
1697     if (x > 0 || y > 0 || xSet || ySet) {
1698         gint newX, newY;
1699         gdk_window_get_origin(gdk_window, &newX, &newY);
1700         if (jwindow) {
1701             mainEnv->CallVoidMethod(jwindow,
1702                     jWindowNotifyMove,
1703                     newX, newY);
1704             CHECK_JNI_EXCEPTION(mainEnv)
1705         }
1706     }
1707 
1708     // As we have no frames, there's no difference between the calls
1709     if ((cw | ch) > 0) {
1710         w = cw; h = ch;
1711     }
1712 
1713     if (w > 0 || h > 0) {
1714         gint newWidth, newHeight;
1715         GtkAllocation ws;
1716         gtk_widget_get_allocation(gtk_widget, &ws);
1717         newWidth = ws.width;
1718         newHeight = ws.height;
1719 
1720         if (w > 0) {
1721             newWidth = w;
1722         }
1723         if (h > 0) {
1724             newHeight = h;
1725         }
1726         gtk_widget_set_size_request(gtk_widget, newWidth, newHeight);
1727         // FIXME: hack to set correct size to view
1728         if (jview) {
1729             mainEnv->CallVoidMethod(jview,
1730                     jViewNotifyResize,
1731                     newWidth, newHeight);
1732             CHECK_JNI_EXCEPTION(mainEnv)
1733         }
1734     }
1735 }
1736 
1737 int WindowContextChild::getEmbeddedX() {
1738     int x;


1756 
1757     embedded_children.erase(pos);
1758     if (toFront) {
1759         embedded_children.push_back(this);
1760     } else {
1761         embedded_children.insert(embedded_children.begin(), this);
1762     }
1763 
1764     gdk_window_restack(gdk_window, NULL, toFront ? TRUE : FALSE);
1765 }
1766 
1767 void WindowContextChild::enter_fullscreen() {
1768     if (full_screen_window) {
1769         return;
1770     }
1771 
1772     full_screen_window = new WindowContextTop(jwindow, NULL, 0L, UNTITLED,
1773                                                 NORMAL, (GdkWMFunction) 0);
1774     int x, y, w, h;
1775     gdk_window_get_origin(gdk_window, &x, &y);
1776 #ifdef GLASS_GTK3
1777     gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h);
1778 #else
1779     gdk_window_get_geometry(gdk_window, NULL, NULL, &w, &h, NULL);
1780 #endif
1781     full_screen_window->set_bounds(x, y, true, true, w, h, -1, -1);
1782 
1783     if (WindowContextBase::sm_grab_window == this) {
1784         ungrab_focus();
1785     }
1786 
1787     reparent_children(full_screen_window);
1788 
1789     full_screen_window->set_visible(true);
1790     full_screen_window->enter_fullscreen();
1791 
1792     if (jwindow) {
1793         mainEnv->CallVoidMethod(jwindow, jWindowNotifyDelegatePtr, (jlong)full_screen_window);
1794         CHECK_JNI_EXCEPTION(mainEnv)
1795     }
1796 
1797     if (jview) {
1798         this->view = (GlassView*)mainEnv->GetLongField(jview, jViewPtr);
1799 
1800         this->view->current_window = full_screen_window;


< prev index next >