1 /* 2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 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 #ifndef GLASS_WINDOW_H 26 #define GLASS_WINDOW_H 27 28 #include <gtk/gtk.h> 29 #include <X11/Xlib.h> 30 31 #include <jni.h> 32 #include <set> 33 #include <vector> 34 35 #include "glass_view.h" 36 37 enum WindowFrameType { 38 TITLED, 39 UNTITLED, 40 TRANSPARENT 41 }; 42 43 enum WindowType { 44 NORMAL, 45 UTILITY, 46 POPUP 47 }; 48 49 enum request_type { 50 REQUEST_NONE, 51 REQUEST_RESIZABLE, 52 REQUEST_NOT_RESIZABLE 53 }; 54 55 struct WindowFrameExtents { 56 int top; 57 int left; 58 int bottom; 59 int right; 60 }; 61 62 static const guint MOUSE_BUTTONS_MASK = (guint) (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK); 63 64 enum BoundsType { 65 BOUNDSTYPE_CONTENT, 66 BOUNDSTYPE_WINDOW 67 }; 68 69 struct WindowGeometry { 70 WindowGeometry(): final_width(), final_height(), 71 refx(), refy(), gravity_x(), gravity_y(), current_width(), current_height(), extents() {} 72 // estimate of the final width the window will get after all pending 73 // configure requests are processed by the window manager 74 struct { 75 int value; 76 BoundsType type; 77 } final_width; 78 79 struct { 80 int value; 81 BoundsType type; 82 } final_height; 83 84 float refx; 85 float refy; 86 float gravity_x; 87 float gravity_y; 88 89 // the last width which was configured or obtained from configure 90 // notification 91 int current_width; 92 93 // the last height which was configured or obtained from configure 94 // notification 95 int current_height; 96 97 WindowFrameExtents extents; 98 99 }; 100 101 class WindowContextChild; 102 class WindowContextTop; 103 104 class WindowContext { 105 public: 106 virtual bool isEnabled() = 0; 107 virtual bool hasIME() = 0; 108 virtual bool filterIME(GdkEvent *) = 0; 109 virtual void enableOrResetIME() = 0; 110 virtual void disableIME() = 0; 111 virtual void paint(void* data, jint width, jint height) = 0; 112 virtual WindowFrameExtents get_frame_extents() = 0; 113 114 virtual void enter_fullscreen() = 0; 115 virtual void exit_fullscreen() = 0; 116 virtual void show_or_hide_children(bool) = 0; 117 virtual void set_visible(bool) = 0; 118 virtual bool is_visible() = 0; 119 virtual void set_bounds(int, int, bool, bool, int, int, int, int) = 0; 120 virtual void set_resizable(bool) = 0; 121 virtual void request_focus() = 0; 122 virtual void set_focusable(bool)= 0; 123 virtual bool grab_focus() = 0; 124 virtual bool grab_mouse_drag_focus() = 0; 125 virtual void ungrab_focus() = 0; 126 virtual void ungrab_mouse_drag_focus() = 0; 127 virtual void set_title(const char*) = 0; 128 virtual void set_alpha(double) = 0; 129 virtual void set_enabled(bool) = 0; 130 virtual void set_minimum_size(int, int) = 0; 131 virtual void set_maximum_size(int, int) = 0; 132 virtual void set_minimized(bool) = 0; 133 virtual void set_maximized(bool) = 0; 134 virtual void set_icon(GdkPixbuf*) = 0; 135 virtual void restack(bool) = 0; 136 virtual void set_cursor(GdkCursor*) = 0; 137 virtual void set_modal(bool, WindowContext* parent = NULL) = 0; 138 virtual void set_gravity(float, float) = 0; 139 virtual void set_level(int) = 0; 140 virtual void set_background(float, float, float) = 0; 141 142 virtual void process_property_notify(GdkEventProperty*) = 0; 143 virtual void process_configure(GdkEventConfigure*) = 0; 144 virtual void process_map() = 0; 145 virtual void process_focus(GdkEventFocus*) = 0; 146 virtual void process_destroy() = 0; 147 virtual void process_delete() = 0; 148 virtual void process_expose(GdkEventExpose*) = 0; 149 virtual void process_mouse_button(GdkEventButton*) = 0; 150 virtual void process_mouse_motion(GdkEventMotion*) = 0; 151 virtual void process_mouse_scroll(GdkEventScroll*) = 0; 152 virtual void process_mouse_cross(GdkEventCrossing*) = 0; 153 virtual void process_key(GdkEventKey*) = 0; 154 virtual void process_state(GdkEventWindowState*) = 0; 155 156 virtual void notify_state(jint) = 0; 157 virtual void notify_on_top(bool) {} 158 159 virtual void add_child(WindowContextTop* child) = 0; 160 virtual void remove_child(WindowContextTop* child) = 0; 161 virtual bool set_view(jobject) = 0; 162 163 virtual GdkWindow *get_gdk_window() = 0; 164 virtual GtkWindow *get_gtk_window() = 0; 165 virtual jobject get_jview() = 0; 166 virtual jobject get_jwindow() = 0; 167 168 virtual int getEmbeddedX() = 0; 169 virtual int getEmbeddedY() = 0; 170 171 172 virtual void increment_events_counter() = 0; 173 virtual void decrement_events_counter() = 0; 174 virtual size_t get_events_count() = 0; 175 virtual bool is_dead() = 0; 176 virtual ~WindowContext() {} 177 }; 178 179 class WindowContextBase: public WindowContext { 180 181 struct _XIM{ 182 XIM im; 183 XIC ic; 184 bool enabled; 185 } xim; 186 187 size_t events_processing_cnt; 188 bool can_be_deleted; 189 protected: 190 std::set<WindowContextTop*> children; 191 jobject jwindow; 192 jobject jview; 193 GtkWidget* gtk_widget; 194 GdkWindow* gdk_window; 195 GdkWMFunction gdk_windowManagerFunctions; 196 197 bool is_iconified; 198 bool is_maximized; 199 bool is_mouse_entered; 200 201 /* 202 * sm_grab_window points to WindowContext holding a mouse grab. 203 * It is mostly used for popup windows. 204 */ 205 static WindowContext* sm_grab_window; 206 207 /* 208 * sm_mouse_drag_window points to a WindowContext from which a mouse drag started. 209 * This WindowContext holding a mouse grab during this drag. After releasing 210 * all mouse buttons sm_mouse_drag_window becomes NULL and sm_grab_window's 211 * mouse grab should be restored if present. 212 * 213 * This is done in order to mimic Windows behavior: 214 * All mouse events should be delivered to a window from which mouse drag 215 * started, until all mouse buttons released. No mouse ENTER/EXIT events 216 * should be reported during this drag. 217 */ 218 static WindowContext* sm_mouse_drag_window; 219 public: 220 bool isEnabled(); 221 bool hasIME(); 222 bool filterIME(GdkEvent *); 223 void enableOrResetIME(); 224 void disableIME(); 225 void paint(void*, jint, jint); 226 GdkWindow *get_gdk_window(); 227 jobject get_jwindow(); 228 jobject get_jview(); 229 230 void add_child(WindowContextTop*); 231 void remove_child(WindowContextTop*); 232 void show_or_hide_children(bool); 233 void reparent_children(WindowContext* parent); 234 void set_visible(bool); 235 bool is_visible(); 236 bool set_view(jobject); 237 bool grab_focus(); 238 bool grab_mouse_drag_focus(); 239 void ungrab_focus(); 240 void ungrab_mouse_drag_focus(); 241 void set_cursor(GdkCursor*); 242 void set_level(int) {} 243 void set_background(float, float, float); 244 245 void process_map() {} 246 void process_focus(GdkEventFocus*); 247 void process_destroy(); 248 void process_delete(); 249 void process_expose(GdkEventExpose*); 250 void process_mouse_button(GdkEventButton*); 251 void process_mouse_motion(GdkEventMotion*); 252 void process_mouse_scroll(GdkEventScroll*); 253 void process_mouse_cross(GdkEventCrossing*); 254 void process_key(GdkEventKey*); 255 void process_state(GdkEventWindowState*); 256 257 void notify_state(jint); 258 259 int getEmbeddedX() { return 0; } 260 int getEmbeddedY() { return 0; } 261 262 void increment_events_counter(); 263 void decrement_events_counter(); 264 size_t get_events_count(); 265 bool is_dead(); 266 267 ~WindowContextBase(); 268 protected: 269 virtual void applyShapeMask(void*, uint width, uint height) = 0; 270 private: 271 bool im_filter_keypress(GdkEventKey*); 272 }; 273 274 class WindowContextPlug: public WindowContextBase { 275 WindowContext* parent; 276 public: 277 bool set_view(jobject); 278 void set_bounds(int, int, bool, bool, int, int, int, int); 279 //WindowFrameExtents get_frame_extents() { return WindowFrameExtents{0, 0, 0, 0}; }; 280 WindowFrameExtents get_frame_extents() { WindowFrameExtents ext = {0, 0, 0, 0}; return ext;} 281 282 void enter_fullscreen() {} 283 void exit_fullscreen() {} 284 void set_resizable(bool) {} 285 void request_focus() {} 286 void set_focusable(bool) {} 287 void set_title(const char*) {} 288 void set_alpha(double) {} 289 void set_enabled(bool) {} 290 void set_minimum_size(int, int) {} 291 void set_maximum_size(int, int) {} 292 void set_minimized(bool) {} 293 void set_maximized(bool) {} 294 void set_icon(GdkPixbuf*) {} 295 void restack(bool) {} 296 void set_modal(bool, WindowContext*) {} 297 void set_gravity(float, float) {} 298 void process_property_notify(GdkEventProperty*) {} 299 void process_configure(GdkEventConfigure*); 300 void process_gtk_configure(GdkEventConfigure*); 301 302 void applyShapeMask(void*, uint width, uint height) { 303 (void)width; 304 (void)height; 305 } 306 GtkWindow *get_gtk_window(); // TODO, get window from parent 307 308 WindowContextPlug(jobject, void*); 309 GtkWidget* gtk_container; 310 std::vector<WindowContextChild *> embedded_children; 311 private: 312 //HACK: remove once set_bounds is implemented correctly 313 void window_configure(XWindowChanges *, unsigned int); 314 WindowContextPlug(WindowContextPlug&); 315 WindowContextPlug& operator= (const WindowContextPlug&); 316 }; 317 318 class WindowContextChild: public WindowContextBase { 319 WindowContextPlug* parent; 320 WindowContextTop* full_screen_window; 321 GlassView* view; // not null while in Full Screen 322 public: 323 void process_mouse_button(GdkEventButton*); 324 bool set_view(jobject); 325 void set_bounds(int, int, bool, bool, int, int, int, int); 326 //WindowFrameExtents get_frame_extents() { return WindowFrameExtents{0, 0, 0, 0}; }; 327 WindowFrameExtents get_frame_extents() { WindowFrameExtents ext = {0, 0, 0, 0}; return ext;} 328 329 void enter_fullscreen(); 330 void exit_fullscreen(); 331 void set_resizable(bool) {} 332 void request_focus() {} 333 void set_focusable(bool) {} 334 void set_title(const char*) {} 335 void set_alpha(double) {} 336 void set_enabled(bool) {} 337 void set_minimum_size(int, int) {} 338 void set_maximum_size(int, int) {} 339 void set_minimized(bool) {} 340 void set_maximized(bool) {} 341 void set_icon(GdkPixbuf*) {} 342 void restack(bool); 343 void set_modal(bool, WindowContext*) {} 344 void set_gravity(float, float) {} 345 void process_property_notify(GdkEventProperty*) {} 346 void process_configure(GdkEventConfigure*); 347 void process_destroy(); 348 void set_visible(bool visible); 349 350 int getEmbeddedX(); 351 int getEmbeddedY(); 352 353 void applyShapeMask(void*, uint width, uint height) { 354 (void)width; 355 (void)height; 356 } 357 GtkWindow *get_gtk_window(); // TODO, get window from parent 358 359 WindowContextChild(jobject, void*, GtkWidget *parent_widget, WindowContextPlug *parent_context); 360 private: 361 WindowContextChild(WindowContextChild&); 362 WindowContextChild& operator= (const WindowContextChild&); 363 }; 364 365 class WindowContextTop: public WindowContextBase { 366 jlong screen; 367 WindowFrameType frame_type; 368 struct WindowContext *owner; 369 WindowGeometry geometry; 370 int stale_config_notifications; 371 struct _Resizable{// we can't use set/get gtk_window_resizable function 372 _Resizable(): request(REQUEST_NONE), value(true), prev(false), 373 minw(-1), minh(-1), maxw(-1), maxh(-1){} 374 request_type request; //request for future setResizable 375 bool value; //actual value of resizable for a window 376 bool prev; //former resizable value (used in setEnabled for parents of modal window) 377 int minw, minh, maxw, maxh; //minimum and maximum window width/height; 378 } resizable; 379 380 bool frame_extents_initialized; 381 bool map_received; 382 bool location_assigned; 383 bool size_assigned; 384 bool on_top; 385 public: 386 WindowContextTop(jobject, WindowContext*, long, WindowFrameType, WindowType, GdkWMFunction); 387 void process_map(); 388 void process_property_notify(GdkEventProperty*); 389 void process_configure(GdkEventConfigure*); 390 void process_destroy(); 391 void process_net_wm_property(); 392 393 WindowFrameExtents get_frame_extents(); 394 395 void set_minimized(bool); 396 void set_maximized(bool); 397 void set_bounds(int, int, bool, bool, int, int, int, int); 398 void set_resizable(bool); 399 void request_focus(); 400 void set_focusable(bool); 401 void set_title(const char*); 402 void set_alpha(double); 403 void set_enabled(bool); 404 void set_minimum_size(int, int); 405 void set_maximum_size(int, int); 406 void set_icon(GdkPixbuf*); 407 void restack(bool); 408 void set_modal(bool, WindowContext* parent = NULL); 409 void set_gravity(float, float); 410 void set_level(int); 411 void set_visible(bool); 412 void notify_on_top(bool); 413 414 void enter_fullscreen(); 415 void exit_fullscreen(); 416 417 void set_owner(WindowContext*); 418 419 GtkWindow *get_gtk_window(); 420 void detach_from_java(); 421 protected: 422 void applyShapeMask(void*, uint width, uint height); 423 private: 424 bool get_frame_extents_property(int *, int *, int *, int *); 425 void request_frame_extents(); 426 void activate_window(); 427 void initialize_frame_extents(); 428 void window_configure(XWindowChanges *, unsigned int); 429 void update_window_constraints(); 430 void set_window_resizable(bool, bool); 431 void update_ontop_tree(bool); 432 bool on_top_inherited(); 433 bool effective_on_top(); 434 WindowContextTop(WindowContextTop&); 435 WindowContextTop& operator= (const WindowContextTop&); 436 }; 437 438 void destroy_and_delete_ctx(WindowContext* ctx); 439 440 class EventsCounterHelper { 441 private: 442 WindowContext* ctx; 443 public: 444 explicit EventsCounterHelper(WindowContext* context) { 445 ctx = context; 446 ctx->increment_events_counter(); 447 } 448 ~EventsCounterHelper() { 449 ctx->decrement_events_counter(); 450 if (ctx->is_dead() && ctx->get_events_count() == 0) { 451 delete ctx; 452 } 453 ctx = NULL; 454 } 455 }; 456 457 #endif /* GLASS_WINDOW_H */ 458