103 (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_MAXIMIZED)) { 104 105 if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) { 106 is_iconified = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED; 107 } 108 if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) { 109 is_maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; 110 } 111 112 jint stateChangeEvent; 113 114 if (is_iconified) { 115 stateChangeEvent = com_sun_glass_events_WindowEvent_MINIMIZE; 116 } else if (is_maximized) { 117 stateChangeEvent = com_sun_glass_events_WindowEvent_MAXIMIZE; 118 } else { 119 stateChangeEvent = com_sun_glass_events_WindowEvent_RESTORE; 120 } 121 122 notify_state(stateChangeEvent); 123 } 124 } 125 126 void WindowContextBase::process_focus(GdkEventFocus* event) { 127 if (!event->in && WindowContextBase::sm_mouse_drag_window == this) { 128 ungrab_mouse_drag_focus(); 129 } 130 if (!event->in && WindowContextBase::sm_grab_window == this) { 131 ungrab_focus(); 132 } 133 if (jwindow) { 134 if (!event->in || isEnabled()) { 135 mainEnv->CallVoidMethod(jwindow, jWindowNotifyFocus, 136 event->in ? com_sun_glass_events_WindowEvent_FOCUS_GAINED : com_sun_glass_events_WindowEvent_FOCUS_LOST); 137 CHECK_JNI_EXCEPTION(mainEnv) 138 } else { 139 mainEnv->CallVoidMethod(jwindow, jWindowNotifyFocusDisabled); 140 CHECK_JNI_EXCEPTION(mainEnv) 141 } 142 } 802 newValue += geometry_get_window_width(windowGeometry) 803 * windowGeometry->gravity_x; 804 } 805 windowGeometry->refx = newValue; 806 } 807 808 static void geometry_set_window_y(WindowGeometry *windowGeometry, int value) { 809 float newValue = value; 810 if (windowGeometry->gravity_y != 0) { 811 newValue += geometry_get_window_height(windowGeometry) 812 * windowGeometry->gravity_y; 813 } 814 windowGeometry->refy = newValue; 815 } 816 817 void WindowContextTop::process_net_wm_property() { 818 // Workaround for https://bugs.launchpad.net/unity/+bug/998073 819 820 static GdkAtom atom_atom = gdk_atom_intern_static_string("ATOM"); 821 static GdkAtom atom_net_wm_state_hidden = gdk_atom_intern_static_string("_NET_WM_STATE_HIDDEN"); 822 823 gint length; 824 825 GdkAtom* atoms = NULL; 826 827 if (gdk_property_get(gdk_window, atom_net_wm_state, atom_atom, 828 0, G_MAXLONG, FALSE, NULL, NULL, &length, (guchar**) &atoms)) { 829 830 gint i = 0; 831 bool is_hidden = false; 832 while (i < length) { 833 if (atom_net_wm_state_hidden == atoms[i]) { 834 is_hidden = true; 835 break; 836 } 837 838 i++; 839 } 840 841 g_free(atoms); 842 843 if (is_iconified != is_hidden) { 844 is_iconified = is_hidden; 845 846 notify_state((is_hidden) 847 ? com_sun_glass_events_WindowEvent_MINIMIZE 848 : com_sun_glass_events_WindowEvent_RESTORE); 849 } 850 } 851 } 852 853 void WindowContextTop::process_property_notify(GdkEventProperty* event) { 854 if (event->atom == atom_net_wm_state && event->window == gdk_window) { 855 process_net_wm_property(); 856 } else if (event->atom == get_net_frame_extents_atom() && 857 event->window == gdk_window) { 858 int top, left, bottom, right; 859 if (get_frame_extents_property(&top, &left, &bottom, &right)) { 860 int oldX = geometry_get_window_x(&geometry); 861 int oldY = geometry_get_window_y(&geometry); 862 int oldWidth = geometry_get_content_width(&geometry); 863 int oldHeight = geometry_get_content_height(&geometry); 864 865 bool updateWindowConstraints = geometry.extents.top != top 866 || geometry.extents.left != left 867 || geometry.extents.bottom != bottom 868 || geometry.extents.right != right; 869 1323 1324 void WindowContextTop::update_ontop_tree(bool on_top) { 1325 bool effective_on_top = on_top || this->on_top; 1326 gtk_window_set_keep_above(GTK_WINDOW(gtk_widget), effective_on_top ? TRUE : FALSE); 1327 for (std::set<WindowContextTop*>::iterator it = children.begin(); it != children.end(); ++it) { 1328 (*it)->update_ontop_tree(effective_on_top); 1329 } 1330 } 1331 1332 bool WindowContextTop::on_top_inherited() { 1333 WindowContext* o = owner; 1334 while (o) { 1335 WindowContextTop* topO = dynamic_cast<WindowContextTop*>(o); 1336 if (!topO) break; 1337 if (topO->on_top) { 1338 return true; 1339 } 1340 o = topO->owner; 1341 } 1342 return false; 1343 } 1344 1345 void WindowContextTop::set_level(int level) { 1346 if (level == com_sun_glass_ui_Window_Level_NORMAL) { 1347 on_top = false; 1348 } else if (level == com_sun_glass_ui_Window_Level_FLOATING 1349 || level == com_sun_glass_ui_Window_Level_TOPMOST) { 1350 on_top = true; 1351 } 1352 // We need to emulate always on top behaviour on child windows 1353 1354 if (!on_top_inherited()) { 1355 update_ontop_tree(on_top); 1356 } 1357 } 1358 1359 void WindowContextTop::set_owner(WindowContext * owner_ctx) { 1360 owner = owner_ctx; 1361 } 1362 | 103 (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_MAXIMIZED)) { 104 105 if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) { 106 is_iconified = event->new_window_state & GDK_WINDOW_STATE_ICONIFIED; 107 } 108 if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) { 109 is_maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; 110 } 111 112 jint stateChangeEvent; 113 114 if (is_iconified) { 115 stateChangeEvent = com_sun_glass_events_WindowEvent_MINIMIZE; 116 } else if (is_maximized) { 117 stateChangeEvent = com_sun_glass_events_WindowEvent_MAXIMIZE; 118 } else { 119 stateChangeEvent = com_sun_glass_events_WindowEvent_RESTORE; 120 } 121 122 notify_state(stateChangeEvent); 123 } else if (event->changed_mask & GDK_WINDOW_STATE_ABOVE) { 124 notify_on_top( event->new_window_state & GDK_WINDOW_STATE_ABOVE); 125 } 126 } 127 128 void WindowContextBase::process_focus(GdkEventFocus* event) { 129 if (!event->in && WindowContextBase::sm_mouse_drag_window == this) { 130 ungrab_mouse_drag_focus(); 131 } 132 if (!event->in && WindowContextBase::sm_grab_window == this) { 133 ungrab_focus(); 134 } 135 if (jwindow) { 136 if (!event->in || isEnabled()) { 137 mainEnv->CallVoidMethod(jwindow, jWindowNotifyFocus, 138 event->in ? com_sun_glass_events_WindowEvent_FOCUS_GAINED : com_sun_glass_events_WindowEvent_FOCUS_LOST); 139 CHECK_JNI_EXCEPTION(mainEnv) 140 } else { 141 mainEnv->CallVoidMethod(jwindow, jWindowNotifyFocusDisabled); 142 CHECK_JNI_EXCEPTION(mainEnv) 143 } 144 } 804 newValue += geometry_get_window_width(windowGeometry) 805 * windowGeometry->gravity_x; 806 } 807 windowGeometry->refx = newValue; 808 } 809 810 static void geometry_set_window_y(WindowGeometry *windowGeometry, int value) { 811 float newValue = value; 812 if (windowGeometry->gravity_y != 0) { 813 newValue += geometry_get_window_height(windowGeometry) 814 * windowGeometry->gravity_y; 815 } 816 windowGeometry->refy = newValue; 817 } 818 819 void WindowContextTop::process_net_wm_property() { 820 // Workaround for https://bugs.launchpad.net/unity/+bug/998073 821 822 static GdkAtom atom_atom = gdk_atom_intern_static_string("ATOM"); 823 static GdkAtom atom_net_wm_state_hidden = gdk_atom_intern_static_string("_NET_WM_STATE_HIDDEN"); 824 static GdkAtom atom_net_wm_state_above = gdk_atom_intern_static_string("_NET_WM_STATE_ABOVE"); 825 826 gint length; 827 828 GdkAtom* atoms = NULL; 829 830 if (gdk_property_get(gdk_window, atom_net_wm_state, atom_atom, 831 0, G_MAXLONG, FALSE, NULL, NULL, &length, (guchar**) &atoms)) { 832 833 gint i = 0; 834 bool is_hidden = false; 835 bool is_above = false; 836 while (i < length) { 837 if (atom_net_wm_state_hidden == atoms[i]) { 838 is_hidden = true; 839 } else if (atom_net_wm_state_above == atoms[i]) { 840 is_above = true; 841 } 842 i++; 843 } 844 845 g_free(atoms); 846 847 if (is_iconified != is_hidden) { 848 is_iconified = is_hidden; 849 850 notify_state((is_hidden) 851 ? com_sun_glass_events_WindowEvent_MINIMIZE 852 : com_sun_glass_events_WindowEvent_RESTORE); 853 } 854 855 notify_on_top(is_above); 856 } 857 } 858 859 void WindowContextTop::process_property_notify(GdkEventProperty* event) { 860 if (event->atom == atom_net_wm_state && event->window == gdk_window) { 861 process_net_wm_property(); 862 } else if (event->atom == get_net_frame_extents_atom() && 863 event->window == gdk_window) { 864 int top, left, bottom, right; 865 if (get_frame_extents_property(&top, &left, &bottom, &right)) { 866 int oldX = geometry_get_window_x(&geometry); 867 int oldY = geometry_get_window_y(&geometry); 868 int oldWidth = geometry_get_content_width(&geometry); 869 int oldHeight = geometry_get_content_height(&geometry); 870 871 bool updateWindowConstraints = geometry.extents.top != top 872 || geometry.extents.left != left 873 || geometry.extents.bottom != bottom 874 || geometry.extents.right != right; 875 1329 1330 void WindowContextTop::update_ontop_tree(bool on_top) { 1331 bool effective_on_top = on_top || this->on_top; 1332 gtk_window_set_keep_above(GTK_WINDOW(gtk_widget), effective_on_top ? TRUE : FALSE); 1333 for (std::set<WindowContextTop*>::iterator it = children.begin(); it != children.end(); ++it) { 1334 (*it)->update_ontop_tree(effective_on_top); 1335 } 1336 } 1337 1338 bool WindowContextTop::on_top_inherited() { 1339 WindowContext* o = owner; 1340 while (o) { 1341 WindowContextTop* topO = dynamic_cast<WindowContextTop*>(o); 1342 if (!topO) break; 1343 if (topO->on_top) { 1344 return true; 1345 } 1346 o = topO->owner; 1347 } 1348 return false; 1349 } 1350 1351 bool WindowContextTop::effective_on_top() { 1352 if (owner) { 1353 WindowContextTop* topO = dynamic_cast<WindowContextTop*>(owner); 1354 return (topO && topO->effective_on_top()) || on_top; 1355 } 1356 return on_top; 1357 } 1358 1359 void WindowContextTop::notify_on_top(bool top) { 1360 // Do not report effective (i.e. native) values to the FX, only if the user sets it manually 1361 if (top != effective_on_top() && jwindow) { 1362 if (on_top_inherited() && !top) { 1363 // Disallow user's "on top" handling on windows that inherited the property 1364 gtk_window_set_keep_above(GTK_WINDOW(gtk_widget), TRUE); 1365 } else { 1366 on_top = top; 1367 update_ontop_tree(top); 1368 mainEnv->CallVoidMethod(jwindow, 1369 jWindowNotifyLevelChanged, 1370 top ? com_sun_glass_ui_Window_Level_FLOATING : com_sun_glass_ui_Window_Level_NORMAL); 1371 CHECK_JNI_EXCEPTION(mainEnv); 1372 } 1373 } 1374 } 1375 1376 void WindowContextTop::set_level(int level) { 1377 if (level == com_sun_glass_ui_Window_Level_NORMAL) { 1378 on_top = false; 1379 } else if (level == com_sun_glass_ui_Window_Level_FLOATING 1380 || level == com_sun_glass_ui_Window_Level_TOPMOST) { 1381 on_top = true; 1382 } 1383 // We need to emulate always on top behaviour on child windows 1384 1385 if (!on_top_inherited()) { 1386 update_ontop_tree(on_top); 1387 } 1388 } 1389 1390 void WindowContextTop::set_owner(WindowContext * owner_ctx) { 1391 owner = owner_ctx; 1392 } 1393 |